You are on page 1of 16

PVS-Studio

OpenCV
:
: 29.03.2013
OpenCV - ,
. /++.
, BSD.
PVS-Studio.
OpenCV . 2500 .
1 .
cv::cvtColor() 415. ,
. ,
.


. , PVSStudio, , . ,
. : "Ok.
- . . ,
. ".
, . ,
. ,
OpenCV. .
, .
OpenCV. .
. , ,
. .
:
CV_IMPL CvGLCM* cvCreateGLCM(....)
{
CvGLCM* newGLCM = 0;
....
memset( newGLCM, 0, sizeof(newGLCM) );
....

}
V512 A call of the 'memset' function will lead to underflow of the buffer 'newGLCM'. cvtexture.cpp 138

:
CvDTreeSplit* CvDTree::find_split_cat_reg(....)
{
....
double** sum_ptr = 0;

.... // sum_ptr not in use


for( i = 0; i < mi; i++ )
{
R += counts[i];
rsum += sum[i];
sum[i] /= MAX(counts[i],1);
sum_ptr[i] = sum + i;
}
....
}
V522 Dereferencing of the null pointer 'sum_ptr' might take place. mltree.cpp 2001
. , , . ,
:
1. PVS-Studio .
. .
, .
2. PVS-Studio
. .
.


. , ,
, .
.
, , ,
PVS-Studio OpenCV. ,
,
. OpenCV,
,
.

Copy-Paste
PVS-Studio copy-paste.
. , augAssignAnd, augAssignOr,
augAssignXor, augAssignDivide . .
, ,
. , .
void MatOp::augAssignAnd(const MatExpr& expr, Mat& m) const
{
Mat temp;
expr.op->assign(expr, temp);
m &= temp;
}

void MatOp::augAssignOr(const MatExpr& expr, Mat& m) const


{
Mat temp;
expr.op->assign(expr, temp);
m |= temp;
}

void MatOp::augAssignDivide(const MatExpr& expr, Mat& m) const


{

Mat temp;
expr.op->assign(expr, temp);
m /= temp;
}

void MatOp::augAssignXor(const MatExpr& expr, Mat& m) const


{
Mat temp;
expr.op->assign(expr, temp);
m /= temp;
}
V524 It is odd that the body of 'augAssignXor' function is fully equivalent to the body of 'augAssignDivide'
function (matop.cpp, line 294). matop.cpp 318
, augAssignXor() , 'augAssignDivide().
. augAssignXor() : "m ^= temp;".

,
, copy-paste.
. , ,
. .

1. .
.
V640 The code's operational logic does not correspond with its formatting. The second statement will
always be executed. It is possible that curly brackets are missing. test_stereomatching.cpp 464
, 'if'.
.


, , , . ,
.
static jpc_enc_cp_t *cp_create(....)
{
....
ccp->sampgrdsubstepx = 0;
ccp->sampgrdsubstepx = 0;
....
}
V519 The 'ccp->sampgrdsubstepx' variable is assigned values twice successively. Perhaps this is a mistake.
Check lines: 414, 415. jpc_enc.c 415
, : ccp->sampgrdsubstepy = 0;.


typedef struct CvStereoCamera
{
....
float fundMatr[9]; /* fundamental matrix */
....
};
CvStereoCamera stereo;

void CvCalibFilter::Stop( bool calibrate )


{
....
for( i = 0; i < 9; i++ )
{
stereo.fundMatr[i] = stereo.fundMatr[i];
}

....
}
V570 The 'stereo.fundMatr[i]' variable is assigned to itself. calibfilter.cpp 339
. , -
.

, :
virtual CvBlob* Process(....)
{
....
while(!m_Collision && m_FGWeight>0)
{
....
break;
}
....
}
V612 An unconditional 'break' within a loop. blobtrackingmsfg.cpp 600
'continue'. 'break'.
.


int jpc_atoaf(char *s, int *numvalues, double **values)
{
char *cp;
....
while ((cp = strtok(0, delim))) {
if (cp != '\0') {
++n;
}

}
....
}
V528 It is odd that pointer to 'char' type is compared with the '\0' value. Probably meant: *cp != '\0'.
jpc_util.c 105
: jpc_util.c 123.
if(cp != '\0') . strtok() ,
. , . ,
: if(*cp != '\0').


, - .
dr3dr2:
CV_IMPL void cvComposeRT(
const CvMat* _rvec1, const CvMat* _tvec1,
const CvMat* _rvec2, const CvMat* _tvec2,
CvMat* _rvec3, CvMat* _tvec3,
CvMat* dr3dr1, CvMat* dr3dt1,
CvMat* dr3dr2, CvMat* dr3dt2,
CvMat* dt3dr1, CvMat* dt3dt1,
CvMat* dt3dr2, CvMat* dt3dt2)
{
....
if( _rvec3 || dr3dr1 || dr3dr1 )
....
}
V501 There are identical sub-expressions to the left and to the right of the '||' operator: _rvec3 || dr3dr1 ||
dr3dr1 calibration.cpp 415

cmptlut[2]:

bool Jpeg2KDecoder::readHeader()
{
....
cmptlut[0] = ....
cmptlut[1] = ....
cmptlut[2] = ....
if( cmptlut[0] < 0 || cmptlut[1] < 0 || cmptlut[0] < 0 )
result = false;
....
}
V501 There are identical sub-expressions 'cmptlut[0] < 0' to the left and to the right of the '||' operator.
grfmt_jpeg2000.cpp 215

dst_size.height :
CV_IMPL IplImage* icvCreateIsometricImage(....)
{
....
if( !dst || dst->depth != desired_depth ||
dst->nChannels != desired_num_channels ||
dst_size.width != src_size.width ||
dst_size.height != dst_size.height )
....
}
V501 There are identical sub-expressions to the left and to the right of the '!=' operator: dst_size.height !=
dst_size.height epilines.cpp 2118

:
void CvDTreeTrainData::read_params(....)

{
....
if( cat_var_count != cat_var_count ||
ord_var_count != ord_var_count )
CV_ERROR(CV_StsParseError,
"var_type is inconsistent with cat_var_count and ord_var_count");
....
}
V501 There are identical sub-expressions to the left and to the right of the '!=' operator: cat_var_count !=
cat_var_count tree.cpp 1415
V501 There are identical sub-expressions to the left and to the right of the '!=' operator: ord_var_count !=
ord_var_count tree.cpp 1415

, :

V501 There are identical sub-expressions to the left and to the right of the '==' operator: M.size() ==
M.size() imgwarp.cpp 3672
V501 There are identical sub-expressions to the left and to the right of the '&&' operator: data &&
dims >= 1 && data mat.hpp 434
V501 There are identical sub-expressions to the left and to the right of the '&&' operator: 0 <= d &&
_sizes && d <= 32 && _sizes matrix.cpp 186
V501 There are identical sub-expressions to the left and to the right of the '==' operator: M.size() ==
M.size() imgwarp.cpp 3685


, ,
. OpenCV . :
CV_IMPL CvStringHashNode*
cvGetHashedKey( CvFileStorage* fs, .... )
{
....
CvStringHash* map = fs->str_hash;

if( !fs )
return 0;
....
}
V595 The 'fs' pointer was utilized before it was verified against nullptr. Check lines: 617, 619.
persistence.cpp 617
void CvBlobTrackerAuto1::Process(IplImage* pImg, IplImage* pMask)
{
....
CvBlob* pBN = NewBlobList.GetBlob(i);
pBN->ID = m_NextBlobID;

if(pBN &&
pBN->w >= CV_BLOB_MINW &&
pBN->h >= CV_BLOB_MINH)
....
}
V595 The 'pBN' pointer was utilized before it was verified against nullptr. Check lines: 432, 434.
blobtrackingauto.cpp 432
, ,
V595. . PVS-Studio
.
. V595 , .
.
, .
, .


, - ,
. , ,
(). .
CAPDRIVERCAPS caps;

bool CvCaptureCAM_VFW::open( int wIndex )


{
....
memset( &caps, 0, sizeof(caps));
capDriverGetCaps( hWndC, &caps, sizeof(&caps));
....
}
V568 It's odd that the argument of sizeof() operator is the '& caps' expression. cap_vfw.cpp 409
capDriverGetCaps() CAPDRIVERCAPS, .

. , .
'latestCounts', 'latestPoints'.
class CV_EXPORTS CvCalibFilter
{
....
enum { MAX_CAMERAS = 3 };
int latestCounts[MAX_CAMERAS];
CvPoint2D32f* latestPoints[MAX_CAMERAS];
....
};

void CvCalibFilter::SetCameraCount( int count )


{
....
memset( latestCounts, 0, sizeof(latestPoints) );
....
}
V512 A call of the 'memset' function will lead to overflow of the buffer 'latestCounts'. calibfilter.cpp 238

64- .
32- . , 32-
'int'. 64- , .
, . -, 32-
. 64-,
. ,
.


, TDD
. .
TDD .
, .
, OpenCV.
void CV_Resize_Test::resize_1d(....)
{
....
for (int r = 0; r < cn; ++r)
{
xyD[r] = 0;
for (int k = 0; k < ksize; ++k)
xyD[r] += w[k] * xyS[k * cn + r];
xyD[r] = xyD[r];
}
....
}
V570 The 'xyD[r]' variable is assigned to itself. test_imgwarp_strict.cpp 560
"xyD[r] = xyD[r];" . ,
, .
: "cls_map[r];". - ?
void ann_get_new_responses(....)
{

....
for( int si = 0; si < train_sidx->cols; si++ )
{
int sidx = train_sidx_ptr[si];
int r = cvRound(responses_ptr[sidx*r_step]);
CV_DbgAssert(fabs(responses_ptr[sidx*r_step]-r) < FLT_EPSILON);
int cls_map_size = (int)cls_map.size();
cls_map[r];
if ( (int)cls_map.size() > cls_map_size )
cls_map[r] = cls_count++;
}
....
}
V607 Ownerless expression 'cls_map[r]'. test_mltests2.cpp 342

, :
void Core_DetTest::get_test_array_types_and_sizes(....)
{
....
sizes[INPUT][0].width =
sizes[INPUT][0].height = sizes[INPUT][0].height;
....
}
V570 The 'sizes[INPUT][0].height' variable is assigned to itself. test_math.cpp 1356

Unspecified behavior
.
, . .
" , . ".
CvSeq * cvFindNextContour( CvContourScanner scanner )

{
....
new_mask = INT_MIN >> 1;
....
}
V610 Unspecified behavior. Check the shift operator '>>. The left operand '(- 2147483647 - 1)' is negative.
contours.cpp 1012

void CvFuzzyMeanShiftTracker::SearchWindow::initDepthValues(....)
{
unsigned int d=0, mind = 0xFFFF, maxd = 0,
m0 = 0, m1 = 0, mc, dd;
....
for (int j = 0; j < height; j++)
{
....
if (d > maxd)
maxd = d;
....
}
}
V547 Expression 'd > maxd' is always false. Unsigned type value is never < 0. fuzzymeanshifttracker.cpp 386
'd' . , 'd > maxd' .

void jpc_init_t2state(jpc_enc_t *enc, int raflag)


{
....

for (pass = cblk->passes; pass != endpasses; ++pass) {


pass->lyrno = -1;
pass->lyrno = 0;
}
....
}
V519 The 'pass->lyrno' variable is assigned values twice successively. Perhaps this is a mistake. Check lines:
539, 540. jpc_t2enc.c 540

void KeyPointsFilter::retainBest(vector<KeyPoint>& keypoints, int


n_points)
{
....
if( n_points > 0 && keypoints.size() > (size_t)n_points )
{
if (n_points==0)
{
keypoints.clear();
return;
}
....
}
V637 Two opposite conditions were encountered. The second condition is always false. Check lines: 195,
197. keypoint.cpp 195

void HOGDescriptor::detectMultiScaleROI(....) const


{
....
double *linearwt = new double[totwords+1];

....
delete linearwt;
....
}
V611 The memory was allocated using 'new T[]' operator but was released using the 'delete' operator.
Consider inspecting this code. It's probably better to use 'delete [] linearwt;'. hog.cpp 2630

.
, PVS-Studio. ,
.