From 0fb4f2cc9c31eb5345f72881bd537557cb0b8241 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 20 Mar 2020 21:04:29 +0000 Subject: [PATCH] imgproc: add src.empty() checks in filter operations --- .../imgproc/src/bilateral_filter.dispatch.cpp | 2 ++ modules/imgproc/src/box_filter.dispatch.cpp | 4 +++ modules/imgproc/src/deriv.cpp | 6 ++++ modules/imgproc/src/filter.dispatch.cpp | 15 +++++++++ modules/imgproc/src/median_blur.dispatch.cpp | 2 ++ modules/imgproc/src/morph.dispatch.cpp | 8 +++++ modules/imgproc/src/smooth.dispatch.cpp | 2 ++ modules/imgproc/test/test_filter.cpp | 33 +++++++++++++++++++ modules/ts/include/opencv2/ts/ts_ext.hpp | 31 +++++++++++++++++ 9 files changed, 103 insertions(+) diff --git a/modules/imgproc/src/bilateral_filter.dispatch.cpp b/modules/imgproc/src/bilateral_filter.dispatch.cpp index a27ebb18f5..ed0e71bbab 100644 --- a/modules/imgproc/src/bilateral_filter.dispatch.cpp +++ b/modules/imgproc/src/bilateral_filter.dispatch.cpp @@ -406,6 +406,8 @@ void bilateralFilter( InputArray _src, OutputArray _dst, int d, { CV_INSTRUMENT_REGION(); + CV_Assert(!_src.empty()); + _dst.create( _src.size(), _src.type() ); CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(), diff --git a/modules/imgproc/src/box_filter.dispatch.cpp b/modules/imgproc/src/box_filter.dispatch.cpp index 054e7474c6..c9ec693385 100644 --- a/modules/imgproc/src/box_filter.dispatch.cpp +++ b/modules/imgproc/src/box_filter.dispatch.cpp @@ -443,6 +443,8 @@ void boxFilter(InputArray _src, OutputArray _dst, int ddepth, { CV_INSTRUMENT_REGION(); + CV_Assert(!_src.empty()); + CV_OCL_RUN(_dst.isUMat() && (borderType == BORDER_REPLICATE || borderType == BORDER_CONSTANT || borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101), @@ -514,6 +516,8 @@ void sqrBoxFilter(InputArray _src, OutputArray _dst, int ddepth, { CV_INSTRUMENT_REGION(); + CV_Assert(!_src.empty()); + int srcType = _src.type(), sdepth = CV_MAT_DEPTH(srcType), cn = CV_MAT_CN(srcType); Size size = _src.size(); diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index fa9defb405..1248ea1888 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -416,6 +416,8 @@ void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, { CV_INSTRUMENT_REGION(); + CV_Assert(!_src.empty()); + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); if (ddepth < 0) ddepth = sdepth; @@ -468,6 +470,8 @@ void cv::Scharr( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, { CV_INSTRUMENT_REGION(); + CV_Assert(!_src.empty()); + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); if (ddepth < 0) ddepth = sdepth; @@ -785,6 +789,8 @@ void cv::Laplacian( InputArray _src, OutputArray _dst, int ddepth, int ksize, { CV_INSTRUMENT_REGION(); + CV_Assert(!_src.empty()); + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); if (ddepth < 0) ddepth = sdepth; diff --git a/modules/imgproc/src/filter.dispatch.cpp b/modules/imgproc/src/filter.dispatch.cpp index 65a066b57b..d39c749121 100644 --- a/modules/imgproc/src/filter.dispatch.cpp +++ b/modules/imgproc/src/filter.dispatch.cpp @@ -169,6 +169,9 @@ int FilterEngine::start(const Size& _wholeSize, const Size& sz, const Point& ofs { CV_INSTRUMENT_REGION(); + CV_Assert(!sz.empty()); + CV_Assert(!_wholeSize.empty()); + CV_CPU_DISPATCH(FilterEngine__start, (*this, _wholeSize, sz, ofs), CV_CPU_DISPATCH_MODES_ALL); } @@ -176,6 +179,11 @@ int FilterEngine::start(const Size& _wholeSize, const Size& sz, const Point& ofs int FilterEngine::start(const Mat& src, const Size &wsz, const Point &ofs) { + CV_INSTRUMENT_REGION(); + + CV_Assert(!src.empty()); + CV_Assert(!wsz.empty()); + start( wsz, src.size(), ofs); return startY - ofs.y; } @@ -1398,6 +1406,9 @@ void filter2D(InputArray _src, OutputArray _dst, int ddepth, { CV_INSTRUMENT_REGION(); + CV_Assert(!_src.empty()); + CV_Assert(!_kernel.empty()); + CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2, ocl_filter2D(_src, _dst, ddepth, _kernel, anchor0, delta, borderType)) @@ -1429,6 +1440,10 @@ void sepFilter2D(InputArray _src, OutputArray _dst, int ddepth, { CV_INSTRUMENT_REGION(); + CV_Assert(!_src.empty()); + CV_Assert(!_kernelX.empty()); + CV_Assert(!_kernelY.empty()); + CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && (size_t)_src.rows() > _kernelY.total() && (size_t)_src.cols() > _kernelX.total(), ocl_sepFilter2D(_src, _dst, ddepth, _kernelX, _kernelY, anchor, delta, borderType)) diff --git a/modules/imgproc/src/median_blur.dispatch.cpp b/modules/imgproc/src/median_blur.dispatch.cpp index 79333f5f80..afef09f579 100644 --- a/modules/imgproc/src/median_blur.dispatch.cpp +++ b/modules/imgproc/src/median_blur.dispatch.cpp @@ -280,6 +280,8 @@ void medianBlur( InputArray _src0, OutputArray _dst, int ksize ) { CV_INSTRUMENT_REGION(); + CV_Assert(!_src0.empty()); + CV_Assert( (ksize % 2 == 1) && (_src0.dims() <= 2 )); if( ksize <= 1 || _src0.empty() ) diff --git a/modules/imgproc/src/morph.dispatch.cpp b/modules/imgproc/src/morph.dispatch.cpp index cbb5315f31..45ae3994d9 100644 --- a/modules/imgproc/src/morph.dispatch.cpp +++ b/modules/imgproc/src/morph.dispatch.cpp @@ -939,6 +939,8 @@ static void morphOp( int op, InputArray _src, OutputArray _dst, { CV_INSTRUMENT_REGION(); + CV_Assert(!_src.empty()); + Mat kernel = _kernel.getMat(); Size ksize = !kernel.empty() ? kernel.size() : Size(3,3); anchor = normalizeAnchor(anchor, ksize); @@ -1005,6 +1007,8 @@ void erode( InputArray src, OutputArray dst, InputArray kernel, { CV_INSTRUMENT_REGION(); + CV_Assert(!src.empty()); + morphOp( MORPH_ERODE, src, dst, kernel, anchor, iterations, borderType, borderValue ); } @@ -1015,6 +1019,8 @@ void dilate( InputArray src, OutputArray dst, InputArray kernel, { CV_INSTRUMENT_REGION(); + CV_Assert(!src.empty()); + morphOp( MORPH_DILATE, src, dst, kernel, anchor, iterations, borderType, borderValue ); } @@ -1154,6 +1160,8 @@ void morphologyEx( InputArray _src, OutputArray _dst, int op, { CV_INSTRUMENT_REGION(); + CV_Assert(!_src.empty()); + Mat kernel = _kernel.getMat(); if (kernel.empty()) { diff --git a/modules/imgproc/src/smooth.dispatch.cpp b/modules/imgproc/src/smooth.dispatch.cpp index c90d0828b8..4ac7df8b4d 100644 --- a/modules/imgproc/src/smooth.dispatch.cpp +++ b/modules/imgproc/src/smooth.dispatch.cpp @@ -603,6 +603,8 @@ void GaussianBlur(InputArray _src, OutputArray _dst, Size ksize, { CV_INSTRUMENT_REGION(); + CV_Assert(!_src.empty()); + int type = _src.type(); Size size = _src.size(); _dst.create( size, type ); diff --git a/modules/imgproc/test/test_filter.cpp b/modules/imgproc/test/test_filter.cpp index 947738f16a..11d87a0abe 100644 --- a/modules/imgproc/test/test_filter.cpp +++ b/modules/imgproc/test/test_filter.cpp @@ -2323,4 +2323,37 @@ TEST(Imgproc_Pyrdown, issue_12961) ASSERT_EQ(0.0, cv::norm(dst)); } + +// https://github.com/opencv/opencv/issues/16857 +TEST(Imgproc, filter_empty_src_16857) +{ +#define CV_TEST_EXPECT_EMPTY_THROW(statement) CV_TEST_EXPECT_EXCEPTION_MESSAGE(statement, ".empty()") + + Mat src, dst, dst2; + + CV_TEST_EXPECT_EMPTY_THROW(bilateralFilter(src, dst, 5, 50, 20)); + CV_TEST_EXPECT_EMPTY_THROW(blur(src, dst, Size(3, 3))); + CV_TEST_EXPECT_EMPTY_THROW(boxFilter(src, dst, CV_8U, Size(3, 3))); + CV_TEST_EXPECT_EMPTY_THROW(sqrBoxFilter(src, dst, CV_8U, Size(3, 3))); + CV_TEST_EXPECT_EMPTY_THROW(medianBlur(src, dst, 3)); + CV_TEST_EXPECT_EMPTY_THROW(GaussianBlur(src, dst, Size(3, 3), 0)); + CV_TEST_EXPECT_EMPTY_THROW(cv::filter2D(src, dst, CV_8U, Mat_::zeros(Size(3, 3)))); + CV_TEST_EXPECT_EMPTY_THROW(sepFilter2D(src, dst, CV_8U, Mat_::zeros(Size(3, 1)), Mat_::zeros(Size(1, 3)))); + CV_TEST_EXPECT_EMPTY_THROW(Sobel(src, dst, CV_8U, 1, 1)); + CV_TEST_EXPECT_EMPTY_THROW(spatialGradient(src, dst, dst2)); + CV_TEST_EXPECT_EMPTY_THROW(Scharr(src, dst, CV_8U, 1, 1)); + CV_TEST_EXPECT_EMPTY_THROW(Laplacian(src, dst, CV_8U)); + + CV_TEST_EXPECT_EMPTY_THROW(cv::dilate(src, dst, Mat())); // cvtest:: by default + CV_TEST_EXPECT_EMPTY_THROW(cv::erode(src, dst, Mat())); // cvtest:: by default + CV_TEST_EXPECT_EMPTY_THROW(morphologyEx(src, dst, MORPH_OPEN, Mat())); + + //debug: CV_TEST_EXPECT_EMPTY_THROW(blur(Mat_(Size(3,3)), dst, Size(3, 3))); + + EXPECT_TRUE(src.empty()); + EXPECT_TRUE(dst.empty()); + EXPECT_TRUE(dst2.empty()); +} + + }} // namespace diff --git a/modules/ts/include/opencv2/ts/ts_ext.hpp b/modules/ts/include/opencv2/ts/ts_ext.hpp index f22a9d42eb..b2a4cac241 100644 --- a/modules/ts/include/opencv2/ts/ts_ext.hpp +++ b/modules/ts/include/opencv2/ts/ts_ext.hpp @@ -161,4 +161,35 @@ bool checkBigDataTests(); #undef TEST_P #define TEST_P(test_case_name, test_name) CV__TEST_P(test_case_name, test_name, Body, CV__TEST_BODY_IMPL) + +#define CV_TEST_EXPECT_EXCEPTION_MESSAGE(statement, msg) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + const char* msg_ = msg; \ + bool hasException = false; \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (const cv::Exception& e) { \ + if (NULL == strstr(e.what(), msg_)) \ + ADD_FAILURE() << "Unexpected cv::Exception is raised: " << #statement << "\n Expected message substring: '" << msg_ << "'. Actual message:\n" << e.what(); \ + hasException = true; \ + } \ + catch (const std::exception& e) { \ + ADD_FAILURE() << "Unexpected std::exception is raised: " << #statement << "\n" << e.what(); \ + hasException = true; \ + } \ + catch (...) { \ + ADD_FAILURE() << "Unexpected C++ exception is raised: " << #statement; \ + hasException = true; \ + } \ + if (!hasException) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_test_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_test_, __LINE__): \ + ADD_FAILURE() << "Failed: Expected: " #statement " throws an '" << msg << "' exception.\n" \ + " Actual: it doesn't." + + #endif // OPENCV_TS_EXT_HPP