imgproc: add src.empty() checks in filter operations
authorAlexander Alekhin <alexander.a.alekhin@gmail.com>
Fri, 20 Mar 2020 21:04:29 +0000 (21:04 +0000)
committerAlexander Alekhin <alexander.a.alekhin@gmail.com>
Fri, 20 Mar 2020 21:04:29 +0000 (21:04 +0000)
modules/imgproc/src/bilateral_filter.dispatch.cpp
modules/imgproc/src/box_filter.dispatch.cpp
modules/imgproc/src/deriv.cpp
modules/imgproc/src/filter.dispatch.cpp
modules/imgproc/src/median_blur.dispatch.cpp
modules/imgproc/src/morph.dispatch.cpp
modules/imgproc/src/smooth.dispatch.cpp
modules/imgproc/test/test_filter.cpp
modules/ts/include/opencv2/ts/ts_ext.hpp

index a27ebb1..ed0e71b 100644 (file)
@@ -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(),
index 054e747..c9ec693 100644 (file)
@@ -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();
 
index fa9defb..1248ea1 100644 (file)
@@ -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;
index 65a066b..d39c749 100644 (file)
@@ -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))
 
index 79333f5..afef09f 100644 (file)
@@ -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() )
index cbb5315..45ae399 100644 (file)
@@ -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())
     {
index c90d082..4ac7df8 100644 (file)
@@ -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 );
index 947738f..11d87a0 100644 (file)
@@ -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_<float>::zeros(Size(3, 3))));
+    CV_TEST_EXPECT_EMPTY_THROW(sepFilter2D(src, dst, CV_8U, Mat_<float>::zeros(Size(3, 1)), Mat_<float>::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_<uchar>(Size(3,3)), dst, Size(3, 3)));
+
+    EXPECT_TRUE(src.empty());
+    EXPECT_TRUE(dst.empty());
+    EXPECT_TRUE(dst2.empty());
+}
+
+
 }} // namespace
index f22a9d4..b2a4cac 100644 (file)
@@ -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