Skip to content

Access violation in boundingRect on arm64 NEON because of reading out of bounds #14863

@rolandpersson

Description

@rolandpersson
System information (version)
  • OpenCV => 4.1
  • Operating System / Platform => iOS 12, arm64
  • Compiler => Xcode 10.2.1
Detailed description

The boundingRect() function will crash if the memory beyond the end of the array of points passed into it is not readable.

Steps to reproduce

It is difficult to produce a simple code sample that reproduces this as it will only actually crash if the memory beyond the end of the array is not readable (which it usually is). I have been able to reproduce it by passing an std::vectorcv::Point with 4096 entries to cv::boundingRect() and enabling the following memory debugging flags in Xcode.

  • Malloc Guard Edges
  • Guard Malloc
More Info

My own understanding of the problem is that vx_load_low on ARM NEON translates to an instruction that reads two 64-bit elements rather than just the low one.

The following lines from pointSetBoundingRect is where the crash occurs:

        if( i <= npoints - v_int32::nlanes/4 )
        {
            v_int32 ptXY = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(vx_load_low(pts + i))));
            minval = v_min(ptXY, minval);
            maxval = v_max(ptXY, maxval);
            i += v_int64::nlanes/2;
        }

When it crashes i == 4095 and a single element remains to read from pts array.

This is the assembly code generated by the compiler:

    0x104fc9774 <+400>: ushll2.2d v1, v1, #0x0
    0x104fc9778 <+404>: smin.4s v1, v2, v1
    0x104fc977c <+408>: ushll.2d v2, v0, #0x0
    0x104fc9780 <+412>: ushll2.2d v0, v0, #0x0
    0x104fc9784 <+416>: smax.4s v0, v2, v0
    0x104fc9788 <+420>: cmp    w9, w0
    0x104fc978c <+424>: b.ge   0x104fc97a4               ; <+448> [inlined] cv::hal_baseline::v_int32x4::get0() const at shapedescr.cpp:778
    0x104fc9790 <+428>: add    x8, x8, w9, uxtw #3
->  0x104fc9794 <+432>: ld2.2d { v2, v3 }, [x8]
    0x104fc9798 <+436>: ushll.2d v2, v2, #0x0
    0x104fc979c <+440>: smin.4s v1, v2, v1
    0x104fc97a0 <+444>: smax.4s v0, v2, v0
    0x104fc97a4 <+448>: fmov   w8, s1
    0x104fc97a8 <+452>: fmov   w9, s0
    0x104fc97ac <+456>: ushll2.2d v1, v1, #0x0

The ld2.2d causes the access violation: Thread 5: EXC_BAD_ACCESS (code=2, address=0x1078d4000)

Here is the register dump:

General Purpose Registers:
        x0 = 0x0000000000001000
        x1 = 0x0000000000000002
        x2 = 0x00000000ffffffff
        x3 = 0x0000000000000001
        x4 = 0x0000000000008000
        x5 = 0x0000000000000003
        x6 = 0x0000000000000000
        x7 = 0x0000000000000000
        x8 = 0x00000001078d3ff8
        x9 = 0x0000000000000fff
       x10 = 0x0000000000000ffc
       x11 = 0x00000001078d3ff8
       x12 = 0x0000000000000fff
       x13 = 0x0000000000000001
       x14 = 0x0000000000000001
       x15 = 0x00000000000000d0
       x16 = 0x000000000000004a
       x17 = 0x000000025f6ce620  (void *)0x000000022ee4e5d4: malloc
       x18 = 0x0000000000000000
       x19 = 0x000000016b434908
       x20 = 0x000000016b434870
       x21 = 0x000000016b43cf58
       x22 = 0x000000016b43cf70
       x23 = 0x000000016b43d0f8
       x24 = 0x0000000000008b2b
       x25 = 0x0000000000000000
       x26 = 0x0000000000000000
       x27 = 0x0000000000000074
       x28 = 0x000000005d0d3aff
        fp = 0x000000016b43c950
        lr = 0x0000000104fc960c  `cv::pointSetBoundingRect(cv::Mat const&) + 40 at shapedescr.cpp:743:5
        sp = 0x000000016b434830
        pc = 0x0000000104fc9794  `cv::pointSetBoundingRect(cv::Mat const&) + 432 [inlined] cv::hal_baseline::v_load_low(long long const*) at intrin.hpp:412
 `cv::pointSetBoundingRect(cv::Mat const&) + 432 [inlined] cv::hal_baseline::simd128::vx_load_low(long long const*) at shapedescr.cpp:768
 `cv::pointSetBoundingRect(cv::Mat const&) + 432 at shapedescr.cpp:768
      cpsr = 0x80000000

The same crash also happens on Android devices.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions