From 659cf7249e78453b7bb2cc4da3df2a5d19176cd5 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 9 Dec 2021 20:23:35 +0000 Subject: [PATCH] imgproc(ocl): fix resizeLN, avoid integer overflow --- modules/imgproc/src/opencl/resize.cl | 8 ++++---- modules/imgproc/src/resize.cpp | 3 ++- modules/imgproc/test/ocl/test_warp.cpp | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/modules/imgproc/src/opencl/resize.cl b/modules/imgproc/src/opencl/resize.cl index 67603e4f17..a28c59296e 100644 --- a/modules/imgproc/src/opencl/resize.cl +++ b/modules/imgproc/src/opencl/resize.cl @@ -51,8 +51,6 @@ #endif #endif -#define INTER_RESIZE_COEF_SCALE (1 << INTER_RESIZE_COEF_BITS) -#define CAST_BITS (INTER_RESIZE_COEF_BITS << 1) #define INC(x,l) min(x+1,l-1) #define noconvert @@ -188,7 +186,9 @@ __kernel void resizeLN(__global const uchar * srcptr, int src_step, int src_offs int y_ = INC(y, src_rows); int x_ = INC(x, src_cols); -#if depth <= 4 +#if depth <= 1 // 8U/8S only, 16U+ cause integer overflows +#define INTER_RESIZE_COEF_SCALE (1 << INTER_RESIZE_COEF_BITS) +#define CAST_BITS (INTER_RESIZE_COEF_BITS << 1) u = u * INTER_RESIZE_COEF_SCALE; v = v * INTER_RESIZE_COEF_SCALE; @@ -214,7 +214,7 @@ __kernel void resizeLN(__global const uchar * srcptr, int src_step, int src_offs WT data2 = convertToWT(loadpix(srcptr + mad24(y_, src_step, mad24(x, TSIZE, src_offset)))); WT data3 = convertToWT(loadpix(srcptr + mad24(y_, src_step, mad24(x_, TSIZE, src_offset)))); - T uval = u1 * v1 * data0 + u * v1 * data1 + u1 * v *data2 + u * v *data3; + T uval = convertToDT((u1 * v1) * data0 + (u * v1) * data1 + (u1 * v) * data2 + (u * v) * data3); #endif storepix(uval, dstptr + mad24(dy, dst_step, mad24(dx, TSIZE, dst_offset))); } diff --git a/modules/imgproc/src/resize.cpp b/modules/imgproc/src/resize.cpp index 4f1a4576ce..90a05085e3 100644 --- a/modules/imgproc/src/resize.cpp +++ b/modules/imgproc/src/resize.cpp @@ -3376,7 +3376,8 @@ static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize, } else { - int wdepth = std::max(depth, CV_32S), wtype = CV_MAKETYPE(wdepth, cn); + int wdepth = depth <= CV_8S ? CV_32S : std::max(depth, CV_32F); + int wtype = CV_MAKETYPE(wdepth, cn); k.create("resizeLN", ocl::imgproc::resize_oclsrc, format("-D INTER_LINEAR -D depth=%d -D T=%s -D T1=%s " "-D WT=%s -D convertToWT=%s -D convertToDT=%s -D cn=%d " diff --git a/modules/imgproc/test/ocl/test_warp.cpp b/modules/imgproc/test/ocl/test_warp.cpp index 15e024a140..b43c9b6732 100644 --- a/modules/imgproc/test/ocl/test_warp.cpp +++ b/modules/imgproc/test/ocl/test_warp.cpp @@ -327,6 +327,20 @@ OCL_TEST_P(Resize, Mat) } } +OCL_TEST(Resize, overflow_21198) +{ + Mat src(Size(600, 600), CV_16UC3, Scalar::all(32768)); + UMat src_u; + src.copyTo(src_u); + + Mat dst; + cv::resize(src, dst, Size(1024, 1024), 0, 0, INTER_LINEAR); + UMat dst_u; + cv::resize(src_u, dst_u, Size(1024, 1024), 0, 0, INTER_LINEAR); + EXPECT_LE(cv::norm(dst_u, dst, NORM_INF), 1.0f); +} + + ///////////////////////////////////////////////////////////////////////////////////////////////// // remap