From c7732e1043c422cda5c243f3a668a3e868602ee1 Mon Sep 17 00:00:00 2001 From: Anshu Date: Fri, 27 Mar 2026 18:10:09 +0530 Subject: [PATCH] Merge pull request #28397 from 0AnshuAditya0:fix-simd-oob-read-28396 Fixes #28396 : out-of-bounds read in SIMD type conversion #28397 Fixes #28396 Fixes #27080 The vx_load_expand function in WASM intrinsics was using wasm_v128_load which always loads a full 128-bit register (16 bytes), even when the function only needed 8 elements. For example, when converting uint8 to float32: - vx_load_expand needs 8 uint8 elements - But wasm_v128_load reads 16 bytes from memory - This causes an 8-byte out-of-bounds read ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- .../include/opencv2/core/hal/intrin_wasm.hpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/modules/core/include/opencv2/core/hal/intrin_wasm.hpp b/modules/core/include/opencv2/core/hal/intrin_wasm.hpp index 7c4d8e05df..f21cca7aea 100644 --- a/modules/core/include/opencv2/core/hal/intrin_wasm.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_wasm.hpp @@ -1859,9 +1859,12 @@ inline _Tpwvec v_expand_high(const _Tpvec& a) \ { return _Tpwvec(__CV_CAT(intrin, _high)(a.val)); } \ inline _Tpwvec v_load_expand(const _Tp* ptr) \ { \ - v128_t a = wasm_v128_load(ptr); \ - return _Tpwvec(intrin(a)); \ -} + using lane_t = typename _Tpwvec::lane_type; \ + alignas(16) lane_t tmp[_Tpwvec::nlanes]; \ + for(int i = 0; i < _Tpwvec::nlanes; i++) \ + tmp[i] = static_cast(ptr[i]); \ + return _Tpwvec(wasm_v128_load(tmp)); \ +} \ OPENCV_HAL_IMPL_WASM_EXPAND(v_uint8x16, v_uint16x8, uchar, v128_cvtu8x16_i16x8) OPENCV_HAL_IMPL_WASM_EXPAND(v_int8x16, v_int16x8, schar, v128_cvti8x16_i16x8) @@ -1873,9 +1876,12 @@ OPENCV_HAL_IMPL_WASM_EXPAND(v_int32x4, v_int64x2, int, v128_cvti32x4_i64x2) #define OPENCV_HAL_IMPL_WASM_EXPAND_Q(_Tpvec, _Tp, intrin) \ inline _Tpvec v_load_expand_q(const _Tp* ptr) \ { \ - v128_t a = wasm_v128_load(ptr); \ - return _Tpvec(intrin(a)); \ -} + using lane_t = typename _Tpvec::lane_type; \ + alignas(16) lane_t tmp[_Tpvec::nlanes]; \ + for(int i = 0; i < _Tpvec::nlanes; i++) \ + tmp[i] = static_cast(ptr[i]); \ + return _Tpvec(wasm_v128_load(tmp)); \ +} \ OPENCV_HAL_IMPL_WASM_EXPAND_Q(v_uint32x4, uchar, v128_cvtu8x16_i32x4) OPENCV_HAL_IMPL_WASM_EXPAND_Q(v_int32x4, schar, v128_cvti8x16_i32x4)