From b04ed5956e9e87a4dcbf7ee0ee2d830116360226 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Wed, 17 May 2017 17:36:48 +0300 Subject: [PATCH] Fixed several issues found by static analysis in core module --- modules/core/include/opencv2/core/mat.inl.hpp | 4 +- modules/core/include/opencv2/core/types.hpp | 3 +- modules/core/src/arithm.cpp | 2 +- modules/core/src/array.cpp | 3 +- modules/core/src/copy.cpp | 1 + modules/core/src/matrix.cpp | 6 +- modules/core/src/ocl.cpp | 2 +- modules/core/src/out.cpp | 2 +- modules/core/src/parallel_pthreads.cpp | 4 +- modules/core/src/persistence.cpp | 94 ++++++++++++++++++--------- modules/core/src/rand.cpp | 20 +++--- modules/core/src/stat.cpp | 91 +++++++++++++------------- modules/core/src/umatrix.cpp | 1 + 13 files changed, 139 insertions(+), 94 deletions(-) diff --git a/modules/core/include/opencv2/core/mat.inl.hpp b/modules/core/include/opencv2/core/mat.inl.hpp index ce8f6e9..97623b5 100644 --- a/modules/core/include/opencv2/core/mat.inl.hpp +++ b/modules/core/include/opencv2/core/mat.inl.hpp @@ -872,7 +872,7 @@ size_t Mat::step1(int i) const inline bool Mat::empty() const { - return data == 0 || total() == 0; + return data == 0 || total() == 0 || dims == 0; } inline @@ -3730,7 +3730,7 @@ size_t UMat::step1(int i) const inline bool UMat::empty() const { - return u == 0 || total() == 0; + return u == 0 || total() == 0 || dims == 0; } inline diff --git a/modules/core/include/opencv2/core/types.hpp b/modules/core/include/opencv2/core/types.hpp index 13cbe68..45a9674 100644 --- a/modules/core/include/opencv2/core/types.hpp +++ b/modules/core/include/opencv2/core/types.hpp @@ -1040,7 +1040,8 @@ Complex<_Tp> operator / (const Complex<_Tp>& a, const Complex<_Tp>& b) template static inline Complex<_Tp>& operator /= (Complex<_Tp>& a, const Complex<_Tp>& b) { - return (a = a / b); + a = a / b; + return a; } template static inline diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index 9c2c126..cbc604d 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -523,7 +523,7 @@ static bool ocl_arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, float usrdata_f[3]; int i, n = oclop == OCL_OP_MUL_SCALE || oclop == OCL_OP_DIV_SCALE || oclop == OCL_OP_RDIV_SCALE || oclop == OCL_OP_RECIP_SCALE ? 1 : oclop == OCL_OP_ADDW ? 3 : 0; - if( n > 0 && wdepth == CV_32F ) + if( usrdata && n > 0 && wdepth == CV_32F ) { for( i = 0; i < n; i++ ) usrdata_f[i] = (float)usrdata_d[i]; diff --git a/modules/core/src/array.cpp b/modules/core/src/array.cpp index d22f9c2..b428819 100644 --- a/modules/core/src/array.cpp +++ b/modules/core/src/array.cpp @@ -545,7 +545,7 @@ cvCreateSparseMat( int dims, const int* sizes, int type ) if( pix_size == 0 ) CV_Error( CV_StsUnsupportedFormat, "invalid array data type" ); - if( dims <= 0 || dims > CV_MAX_DIM_HEAP ) + if( dims <= 0 || dims > CV_MAX_DIM ) CV_Error( CV_StsOutOfRange, "bad number of dimensions" ); if( !sizes ) @@ -1839,6 +1839,7 @@ cvPtr2D( const CvArr* arr, int y, int x, int* _type ) } else if( CV_IS_SPARSE_MAT( arr )) { + CV_Assert(((CvSparseMat*)arr)->dims == 2); int idx[] = { y, x }; ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, _type, 1, 0 ); } diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index b136874..ec039d4 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -448,6 +448,7 @@ Mat& Mat::operator = (const Scalar& s) for( size_t j = 0; j < elsize; j += blockSize ) { size_t sz = MIN(blockSize, elsize - j); + CV_Assert(sz <= sizeof(scalar)); memcpy( dptr + j, scalar, sz ); } } diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 8a4199f..50a0856 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -5786,10 +5786,10 @@ void minMaxLoc( const SparseMat& src, double* _minval, double* _maxval, int* _mi else CV_Error( CV_StsUnsupportedFormat, "Only 32f and 64f are supported" ); - if( _minidx ) + if( _minidx && minidx ) for( i = 0; i < d; i++ ) _minidx[i] = minidx[i]; - if( _maxidx ) + if( _maxidx && maxidx ) for( i = 0; i < d; i++ ) _maxidx[i] = maxidx[i]; } @@ -5898,7 +5898,7 @@ _IplImage::_IplImage(const cv::Mat& m) CvSparseMat* cvCreateSparseMat(const cv::SparseMat& sm) { - if( !sm.hdr ) + if( !sm.hdr || sm.hdr->dims > (int)cv::SparseMat::MAX_DIM) return 0; CvSparseMat* m = cvCreateSparseMat(sm.hdr->dims, sm.hdr->size, sm.type()); diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 047dbae..c519ad8 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -1204,7 +1204,7 @@ not_found: if (!configuration) return NULL; // suppress messages on stderr - std::cerr << "ERROR: Requested OpenCL device not found, check configuration: " << (configuration == NULL ? "" : configuration) << std::endl + std::cerr << "ERROR: Requested OpenCL device not found, check configuration: " << configuration << std::endl << " Platform: " << (platform.length() == 0 ? "any" : platform) << std::endl << " Device types: "; for (size_t t = 0; t < deviceTypes.size(); t++) diff --git a/modules/core/src/out.cpp b/modules/core/src/out.cpp index 343fd0a..13c2b8f 100644 --- a/modules/core/src/out.cpp +++ b/modules/core/src/out.cpp @@ -103,7 +103,7 @@ namespace cv } else { - sprintf(floatFormat, "%%.%dg", std::min(precision, 20)); + snprintf(floatFormat, 8, "%%.%dg", std::min(precision, 20)); } switch(mtx.depth()) diff --git a/modules/core/src/parallel_pthreads.cpp b/modules/core/src/parallel_pthreads.cpp index 96ddfe7..83768cd 100644 --- a/modules/core/src/parallel_pthreads.cpp +++ b/modules/core/src/parallel_pthreads.cpp @@ -141,10 +141,10 @@ private: pthread_t m_posix_thread; pthread_mutex_t m_thread_mutex; pthread_cond_t m_cond_thread_task; - bool m_task_start; + volatile bool m_task_start; ThreadManager* m_parent; - ForThreadState m_state; + volatile ForThreadState m_state; size_t m_id; }; diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index d7aa144..e7ab982 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -367,6 +367,11 @@ namespace base64 void check_dt(const char* dt); private: + // disable copy and assignment + Base64Writer(const Base64Writer &); + Base64Writer & operator=(const Base64Writer &); + + private: Base64ContextEmitter * emitter; std::string data_type_string; @@ -1376,7 +1381,8 @@ static char* icvYMLParseBase64(CvFileStorage* fs, char* ptr, int indent, CvFileN beg = end; icvYMLGetMultilineStringContent( fs, beg, indent, beg, end ); } - if ( !base64::base64_valid(base64_buffer.data(), 0U, base64_buffer.size()) ) + if ( base64_buffer.empty() || + !base64::base64_valid(base64_buffer.data(), 0U, base64_buffer.size()) ) CV_PARSE_ERROR( "Invalid Base64 data." ); /* buffer for decoded data(exclude header) */ @@ -1451,7 +1457,7 @@ static char* icvYMLParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node, int parent_flags, int min_indent ) { - char buf[CV_FS_MAX_LEN + 1024]; + char buf[CV_FS_MAX_LEN + 1024] = {0}; char* endptr = 0; char c = ptr[0], d = ptr[1]; int is_parent_flow = CV_NODE_IS_FLOW(parent_flags); @@ -1668,7 +1674,7 @@ force_int: { int new_min_indent = min_indent + !is_parent_flow; int struct_flags = CV_NODE_FLOW + (c == '{' ? CV_NODE_MAP : CV_NODE_SEQ); - int is_simple = 1; + bool is_simple = true; icvFSCreateCollection( fs, CV_NODE_TYPE(struct_flags) + (node->info ? CV_NODE_USER : 0), node ); @@ -1706,16 +1712,18 @@ force_int: break; elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 ); } + CV_Assert(elem); ptr = icvYMLParseValue( fs, ptr, elem, struct_flags, new_min_indent ); if( CV_NODE_IS_MAP(struct_flags) ) elem->tag |= CV_NODE_NAMED; - is_simple &= !CV_NODE_IS_COLLECTION(elem->tag); + is_simple = is_simple && !CV_NODE_IS_COLLECTION(elem->tag); } node->data.seq->flags |= is_simple ? CV_NODE_SEQ_SIMPLE : 0; } else { - int indent, struct_flags, is_simple; + int indent, struct_flags; + bool is_simple; if( is_parent_flow || c != '-' ) { @@ -1760,7 +1768,7 @@ force_string: (node->info ? CV_NODE_USER : 0), node ); indent = (int)(ptr - fs->buffer_start); - is_simple = 1; + is_simple = true; for(;;) { @@ -1778,12 +1786,12 @@ force_string: elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 ); } - + CV_Assert(elem); ptr = icvYMLSkipSpaces( fs, ptr, indent + 1, INT_MAX ); ptr = icvYMLParseValue( fs, ptr, elem, struct_flags, indent + 1 ); if( CV_NODE_IS_MAP(struct_flags) ) elem->tag |= CV_NODE_NAMED; - is_simple &= !CV_NODE_IS_COLLECTION(elem->tag); + is_simple = is_simple && !CV_NODE_IS_COLLECTION(elem->tag); ptr = icvYMLSkipSpaces( fs, ptr, 0, INT_MAX ); if( ptr - fs->buffer_start != indent ) @@ -2355,7 +2363,8 @@ static char* icvXMLParseBase64(CvFileStorage* fs, char* ptr, CvFileNode * node) beg = end; icvXMLGetMultilineStringContent( fs, beg, beg, end ); } - if ( !base64::base64_valid(base64_buffer.data(), 0U, base64_buffer.size()) ) + if ( base64_buffer.empty() || + !base64::base64_valid(base64_buffer.data(), 0U, base64_buffer.size()) ) CV_PARSE_ERROR( "Invalid Base64 data." ); /* alloc buffer for all decoded data(include header) */ @@ -2402,7 +2411,7 @@ icvXMLParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node, int value_type CV_DEFAULT(CV_NODE_NONE)) { CvFileNode *elem = node; - int have_space = 1, is_simple = 1; + bool have_space = true, is_simple = true; int is_user_type = CV_NODE_IS_USER(value_type); memset( node, 0, sizeof(*node) ); @@ -2416,7 +2425,7 @@ icvXMLParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node, if( cv_isspace(c) || c == '\0' || (c == '<' && ptr[1] == '!' && ptr[2] == '-') ) { ptr = icvXMLSkipSpaces( fs, ptr, 0 ); - have_space = 1; + have_space = true; c = *ptr; } @@ -2482,7 +2491,7 @@ icvXMLParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node, elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 ); else elem = cvGetFileNode( fs, node, key, 1 ); - + CV_Assert(elem); if (!is_binary_string) ptr = icvXMLParseValue( fs, ptr, elem, elem_type); else { @@ -2493,12 +2502,12 @@ icvXMLParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node, if( !is_noname ) elem->tag |= CV_NODE_NAMED; - is_simple &= !CV_NODE_IS_COLLECTION(elem->tag); + is_simple = is_simple && !CV_NODE_IS_COLLECTION(elem->tag); elem->info = info; ptr = icvXMLParseTag( fs, ptr, &key2, &list, &tag_type ); if( tag_type != CV_XML_CLOSING_TAG || key2 != key ) CV_PARSE_ERROR( "Mismatched closing tag" ); - have_space = 1; + have_space = true; } else { @@ -2547,7 +2556,7 @@ icvXMLParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node, else { // string - char buf[CV_FS_MAX_LEN+16]; + char buf[CV_FS_MAX_LEN+16] = {0}; int i = 0, len, is_quoted = 0; elem->tag = CV_NODE_STRING; if( c == '\"' ) @@ -2630,7 +2639,7 @@ icvXMLParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node, if( !CV_NODE_IS_COLLECTION(value_type) && value_type != CV_NODE_NONE ) break; - have_space = 0; + have_space = false; } } @@ -2708,6 +2717,7 @@ icvXMLParseTag( CvFileStorage* fs, char* ptr, CvStringHashNode** _tag, while( cv_isalnum(c) || c == '_' || c == '-' ); attrname = cvGetHashedKey( fs, ptr, (int)(endptr - ptr), 1 ); + CV_Assert(attrname); ptr = endptr; if( !tagname ) @@ -2840,6 +2850,7 @@ icvXMLParse( CvFileStorage* fs ) CvFileNode* root_node; ptr = icvXMLParseTag( fs, ptr, &key, &list, &tag_type ); if( tag_type != CV_XML_OPENING_TAG || + !key || strcmp(key->str.ptr,"opencv_storage") != 0 ) CV_PARSE_ERROR( " tag is missing" ); @@ -3665,6 +3676,9 @@ static char* icvJSONParseMap( CvFileStorage* fs, char* ptr, CvFileNode* node ); static char* icvJSONParseSeq( CvFileStorage* fs, char* ptr, CvFileNode* node ) { + if (!ptr) + CV_PARSE_ERROR( "ptr is NULL" ); + if ( *ptr != '[' ) CV_PARSE_ERROR( "'[' - left-brace of seq is missing" ); else @@ -3703,6 +3717,9 @@ static char* icvJSONParseSeq( CvFileStorage* fs, char* ptr, CvFileNode* node ) CV_PARSE_ERROR( "Unexpected character" ); } + if (!ptr) + CV_PARSE_ERROR("ptr is NULL"); + if ( *ptr != ']' ) CV_PARSE_ERROR( "']' - right-brace of seq is missing" ); else @@ -3713,6 +3730,9 @@ static char* icvJSONParseSeq( CvFileStorage* fs, char* ptr, CvFileNode* node ) static char* icvJSONParseMap( CvFileStorage* fs, char* ptr, CvFileNode* node ) { + if (!ptr) + CV_PARSE_ERROR("ptr is NULL"); + if ( *ptr != '{' ) CV_PARSE_ERROR( "'{' - left-brace of map is missing" ); else @@ -3731,6 +3751,8 @@ static char* icvJSONParseMap( CvFileStorage* fs, char* ptr, CvFileNode* node ) { CvFileNode* child = 0; ptr = icvJSONParseKey( fs, ptr, node, &child ); + if ( ptr == 0 || fs->dummy_eof ) + break; ptr = icvJSONSkipSpaces( fs, ptr ); if ( ptr == 0 || fs->dummy_eof ) break; @@ -3774,6 +3796,9 @@ static char* icvJSONParseMap( CvFileStorage* fs, char* ptr, CvFileNode* node ) CV_PARSE_ERROR( "Unexpected character" ); } + if (!ptr) + CV_PARSE_ERROR("ptr is NULL"); + if ( *ptr != '}' ) CV_PARSE_ERROR( "'}' - right-brace of map is missing" ); else @@ -4180,6 +4205,7 @@ cvOpenFileStorage( const char* query, CvMemStorage* dststorage, int flags, const CV_Error( CV_StsBadFlag, "CV_STORAGE_APPEND and CV_STORAGE_MEMORY are not currently compatible" ); fs = (CvFileStorage*)cvAlloc( sizeof(*fs) ); + CV_Assert(fs); memset( fs, 0, sizeof(*fs)); fs->memstorage = cvCreateMemStorage( default_block_size ); @@ -4344,6 +4370,7 @@ cvOpenFileStorage( const char* query, CvMemStorage* dststorage, int flags, const } icvCloseFile( fs ); fs->file = fopen( fs->filename, "r+t" ); + CV_Assert(fs->file); fseek( fs->file, last_occurence, SEEK_SET ); // replace the last "" with " ", which has the same length icvPuts( fs, " " ); @@ -4397,6 +4424,7 @@ cvOpenFileStorage( const char* query, CvMemStorage* dststorage, int flags, const { icvCloseFile( fs ); fs->file = fopen( fs->filename, "r+t" ); + CV_Assert(fs->file); fseek( fs->file, roffset, SEEK_END ); fputs( ",", fs->file ); } @@ -5316,7 +5344,7 @@ icvReadMatND( CvFileStorage* fs, CvFileNode* node ) const char* dt; CvFileNode* data; CvFileNode* sizes_node; - int sizes[CV_MAX_DIM], dims, elem_type; + int sizes[CV_MAX_DIM] = {0}, dims, elem_type; int i, total_size; sizes_node = cvGetFileNodeByName( fs, node, "sizes" ); @@ -5341,7 +5369,10 @@ icvReadMatND( CvFileStorage* fs, CvFileNode* node ) for( total_size = CV_MAT_CN(elem_type), i = 0; i < dims; i++ ) + { + CV_Assert(sizes[i]); total_size *= sizes[i]; + } int nelems = icvFileNodeSeqLen( data ); @@ -5481,7 +5512,7 @@ icvReadSparseMat( CvFileStorage* fs, CvFileNode* node ) dims = CV_NODE_IS_SEQ(sizes_node->tag) ? sizes_node->data.seq->total : CV_NODE_IS_INT(sizes_node->tag) ? 1 : -1; - if( dims <= 0 || dims > CV_MAX_DIM_HEAP ) + if( dims <= 0 || dims > CV_MAX_DIM) CV_Error( CV_StsParseError, "Could not determine sparse matrix dimensionality" ); cvReadRawData( fs, sizes_node, sizes, "i" ); @@ -5578,6 +5609,7 @@ icvWriteImage( CvFileStorage* fs, const char* name, } depth = IPL2CV_DEPTH(image->depth); + CV_Assert(depth < 9); sprintf( dt_buf, "%d%c", image->nChannels, icvTypeSymbol[depth] ); dt = dt_buf + (dt_buf[2] == '\0' && dt_buf[0] == '1'); cvWriteString( fs, "dt", dt, 0 ); @@ -5620,7 +5652,7 @@ icvReadImage( CvFileStorage* fs, CvFileNode* node ) elem_type = icvDecodeSimpleFormat( dt ); data_order = cvReadStringByName( fs, node, "layout", "interleaved" ); - if( strcmp( data_order, "interleaved" ) != 0 ) + if( !data_order || strcmp( data_order, "interleaved" ) != 0 ) CV_Error( CV_StsError, "Only interleaved images can be read" ); data = cvGetFileNodeByName( fs, node, "data" ); @@ -5976,6 +6008,7 @@ icvReadSeq( CvFileStorage* fs, CvFileNode* node ) if( header_node ) { + CV_Assert(header_dt); cvReadRawData( fs, header_node, (char*)seq + sizeof(CvSeq), header_dt ); } else if( rect_node ) @@ -6048,6 +6081,7 @@ icvReadSeqTree( CvFileStorage* fs, CvFileNode* node ) CvSeq* seq; int level; seq = (CvSeq*)cvRead( fs, elem ); + CV_Assert(seq); level = cvReadIntByName( fs, elem, "level", -1 ); if( level < 0 ) CV_Error( CV_StsParseError, "All the sequence tree nodes should contain \"level\" field" ); @@ -6352,7 +6386,10 @@ icvReadGraph( CvFileStorage* fs, CvFileNode* node ) graph = cvCreateGraph( flags, header_size, vtx_size, edge_size, fs->dststorage ); if( header_node ) + { + CV_Assert(header_dt); cvReadRawData( fs, header_node, (char*)graph + sizeof(CvGraph), header_dt ); + } read_buf_size = MAX( src_vtx_size*3, 1 << 16 ); read_buf_size = MAX( src_edge_size*3, read_buf_size ); @@ -7020,17 +7057,20 @@ void* FileNode::readObj() const return cvRead( (CvFileStorage*)fs, (CvFileNode*)node ); } +static const FileNodeIterator::SeqReader emptyReader = {0, 0, 0, 0, 0, 0, 0, 0}; + FileNodeIterator::FileNodeIterator() { fs = 0; container = 0; - reader.ptr = 0; + reader = emptyReader; remaining = 0; } FileNodeIterator::FileNodeIterator(const CvFileStorage* _fs, const CvFileNode* _node, size_t _ofs) { + reader = emptyReader; if( _fs && _node && CV_NODE_TYPE(_node->tag) != CV_NODE_NONE ) { int node_type = _node->tag & FileNode::TYPE_MASK; @@ -7053,7 +7093,6 @@ FileNodeIterator::FileNodeIterator(const CvFileStorage* _fs, { fs = 0; container = 0; - reader.ptr = 0; remaining = 0; } } @@ -7916,13 +7955,13 @@ class base64::RawDataToBinaryConvertor { public: - RawDataToBinaryConvertor(const void* src, int len, const char* dt) + RawDataToBinaryConvertor(const void* src, int len, const std::string & dt) : beg(reinterpret_cast(src)) , cur(0) , end(0) { CV_Assert(src); - CV_Assert(dt); + CV_Assert(!dt.empty()); CV_Assert(len > 0); /* calc step and to_binary_funcs */ @@ -7931,7 +7970,7 @@ public: end = beg; cur = beg; - step = ::icvCalcStructSize(dt, 0); + step = ::icvCalcStructSize(dt.c_str(), 0); end = beg + step * static_cast(len); } @@ -7963,7 +8002,7 @@ private: }; private: - void make_to_binary_funcs(const char* dt) + void make_to_binary_funcs(const std::string &dt) { size_t cnt = 0; size_t offset = 0; @@ -8225,10 +8264,7 @@ base64::Base64Writer::Base64Writer(::CvFileStorage * fs) void base64::Base64Writer::write(const void* _data, size_t len, const char* dt) { check_dt(dt); - - RawDataToBinaryConvertor convertor( - _data, static_cast(len), data_type_string.c_str() - ); + RawDataToBinaryConvertor convertor(_data, static_cast(len), data_type_string); emitter->write(convertor); } diff --git a/modules/core/src/rand.cpp b/modules/core/src/rand.cpp index 094cde9..d0abc97 100644 --- a/modules/core/src/rand.cpp +++ b/modules/core/src/rand.cpp @@ -500,7 +500,9 @@ void RNG::fill( InputOutputArray _mat, int disttype, Mat mat = _mat.getMat(), _param1 = _param1arg.getMat(), _param2 = _param2arg.getMat(); int depth = mat.depth(), cn = mat.channels(); AutoBuffer _parambuf; - int j, k, fast_int_mode = 0, smallFlag = 1; + int j, k; + bool fast_int_mode = false; + bool smallFlag = true; RandFunc func = 0; RandnScaleFunc scaleFunc = 0; @@ -553,7 +555,7 @@ void RNG::fill( InputOutputArray _mat, int disttype, if( depth <= CV_32S ) { ip = (Vec2i*)(parambuf + cn*2); - for( j = 0, fast_int_mode = 1; j < cn; j++ ) + for( j = 0, fast_int_mode = true; j < cn; j++ ) { double a = std::min(p1[j], p2[j]); double b = std::max(p1[j], p2[j]); @@ -568,9 +570,9 @@ void RNG::fill( InputOutputArray _mat, int disttype, int idiff = ip[j][0] = cvFloor(b) - ip[j][1] - 1; double diff = b - a; - fast_int_mode &= diff <= 4294967296. && (idiff & (idiff+1)) == 0; + fast_int_mode = fast_int_mode && diff <= 4294967296. && (idiff & (idiff+1)) == 0; if( fast_int_mode ) - smallFlag &= idiff <= 255; + smallFlag = smallFlag && (idiff <= 255); else { if( diff > INT_MAX ) @@ -596,7 +598,7 @@ void RNG::fill( InputOutputArray _mat, int disttype, } } - func = randTab[fast_int_mode][depth]; + func = randTab[fast_int_mode ? 1 : 0][depth]; } else { @@ -687,9 +689,9 @@ void RNG::fill( InputOutputArray _mat, int disttype, buf.allocate(blockSize*cn*4); param = (uchar*)(double*)buf; - if( ip ) + if( depth <= CV_32S ) { - if( ds ) + if( !fast_int_mode ) { DivStruct* p = (DivStruct*)param; for( j = 0; j < blockSize*cn; j += cn ) @@ -704,7 +706,7 @@ void RNG::fill( InputOutputArray _mat, int disttype, p[j + k] = ip[k]; } } - else if( fp ) + else if( depth == CV_32F ) { Vec2f* p = (Vec2f*)param; for( j = 0; j < blockSize*cn; j += cn ) @@ -732,7 +734,7 @@ void RNG::fill( InputOutputArray _mat, int disttype, int len = std::min(total - j, blockSize); if( disttype == CV_RAND_UNI ) - func( ptr, len*cn, &state, param, smallFlag != 0 ); + func( ptr, len*cn, &state, param, smallFlag ); else { randn_0_1_32f(nbuf, len*cn, &state); diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index a655e11..39f0794 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -76,6 +76,13 @@ struct Sum_SIMD } }; +template +inline void addChannels(DT * dst, ST * buf, int cn) +{ + for (int i = 0; i < 4; ++i) + dst[i % cn] += buf[i]; +} + #if CV_SSE2 template <> @@ -113,9 +120,7 @@ struct Sum_SIMD int CV_DECL_ALIGNED(16) ar[4]; _mm_store_si128((__m128i*)ar, v_sum); - for (int i = 0; i < 4; i += cn) - for (int j = 0; j < cn; ++j) - dst[j] += ar[j + i]; + addChannels(dst, ar, cn); return x / cn; } @@ -143,9 +148,7 @@ struct Sum_SIMD _mm_store_pd(ar, v_sum0); _mm_store_pd(ar + 2, v_sum1); - for (int i = 0; i < 4; i += cn) - for (int j = 0; j < cn; ++j) - dst[j] += ar[j + i]; + addChannels(dst, ar, cn); return x / cn; } @@ -174,9 +177,7 @@ struct Sum_SIMD _mm_store_pd(ar, v_sum0); _mm_store_pd(ar + 2, v_sum1); - for (int i = 0; i < 4; i += cn) - for (int j = 0; j < cn; ++j) - dst[j] += ar[j + i]; + addChannels(dst, ar, cn); return x / cn; } @@ -220,9 +221,7 @@ struct Sum_SIMD unsigned int CV_DECL_ALIGNED(16) ar[4]; vst1q_u32(ar, v_sum); - for (int i = 0; i < 4; i += cn) - for (int j = 0; j < cn; ++j) - dst[j] += ar[j + i]; + addChannels(dst, ar, cn); return x / cn; } @@ -263,9 +262,7 @@ struct Sum_SIMD int CV_DECL_ALIGNED(16) ar[4]; vst1q_s32(ar, v_sum); - for (int i = 0; i < 4; i += cn) - for (int j = 0; j < cn; ++j) - dst[j] += ar[j + i]; + addChannels(dst, ar, cn); return x / cn; } @@ -296,9 +293,7 @@ struct Sum_SIMD unsigned int CV_DECL_ALIGNED(16) ar[4]; vst1q_u32(ar, v_sum); - for (int i = 0; i < 4; i += cn) - for (int j = 0; j < cn; ++j) - dst[j] += ar[j + i]; + addChannels(dst, ar, cn); return x / cn; } @@ -329,9 +324,7 @@ struct Sum_SIMD int CV_DECL_ALIGNED(16) ar[4]; vst1q_s32(ar, v_sum); - for (int i = 0; i < 4; i += cn) - for (int j = 0; j < cn; ++j) - dst[j] += ar[j + i]; + addChannels(dst, ar, cn); return x / cn; } @@ -748,6 +741,16 @@ struct SumSqr_SIMD } }; +template +inline void addSqrChannels(T * sum, T * sqsum, T * buf, int cn) +{ + for (int i = 0; i < 4; ++i) + { + sum[i % cn] += buf[i]; + sqsum[i % cn] += buf[4 + i]; + } +} + #if CV_SSE2 template <> @@ -796,12 +799,7 @@ struct SumSqr_SIMD _mm_store_si128((__m128i*)ar, v_sum); _mm_store_si128((__m128i*)(ar + 4), v_sqsum); - for (int i = 0; i < 4; i += cn) - for (int j = 0; j < cn; ++j) - { - sum[j] += ar[j + i]; - sqsum[j] += ar[4 + j + i]; - } + addSqrChannels(sum, sqsum, ar, cn); return x / cn; } @@ -853,12 +851,7 @@ struct SumSqr_SIMD _mm_store_si128((__m128i*)ar, v_sum); _mm_store_si128((__m128i*)(ar + 4), v_sqsum); - for (int i = 0; i < 4; i += cn) - for (int j = 0; j < cn; ++j) - { - sum[j] += ar[j + i]; - sqsum[j] += ar[4 + j + i]; - } + addSqrChannels(sum, sqsum, ar, cn); return x / cn; } @@ -1144,6 +1137,8 @@ static bool ipp_sum(Mat &src, Scalar &_res) #if IPP_VERSION_X100 >= 700 int cn = src.channels(); + if (cn > 4) + return false; size_t total_size = src.total(); int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0; if( src.dims == 2 || (src.isContinuous() && cols > 0 && (size_t)rows*cols == total_size) ) @@ -1402,6 +1397,9 @@ static bool ipp_mean( Mat &src, Mat &mask, Scalar &ret ) #if IPP_VERSION_X100 >= 700 size_t total_size = src.total(); + int cn = src.channels(); + if (cn > 4) + return false; int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0; if( src.dims == 2 || (src.isContinuous() && mask.isContinuous() && cols > 0 && (size_t)rows*cols == total_size) ) { @@ -1471,7 +1469,7 @@ static bool ipp_mean( Mat &src, Mat &mask, Scalar &ret ) CV_INSTRUMENT_FUN_IPP(ippiMean, src.ptr(), (int)src.step[0], sz, res); if( status >= 0 ) { - for( int i = 0; i < src.channels(); i++ ) + for( int i = 0; i < cn; i++ ) ret[i] = res[i]; return true; } @@ -1560,9 +1558,12 @@ static bool ocl_meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv bool haveMask = _mask.kind() != _InputArray::NONE; int nz = haveMask ? -1 : (int)_src.total(); Scalar mean, stddev; + const int cn = _src.channels(); + if (cn > 4) + return false; { - int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + int type = _src.type(), depth = CV_MAT_DEPTH(type); bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0, isContinuous = _src.isContinuous(), isMaskContinuous = _mask.isContinuous(); @@ -1585,7 +1586,7 @@ static bool ocl_meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv wgs2_aligned <<= 1; wgs2_aligned >>= 1; - if ( (!doubleSupport && depth == CV_64F) || cn > 4 ) + if ( (!doubleSupport && depth == CV_64F) ) return false; char cvt[2][40]; @@ -1638,7 +1639,7 @@ static bool ocl_meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv } double total = nz != 0 ? 1.0 / nz : 0; - int k, j, cn = _src.channels(); + int k, j; for (int i = 0; i < cn; ++i) { mean[i] *= total; @@ -2975,8 +2976,10 @@ static bool ocl_norm( InputArray _src, int normType, InputArray _mask, double & if (d.isNVidia()) return false; #endif - - int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + const int cn = _src.channels(); + if (cn > 4) + return false; + int type = _src.type(), depth = CV_MAT_DEPTH(type); bool doubleSupport = d.doubleFPConfig() > 0, haveMask = _mask.kind() != _InputArray::NONE; @@ -3001,11 +3004,8 @@ static bool ocl_norm( InputArray _src, int normType, InputArray _mask, double & OCL_OP_SUM_SQR : (unstype ? OCL_OP_SUM : OCL_OP_SUM_ABS), _mask) ) return false; - if (!haveMask) - cn = 1; - double s = 0.0; - for (int i = 0; i < cn; ++i) + for (int i = 0; i < (haveMask ? cn : 1); ++i) s += sc[i]; result = normType == NORM_L1 || normType == NORM_L2SQR ? s : std::sqrt(s); @@ -3320,7 +3320,10 @@ static bool ocl_norm( InputArray _src1, InputArray _src2, int normType, InputArr #endif Scalar sc1, sc2; - int type = _src1.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + int cn = _src1.channels(); + if (cn > 4) + return false; + int type = _src1.type(), depth = CV_MAT_DEPTH(type); bool relative = (normType & NORM_RELATIVE) != 0; normType &= ~NORM_RELATIVE; bool normsum = normType == NORM_L1 || normType == NORM_L2 || normType == NORM_L2SQR; diff --git a/modules/core/src/umatrix.cpp b/modules/core/src/umatrix.cpp index 6991b40..ad61878 100644 --- a/modules/core/src/umatrix.cpp +++ b/modules/core/src/umatrix.cpp @@ -835,6 +835,7 @@ void UMat::copyTo(OutputArray _dst) const if( _dst.isUMat() ) { UMat dst = _dst.getUMat(); + CV_Assert(dst.u); if( u == dst.u && dst.offset == offset ) return; -- 2.7.4