diff --git a/modules/core/src/matrix_wrap.cpp b/modules/core/src/matrix_wrap.cpp index 8d9e984bc83604493adedd27a3d301cd881cd6f3..f0b5b895c4bb7969c41c3be2c2ef21d65826276c 100644 --- a/modules/core/src/matrix_wrap.cpp +++ b/modules/core/src/matrix_wrap.cpp @@ -914,7 +914,7 @@ bool _InputArray::isContinuous(int i) const if( k == STD_ARRAY_MAT ) { const Mat* vv = (const Mat*)obj; - CV_Assert(i > 0 && i < sz.height); + CV_Assert(i >= 0 && i < sz.height); return vv[i].isContinuous(); } @@ -948,21 +948,21 @@ bool _InputArray::isSubmatrix(int i) const if( k == STD_VECTOR_MAT ) { const std::vector& vv = *(const std::vector*)obj; - CV_Assert((size_t)i < vv.size()); + CV_Assert(i >= 0 && (size_t)i < vv.size()); return vv[i].isSubmatrix(); } if( k == STD_ARRAY_MAT ) { const Mat* vv = (const Mat*)obj; - CV_Assert(i < sz.height); + CV_Assert(i >= 0 && i < sz.height); return vv[i].isSubmatrix(); } if( k == STD_VECTOR_UMAT ) { const std::vector& vv = *(const std::vector*)obj; - CV_Assert((size_t)i < vv.size()); + CV_Assert(i >= 0 && (size_t)i < vv.size()); return vv[i].isSubmatrix(); } @@ -993,9 +993,7 @@ size_t _InputArray::offset(int i) const if( k == STD_VECTOR_MAT ) { const std::vector& vv = *(const std::vector*)obj; - if( i < 0 ) - return 1; - CV_Assert( i < (int)vv.size() ); + CV_Assert( i >= 0 && i < (int)vv.size() ); return (size_t)(vv[i].ptr() - vv[i].datastart); } @@ -1003,16 +1001,14 @@ size_t _InputArray::offset(int i) const if( k == STD_ARRAY_MAT ) { const Mat* vv = (const Mat*)obj; - if( i < 0 ) - return 1; - CV_Assert( i < sz.height ); + CV_Assert( i >= 0 && i < sz.height ); return (size_t)(vv[i].ptr() - vv[i].datastart); } if( k == STD_VECTOR_UMAT ) { const std::vector& vv = *(const std::vector*)obj; - CV_Assert((size_t)i < vv.size()); + CV_Assert(i >= 0 && (size_t)i < vv.size()); return vv[i].offset; } @@ -1026,7 +1022,7 @@ size_t _InputArray::offset(int i) const if (k == STD_VECTOR_CUDA_GPU_MAT) { const std::vector& vv = *(const std::vector*)obj; - CV_Assert((size_t)i < vv.size()); + CV_Assert(i >= 0 && (size_t)i < vv.size()); return (size_t)(vv[i].data - vv[i].datastart); } @@ -1056,25 +1052,21 @@ size_t _InputArray::step(int i) const if( k == STD_VECTOR_MAT ) { const std::vector& vv = *(const std::vector*)obj; - if( i < 0 ) - return 1; - CV_Assert( i < (int)vv.size() ); + CV_Assert( i >= 0 && i < (int)vv.size() ); return vv[i].step; } if( k == STD_ARRAY_MAT ) { const Mat* vv = (const Mat*)obj; - if( i < 0 ) - return 1; - CV_Assert( i < sz.height ); + CV_Assert( i >= 0 && i < sz.height ); return vv[i].step; } if( k == STD_VECTOR_UMAT ) { const std::vector& vv = *(const std::vector*)obj; - CV_Assert((size_t)i < vv.size()); + CV_Assert(i >= 0 && (size_t)i < vv.size()); return vv[i].step; } @@ -1086,7 +1078,7 @@ size_t _InputArray::step(int i) const if (k == STD_VECTOR_CUDA_GPU_MAT) { const std::vector& vv = *(const std::vector*)obj; - CV_Assert((size_t)i < vv.size()); + CV_Assert(i >= 0 && (size_t)i < vv.size()); return vv[i].step; } diff --git a/modules/core/test/test_mat.cpp b/modules/core/test/test_mat.cpp index 0bc3961fe2f856f3a140d9026adf227559648851..a2426ad977837c6b39e03f77daff39b77332cd02 100644 --- a/modules/core/test/test_mat.cpp +++ b/modules/core/test/test_mat.cpp @@ -9,6 +9,8 @@ #include "opencv2/core/eigen.hpp" #endif +#include "opencv2/core/cuda.hpp" + namespace opencv_test { namespace { class Core_ReduceTest : public cvtest::BaseTest @@ -1984,6 +1986,157 @@ TEST(Core_InputArray, fetch_MatExpr) } +#ifdef CV_CXX11 +class TestInputArrayRangeChecking { + static const char *kind2str(cv::_InputArray ia) + { + switch (ia.kind()) + { + #define C(x) case cv::_InputArray::x: return #x + C(MAT); + C(UMAT); + C(EXPR); + C(MATX); + C(STD_VECTOR); + C(STD_ARRAY); + C(NONE); + C(STD_VECTOR_VECTOR); + C(STD_BOOL_VECTOR); + C(STD_VECTOR_MAT); + C(STD_ARRAY_MAT); + C(STD_VECTOR_UMAT); + C(CUDA_GPU_MAT); + C(STD_VECTOR_CUDA_GPU_MAT); + #undef C + default: + return ""; + } + } + + static void banner(cv::_InputArray ia, const char *label, const char *name) + { + std::cout << std::endl + << label << " = " << name << ", Kind: " << kind2str(ia) + << std::endl; + } + + template + static void testA(I ia, F f, const char *mfname) + { + banner(ia, "f", mfname); + EXPECT_THROW(f(ia, -1), cv::Exception) + << "f(ia, " << -1 << ") should throw cv::Exception"; + for (int i = 0; i < int(ia.size()); i++) + { + EXPECT_NO_THROW(f(ia, i)) + << "f(ia, " << i << ") should not throw an exception"; + } + EXPECT_THROW(f(ia, int(ia.size())), cv::Exception) + << "f(ia, " << ia.size() << ") should throw cv::Exception"; + } + + template + static void testB(I ia, F f, const char *mfname) + { + banner(ia, "f", mfname); + EXPECT_THROW(f(ia, -1), cv::Exception) + << "f(ia, " << -1 << ") should throw cv::Exception"; + for (int i = 0; i < int(ia.size()); i++) + { + EXPECT_NO_THROW(f(ia, i)) + << "f(ia, " << i << ") should not throw an exception"; + } + EXPECT_THROW(f(ia, int(ia.size())), cv::Exception) + << "f(ia, " << ia.size() << ") should throw cv::Exception"; + } + + static void test_isContinuous() + { + auto f = [](cv::_InputArray ia, int i) { (void)ia.isContinuous(i); }; + + cv::Mat M; + cv::UMat uM; + + std::vector vec = {M, M}; + std::array arr = {M, M}; + std::vector uvec = {uM, uM}; + + testA(vec, f, "isContinuous"); + testA(arr, f, "isContinuous"); + testA(uvec, f, "isContinuous"); + } + + static void test_isSubmatrix() + { + auto f = [](cv::_InputArray ia, int i) { (void)ia.isSubmatrix(i); }; + + cv::Mat M; + cv::UMat uM; + + std::vector vec = {M, M}; + std::array arr = {M, M}; + std::vector uvec = {uM, uM}; + + testA(vec, f, "isSubmatrix"); + testA(arr, f, "isSubmatrix"); + testA(uvec, f, "isSubmatrix"); + } + + static void test_offset() + { + auto f = [](cv::_InputArray ia, int i) { return ia.offset(i); }; + + cv::Mat M; + cv::UMat uM; + cv::cuda::GpuMat gM; + + std::vector vec = {M, M}; + std::array arr = {M, M}; + std::vector uvec = {uM, uM}; + std::vector gvec = {gM, gM}; + + testB(vec, f, "offset"); + testB(arr, f, "offset"); + testB(uvec, f, "offset"); + testB(gvec, f, "offset"); + } + + static void test_step() + { + auto f = [](cv::_InputArray ia, int i) { return ia.step(i); }; + + cv::Mat M; + cv::UMat uM; + cv::cuda::GpuMat gM; + + std::vector vec = {M, M}; + std::array arr = {M, M}; + std::vector uvec = {uM, uM}; + std::vector gvec = {gM, gM}; + + testB(vec, f, "step"); + testB(arr, f, "step"); + testB(uvec, f, "step"); + testB(gvec, f, "step"); + } + +public: + static void run() + { + test_isContinuous(); + test_isSubmatrix(); + test_offset(); + test_step(); + } +}; + +TEST(Core_InputArray, range_checking) +{ + TestInputArrayRangeChecking::run(); +} +#endif + + TEST(Core_Vectors, issue_13078) { float floats_[] = { 1, 2, 3, 4, 5, 6, 7, 8 };