From 8b772e860ad66d5c27d7c69199a008afb69d5c63 Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Fri, 4 Sep 2026 16:12:16 +0200 Subject: [PATCH] Fix potential CPU bomb The test went from 2.8s to 7ms --- modules/imgproc/src/warp_kernels.simd.hpp | 23 ++++++++++++++--------- modules/imgproc/test/test_imgwarp.cpp | 10 ++++++++++ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/modules/imgproc/src/warp_kernels.simd.hpp b/modules/imgproc/src/warp_kernels.simd.hpp index f6cc9a1742..f01c984f9f 100644 --- a/modules/imgproc/src/warp_kernels.simd.hpp +++ b/modules/imgproc/src/warp_kernels.simd.hpp @@ -336,17 +336,22 @@ static inline int borderInterpolate_fast( int p, int len, int borderType ) p = p < 0 ? 0 : len - 1; else if( borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101 ) { + const int delta = borderType == BORDER_REFLECT_101; if( len == 1 ) return 0; - int delta = borderType == BORDER_REFLECT_101; - do - { - if( p < 0 ) - p = -p - 1 + delta; - else - p = len - 1 - (p - len) - delta; - } - while( (unsigned)p >= (unsigned)len ); + + // Fast path: single reflection without division for small deviations. + if( -len + delta <= p && p < 2 * len - delta ) + return p < 0 ? -p - 1 + delta : 2 * len - 1 - delta - p; + // Bounded fallback: O(1) modulo for large |p| + const int64 period = 2LL * (len - delta); + int64 p64 = p; + p64 %= period; + if( p64 < 0 ) + p64 += period; + if( p64 >= len ) + p64 = period - p64 - 1 + delta; + p = (int)p64; } else if( borderType == BORDER_WRAP ) { diff --git a/modules/imgproc/test/test_imgwarp.cpp b/modules/imgproc/test/test_imgwarp.cpp index 4bf0150de3..6b4051c716 100644 --- a/modules/imgproc/test/test_imgwarp.cpp +++ b/modules/imgproc/test/test_imgwarp.cpp @@ -1253,5 +1253,15 @@ TEST(Imgproc_Warping, infinite_loop) << "cv::warpAffine hung in an infinite loop!"; } +TEST(Imgproc_Warping, interpolate_loop) +{ + // 1000x1000 destination image with out-of-bounds coordinates: + cv::Mat src(2, 2, CV_8UC1, cv::Scalar(42)); + cv::Mat dst; + // A perspective or affine transform mapping pixels to large coordinates: + cv::Matx23d M(1, 0, 1e7, 0, 1, 1e7); + cv::warpAffine(src, dst, M, cv::Size(50, 50), cv::INTER_NEAREST, cv::BORDER_REFLECT_101); +} + }} // namespace /* End of file. */