From a4bd7506a5bd04100fa18626a8aca65ac1d10c79 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 29 Jan 2020 17:42:16 +0300 Subject: [PATCH] core: CV_STRONG_ALIGNMENT macro Should be used to guard unsafe type casts of pointers --- modules/core/include/opencv2/core/cvdef.h | 7 +++ .../core/include/opencv2/core/hal/intrin_cpp.hpp | 52 +++++++++++++++++++++- modules/core/src/copy.cpp | 26 +++++------ modules/dnn/src/onnx/onnx_importer.cpp | 2 + 4 files changed, 70 insertions(+), 17 deletions(-) diff --git a/modules/core/include/opencv2/core/cvdef.h b/modules/core/include/opencv2/core/cvdef.h index 787be9e..9191feb 100644 --- a/modules/core/include/opencv2/core/cvdef.h +++ b/modules/core/include/opencv2/core/cvdef.h @@ -335,6 +335,13 @@ enum CpuFeatures { #include "cv_cpu_dispatch.h" +#if !defined(CV_STRONG_ALIGNMENT) && defined(__arm__) && !(defined(__aarch64__) || defined(_M_ARM64)) +// int*, int64* should be propertly aligned pointers on ARMv7 +#define CV_STRONG_ALIGNMENT 1 +#endif +#if !defined(CV_STRONG_ALIGNMENT) +#define CV_STRONG_ALIGNMENT 0 +#endif /* fundamental constants */ #define CV_PI 3.1415926535897932384626433832795 diff --git a/modules/core/include/opencv2/core/hal/intrin_cpp.hpp b/modules/core/include/opencv2/core/hal/intrin_cpp.hpp index c3e89b9..859bfd7 100644 --- a/modules/core/include/opencv2/core/hal/intrin_cpp.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_cpp.hpp @@ -1458,16 +1458,23 @@ template inline void v_zip( const v_reg<_Tp, n>& a0, const @return register object @note Returned type will be detected from passed pointer type, for example uchar ==> cv::v_uint8x16, int ==> cv::v_int32x4, etc. + +@note Alignment requirement: +if CV_STRONG_ALIGNMENT=1 then passed pointer must be aligned (`sizeof(lane type)` should be enough). +Do not cast pointer types without runtime check for pointer alignment (like `uchar*` => `int*`). */ template inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_load(const _Tp* ptr) { +#if CV_STRONG_ALIGNMENT + CV_Assert(isAligned(ptr)); +#endif return v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128>(ptr); } /** @brief Load register contents from memory (aligned) -similar to cv::v_load, but source memory block should be aligned (to 16-byte boundary) +similar to cv::v_load, but source memory block should be aligned (to 16-byte boundary in case of SIMD128, 32-byte - SIMD256, etc) */ template inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_load_aligned(const _Tp* ptr) @@ -1488,6 +1495,9 @@ v_int32x4 r = v_load_low(lo); template inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_load_low(const _Tp* ptr) { +#if CV_STRONG_ALIGNMENT + CV_Assert(isAligned(ptr)); +#endif v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> c; for( int i = 0; i < c.nlanes/2; i++ ) { @@ -1509,6 +1519,10 @@ v_int32x4 r = v_load_halves(lo, hi); template inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_load_halves(const _Tp* loptr, const _Tp* hiptr) { +#if CV_STRONG_ALIGNMENT + CV_Assert(isAligned(loptr)); + CV_Assert(isAligned(hiptr)); +#endif v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> c; for( int i = 0; i < c.nlanes/2; i++ ) { @@ -1531,6 +1545,9 @@ template inline v_reg::w_type, V_TypeTraits<_Tp>::nlanes128 / 2> v_load_expand(const _Tp* ptr) { +#if CV_STRONG_ALIGNMENT + CV_Assert(isAligned(ptr)); +#endif typedef typename V_TypeTraits<_Tp>::w_type w_type; v_reg::nlanes128> c; for( int i = 0; i < c.nlanes; i++ ) @@ -1552,6 +1569,9 @@ template inline v_reg::q_type, V_TypeTraits<_Tp>::nlanes128 / 4> v_load_expand_q(const _Tp* ptr) { +#if CV_STRONG_ALIGNMENT + CV_Assert(isAligned(ptr)); +#endif typedef typename V_TypeTraits<_Tp>::q_type q_type; v_reg::nlanes128> c; for( int i = 0; i < c.nlanes; i++ ) @@ -1572,6 +1592,9 @@ For all types except 64-bit. */ template inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a, v_reg<_Tp, n>& b) { +#if CV_STRONG_ALIGNMENT + CV_Assert(isAligned(ptr)); +#endif int i, i2; for( i = i2 = 0; i < n; i++, i2 += 2 ) { @@ -1591,6 +1614,9 @@ For all types except 64-bit. */ template inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a, v_reg<_Tp, n>& b, v_reg<_Tp, n>& c) { +#if CV_STRONG_ALIGNMENT + CV_Assert(isAligned(ptr)); +#endif int i, i3; for( i = i3 = 0; i < n; i++, i3 += 3 ) { @@ -1613,6 +1639,9 @@ inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a, v_reg<_Tp, n>& b, v_reg<_Tp, n>& c, v_reg<_Tp, n>& d) { +#if CV_STRONG_ALIGNMENT + CV_Assert(isAligned(ptr)); +#endif int i, i4; for( i = i4 = 0; i < n; i++, i4 += 4 ) { @@ -1636,6 +1665,9 @@ inline void v_store_interleave( _Tp* ptr, const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, hal::StoreMode /*mode*/=hal::STORE_UNALIGNED) { +#if CV_STRONG_ALIGNMENT + CV_Assert(isAligned(ptr)); +#endif int i, i2; for( i = i2 = 0; i < n; i++, i2 += 2 ) { @@ -1657,6 +1689,9 @@ inline void v_store_interleave( _Tp* ptr, const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, const v_reg<_Tp, n>& c, hal::StoreMode /*mode*/=hal::STORE_UNALIGNED) { +#if CV_STRONG_ALIGNMENT + CV_Assert(isAligned(ptr)); +#endif int i, i3; for( i = i3 = 0; i < n; i++, i3 += 3 ) { @@ -1679,6 +1714,9 @@ template inline void v_store_interleave( _Tp* ptr, const v_ const v_reg<_Tp, n>& d, hal::StoreMode /*mode*/=hal::STORE_UNALIGNED) { +#if CV_STRONG_ALIGNMENT + CV_Assert(isAligned(ptr)); +#endif int i, i4; for( i = i4 = 0; i < n; i++, i4 += 4 ) { @@ -1700,6 +1738,9 @@ Pointer can be unaligned. */ template inline void v_store(_Tp* ptr, const v_reg<_Tp, n>& a) { +#if CV_STRONG_ALIGNMENT + CV_Assert(isAligned(ptr)); +#endif for( int i = 0; i < n; i++ ) ptr[i] = a.s[i]; } @@ -1707,6 +1748,9 @@ inline void v_store(_Tp* ptr, const v_reg<_Tp, n>& a) template inline void v_store(_Tp* ptr, const v_reg<_Tp, n>& a, hal::StoreMode /*mode*/) { +#if CV_STRONG_ALIGNMENT + CV_Assert(isAligned(ptr)); +#endif v_store(ptr, a); } @@ -1720,6 +1764,9 @@ Scheme: template inline void v_store_low(_Tp* ptr, const v_reg<_Tp, n>& a) { +#if CV_STRONG_ALIGNMENT + CV_Assert(isAligned(ptr)); +#endif for( int i = 0; i < (n/2); i++ ) ptr[i] = a.s[i]; } @@ -1734,6 +1781,9 @@ Scheme: template inline void v_store_high(_Tp* ptr, const v_reg<_Tp, n>& a) { +#if CV_STRONG_ALIGNMENT + CV_Assert(isAligned(ptr)); +#endif for( int i = 0; i < (n/2); i++ ) ptr[i] = a.s[i+(n/2)]; } diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index 3fa4982..1f981ee 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -563,12 +563,6 @@ Mat& Mat::setTo(InputArray _value, InputArray _mask) return *this; } -#if CV_NEON && !defined(__aarch64__) -#define CV_CHECK_ALIGNMENT 1 -#else -#define CV_CHECK_ALIGNMENT 0 -#endif - #if CV_SIMD128 template CV_ALWAYS_INLINE void flipHoriz_single( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz ) { @@ -578,7 +572,7 @@ template CV_ALWAYS_INLINE void flipHoriz_single( const uchar* src, s int width_1 = width & -v_uint8x16::nlanes; int i, j; -#if CV_CHECK_ALIGNMENT +#if CV_STRONG_ALIGNMENT CV_Assert(isAligned(src, dst)); #endif @@ -630,7 +624,7 @@ template CV_ALWAYS_INLINE void flipHoriz_double( const int end = (int)(size.width*esz); int width = (end + 1)/2; -#if CV_CHECK_ALIGNMENT +#if CV_STRONG_ALIGNMENT CV_Assert(isAligned(src, dst)); CV_Assert(isAligned(src, dst)); #endif @@ -659,7 +653,7 @@ static void flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz ) { #if CV_SIMD -#if CV_CHECK_ALIGNMENT +#if CV_STRONG_ALIGNMENT size_t alignmentMark = ((size_t)src)|((size_t)dst)|sstep|dstep; #endif if (esz == 2 * v_uint8x16::nlanes) @@ -712,7 +706,7 @@ flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, } } else if (esz == 8 -#if CV_CHECK_ALIGNMENT +#if CV_STRONG_ALIGNMENT && isAligned(alignmentMark) #endif ) @@ -720,7 +714,7 @@ flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, flipHoriz_single(src, sstep, dst, dstep, size, esz); } else if (esz == 4 -#if CV_CHECK_ALIGNMENT +#if CV_STRONG_ALIGNMENT && isAligned(alignmentMark) #endif ) @@ -728,7 +722,7 @@ flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, flipHoriz_single(src, sstep, dst, dstep, size, esz); } else if (esz == 2 -#if CV_CHECK_ALIGNMENT +#if CV_STRONG_ALIGNMENT && isAligned(alignmentMark) #endif ) @@ -740,7 +734,7 @@ flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, flipHoriz_single(src, sstep, dst, dstep, size, esz); } else if (esz == 24 -#if CV_CHECK_ALIGNMENT +#if CV_STRONG_ALIGNMENT && isAligned(alignmentMark) #endif ) @@ -766,7 +760,7 @@ flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, } } } -#if !CV_CHECK_ALIGNMENT +#if !CV_STRONG_ALIGNMENT else if (esz == 12) { flipHoriz_double(src, sstep, dst, dstep, size, esz); @@ -815,7 +809,7 @@ flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size, { int i = 0; #if CV_SIMD -#if CV_CHECK_ALIGNMENT +#if CV_STRONG_ALIGNMENT if (isAligned(src0, src1, dst0, dst1)) #endif { @@ -827,7 +821,7 @@ flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size, vx_store((int*)(dst1 + i), t0); } } -#if CV_CHECK_ALIGNMENT +#if CV_STRONG_ALIGNMENT else { for (; i <= size.width - CV_SIMD_WIDTH; i += CV_SIMD_WIDTH) diff --git a/modules/dnn/src/onnx/onnx_importer.cpp b/modules/dnn/src/onnx/onnx_importer.cpp index 3da494b..039b578 100644 --- a/modules/dnn/src/onnx/onnx_importer.cpp +++ b/modules/dnn/src/onnx/onnx_importer.cpp @@ -148,6 +148,7 @@ Mat getMatFromTensor(opencv_onnx::TensorProto& tensor_proto) else { const char* val = tensor_proto.raw_data().c_str(); +#if CV_STRONG_ALIGNMENT // Aligned pointer is required: https://github.com/opencv/opencv/issues/16373 // this doesn't work: typedef int64_t CV_DECL_ALIGNED(1) unaligned_int64_t; AutoBuffer aligned_val; @@ -158,6 +159,7 @@ Mat getMatFromTensor(opencv_onnx::TensorProto& tensor_proto) memcpy(aligned_val.data(), val, sz); val = (const char*)aligned_val.data(); } +#endif const int64_t* src = reinterpret_cast(val); convertInt64ToInt32(src, dst, blob.total()); } -- 2.7.4