From 1a1a7bbbfd5b0a5cd0bd544eafae8729c9874203 Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Wed, 1 Dec 2021 13:46:03 +0100 Subject: [PATCH] Merge pull request #21112 from vrabaud:3.4_luv_overflow * Fix integer overflow in cv::Luv2RGBinteger::process. For LL=49, uu=205, vv=23, we end up with x=7373056 and y=458 which overflows y*x. * imgproc(test): adjust test parameters to cover SIMD code --- modules/imgproc/src/color_lab.cpp | 8 ++------ modules/imgproc/test/test_color.cpp | 25 ++++++++++++++++++++----- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/modules/imgproc/src/color_lab.cpp b/modules/imgproc/src/color_lab.cpp index a181880862..6b03be6195 100644 --- a/modules/imgproc/src/color_lab.cpp +++ b/modules/imgproc/src/color_lab.cpp @@ -3567,7 +3567,7 @@ struct Luv2RGBinteger long long int xv = ((int)up)*(long long)vp; int x = (int)(xv/BASE); - x = y*x/BASE; + x = ((long long int)y)*x/BASE; long long int vpl = LUVLUT.LvToVpl_b[LL*256+vv]; long long int zp = vpl - xv*(255/3); @@ -3689,6 +3689,7 @@ struct Luv2RGBinteger vzm[i] = zm; vx[i] = (int32_t)(xv >> base_shift); + vx[i] = (((int64_t)y_)*vx[i]) >> base_shift; } v_int32 zm[4]; for(int k = 0; k < 4; k++) @@ -3697,11 +3698,6 @@ struct Luv2RGBinteger zm[k] = vx_load_aligned(vzm + k*vsize/4); } - for(int k = 0; k < 4; k++) - { - x[k] = (y[k]*x[k]) >> base_shift; - } - // z = zm/256 + zm/65536; for (int k = 0; k < 4; k++) { diff --git a/modules/imgproc/test/test_color.cpp b/modules/imgproc/test/test_color.cpp index 3cd57c9d38..f828dac18a 100644 --- a/modules/imgproc/test/test_color.cpp +++ b/modules/imgproc/test/test_color.cpp @@ -1840,6 +1840,21 @@ TEST(Imgproc_ColorLuv, accuracy) { CV_ColorLuvTest test; test.safe_run(); } TEST(Imgproc_ColorRGB, accuracy) { CV_ColorRGBTest test; test.safe_run(); } TEST(Imgproc_ColorBayer, accuracy) { CV_ColorBayerTest test; test.safe_run(); } +TEST(Imgproc_ColorLuv, Overflow_21112) +{ + const Size sz(107, 16); // unaligned size to run both SIMD and generic code + Mat luv_init(sz, CV_8UC3, Scalar(49, 205, 23)); + Mat rgb; + cvtColor(luv_init, rgb, COLOR_Luv2RGB); + // Convert to normal Luv coordinates for floats. + Mat luv_initf(sz, CV_32FC3, Scalar(49.0f/255.f*100, 205.0f*354/255.f - 134, 23.0f*262/255.f - 140)); + Mat rgbf; + cvtColor(luv_initf, rgbf, COLOR_Luv2RGB); + Mat rgb_converted; + rgb.convertTo(rgb_converted, CV_32F); + EXPECT_LE(cvtest::norm(255.f*rgbf, rgb_converted, NORM_INF), 1e-5); +} + TEST(Imgproc_ColorBayer, regression) { cvtest::TS* ts = cvtest::TS::ptr(); @@ -2569,7 +2584,7 @@ int row8uLuv2RGB(const uchar* src_row, uchar *dst_row, int n, int cn, int blue_i long long int xv = ((int)up)*(long long)vp; int x = (int)(xv/BASE); - x = y*x/BASE; + x = ((long long int)y)*x/BASE; long long int vpl = LvToVpl_b[LL*256+vv]; long long int zp = vpl - xv*(255/3); @@ -2725,11 +2740,11 @@ TEST(Imgproc_ColorLuv_Full, bitExactness) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0xec311a14, 0x995efefc, 0xf71b590b, 0xc1edfce7, 0x67b2b2e2, 0xe6d7f90d, 0xbcbaff5c, 0xd86ae19c, - 0x3e8e4647, 0x53f1a5e3, 0x60dfb6ca, 0xcda851fe, 0xd91084b3, 0xe361bf6f, 0x90fe66ed, 0xb19c5b89, + 0x4bff0e00, 0x76bbff01, 0x80735725, 0xb5e0f137, 0x96abb417, 0xfb2cf5cf, 0x314cf55e, 0x77bde10e, + 0x2ab24209, 0x81caa6F0, 0x3019b8eb, 0x427c505f, 0x5bba7d77, 0xf29cb4d6, 0x760f65ca, 0xf6b4536c, - 0x190508ec, 0xc7764e22, 0x19b042a8, 0x2db4c5d8, 0x6e1cfd1d, 0x39bddd51, 0x942714ed, 0x19444d39, - 0xed16e206, 0xc4102784, 0x590075fe, 0xaaef2ec6, 0xbeb84149, 0x8da31e4f, 0x7cbe7d77, 0x1c90b30a, + 0xb5cd0704, 0x82144fd4, 0x4e6f4843, 0x106bc505, 0xf587fc97, 0x3665d9a3, 0x3ea014a8, 0xec664953, + 0x6ec9e59e, 0xf9201e08, 0xf3676fb8, 0xe4e42c10, 0x92d33f64, 0x13b923f7, 0x308f7f50, 0xca98b420, }; RNG rng(0);