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.
System information (version)
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.
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:
When it crashes i == 4095 and a single element remains to read from pts array.
This is the assembly code generated by the compiler:
The ld2.2d causes the access violation: Thread 5: EXC_BAD_ACCESS (code=2, address=0x1078d4000)
Here is the register dump:
The same crash also happens on Android devices.