use correct checkScope function in CheckBufferOverrun for single dimension member arrays

This commit is contained in:
Robert Reif 2011-09-11 19:21:13 -04:00
parent 19928e26d1
commit 0d6592dd2e
3 changed files with 54 additions and 35 deletions

View File

@ -847,16 +847,16 @@ void CheckBufferOverrun::checkScopeForBody(const Token *tok, const ArrayInfo &ar
}
void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::string> &varname, const ArrayInfo &info)
void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::string> &varname, const ArrayInfo &arrayInfo)
{
// Only handling 1-dimensional arrays yet..
/** @todo false negatives: handle multi-dimension arrays someday */
if (info.num().size() > 1)
if (arrayInfo.num().size() > 1)
return;
const MathLib::bigint size = info.num(0);
const MathLib::bigint total_size = info.element_size() * info.num(0);
unsigned int varid = info.varid();
const MathLib::bigint size = arrayInfo.num(0);
const MathLib::bigint total_size = arrayInfo.element_size() * arrayInfo.num(0);
unsigned int varid = arrayInfo.varid();
std::string varnames;
for (unsigned int i = 0; i < varname.size(); ++i)
@ -880,7 +880,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::str
{
std::vector<MathLib::bigint> indexes;
indexes.push_back(index);
arrayIndexOutOfBoundsError(tok->tokAt(varc), info, indexes);
arrayIndexOutOfBoundsError(tok->tokAt(varc), arrayInfo, indexes);
}
}
@ -926,7 +926,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::str
{
std::vector<MathLib::bigint> indexes;
indexes.push_back(index);
arrayIndexOutOfBoundsError(tok->tokAt(1 + varc), info, indexes);
arrayIndexOutOfBoundsError(tok->tokAt(1 + varc), arrayInfo, indexes);
}
tok = tok->tokAt(4 + varc);
continue;
@ -935,22 +935,22 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::str
// memset, memcmp, memcpy, strncpy, fgets..
if (varid == 0 && size > 0)
{
ArrayInfo arrayInfo(0U,
varnames,
(unsigned int)(total_size / size),
(unsigned int)size);
ArrayInfo arrayInfo1(0U,
varnames,
(unsigned int)(total_size / size),
(unsigned int)size);
if (Token::Match(tok, ("%var% ( " + varnames + " ,").c_str()))
checkFunctionParameter(*tok, 1, arrayInfo);
checkFunctionParameter(*tok, 1, arrayInfo1);
if (Token::Match(tok, ("%var% ( %var% , " + varnames + " ,").c_str()))
checkFunctionParameter(*tok, 2, arrayInfo);
checkFunctionParameter(*tok, 2, arrayInfo1);
}
// Loop..
if (Token::simpleMatch(tok, "for ("))
{
const ArrayInfo arrayInfo(varid, varnames, (unsigned int)size, (unsigned int)total_size);
const ArrayInfo arrayInfo1(varid, varnames, (unsigned int)size, (unsigned int)total_size);
bool bailout = false;
checkScopeForBody(tok, arrayInfo, bailout);
checkScopeForBody(tok, arrayInfo1, bailout);
if (bailout)
break;
continue;
@ -1026,8 +1026,8 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::str
if (varid == 0)
continue;
const ArrayInfo arrayInfo(varid, varnames, size, total_size / size);
checkFunctionCall(tok, arrayInfo);
const ArrayInfo arrayInfo1(varid, varnames, size, total_size / size);
checkFunctionCall(tok, arrayInfo1);
}
// undefined behaviour: result of pointer arithmetic is out of bounds
@ -1328,7 +1328,12 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable()
const Token *tok = var->nameToken();
if (var->scope() && var->scope()->isClassOrStruct())
{
tok = var->scope()->classEnd->next();
// Only handle multi-dimension member arrays because single
// dimension arrays are handled in another check.
if (var->dimensions().size() > 1)
tok = var->scope()->classEnd->next();
else
continue;
}
else
{
@ -1617,9 +1622,19 @@ void CheckBufferOverrun::checkStructVariable()
if (!CheckTok)
continue;
// The version of checkScope below doesn't handle multi-dimension arrays
// yet so the other version of checkScope which does is used in another check.
// Ignore this variable because it is a mult-dimension array.
if (arrayInfo.num().size() > 1)
continue;
// Check variable usage..
ArrayInfo temp = arrayInfo;
temp.varid(0);
temp.varid(0); // do variable lookup by variable and member names rather than varid
std::string varnames; // use class and member name for messages
for (unsigned int i = 0; i < varname.size(); ++i)
varnames += (i == 0 ? "" : ".") + varname[i];
temp.varname(varnames);
checkScope(CheckTok, varname, temp);
}
}

View File

@ -188,6 +188,10 @@ public:
{
return _varname;
}
void varname(const std::string &name)
{
_varname = name;
}
};
/** Check for buffer overruns (based on ArrayInfo) */

View File

@ -500,7 +500,7 @@ private:
" struct ABC abc;\n"
" abc.str[10] = 0;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:9]: (error) Array 'str[10]' index 10 out of bounds\n", errout.str());
ASSERT_EQUALS("[test.cpp:9]: (error) Array 'abc.str[10]' index 10 out of bounds\n", errout.str());
check("struct ABC\n"
"{\n"
@ -512,7 +512,7 @@ private:
" struct ABC abc;\n"
" return abc.str[10];\n"
"}\n");
ASSERT_EQUALS("[test.cpp:9]: (error) Array 'str[10]' index 10 out of bounds\n", errout.str());
ASSERT_EQUALS("[test.cpp:9]: (error) Array 'abc.str[10]' index 10 out of bounds\n", errout.str());
// This is not out of bounds because it is a variable length array
check("struct ABC\n"
@ -539,7 +539,7 @@ private:
" struct ABC* x = (struct ABC *)malloc(sizeof(struct ABC) + 10);\n"
" x->str[1] = 0;"
"}\n");
ASSERT_EQUALS("[test.cpp:10]: (error) Array 'str[1]' index 1 out of bounds\n", errout.str());
ASSERT_EQUALS("[test.cpp:10]: (error) Array 'x.str[1]' index 1 out of bounds\n", errout.str());
// This is not out of bounds because it is a variable length array
// and the index is within the memory allocated.
@ -581,7 +581,7 @@ private:
" struct ABC* x = (struct ABC *)malloc(sizeof(ABC) + 10);\n"
" x->str[11] = 0;"
"}\n");
ASSERT_EQUALS("[test.cpp:9]: (error) Array 'str[11]' index 11 out of bounds\n", errout.str());
ASSERT_EQUALS("[test.cpp:9]: (error) Array 'x.str[11]' index 11 out of bounds\n", errout.str());
// This is out of bounds because it is outside the memory allocated
/** @todo this doesn't work because of a bug in sizeof(struct) */
@ -608,7 +608,7 @@ private:
" struct ABC* x = (struct ABC *)malloc(sizeof(ABC));\n"
" x->str[1] = 0;"
"}\n");
ASSERT_EQUALS("[test.cpp:9]: (error) Array 'str[1]' index 1 out of bounds\n", errout.str());
ASSERT_EQUALS("[test.cpp:9]: (error) Array 'x.str[1]' index 1 out of bounds\n", errout.str());
// This is out of bounds because it is not a variable array
check("struct ABC\n"
@ -621,7 +621,7 @@ private:
" struct ABC x;\n"
" x.str[1] = 0;"
"}\n");
ASSERT_EQUALS("[test.cpp:9]: (error) Array 'str[1]' index 1 out of bounds\n", errout.str());
ASSERT_EQUALS("[test.cpp:9]: (error) Array 'x.str[1]' index 1 out of bounds\n", errout.str());
check("struct foo\n"
"{\n"
@ -649,7 +649,7 @@ private:
"{\n"
" abc->str[10] = 0;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:8]: (error) Array 'str[10]' index 10 out of bounds\n", errout.str());
ASSERT_EQUALS("[test.cpp:8]: (error) Array 'abc.str[10]' index 10 out of bounds\n", errout.str());
}
@ -667,7 +667,7 @@ private:
" struct ABC abc;\n"
" abc.str[SIZE] = 0;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:11]: (error) Array 'str[10]' index 10 out of bounds\n", errout.str());
ASSERT_EQUALS("[test.cpp:11]: (error) Array 'abc.str[10]' index 10 out of bounds\n", errout.str());
}
void array_index_9()
@ -757,7 +757,7 @@ private:
" abc->str[10] = 0;\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:13]: (error) Array 'str[10]' index 10 out of bounds\n", errout.str());
ASSERT_EQUALS("[test.cpp:13]: (error) Array 'abc.str[10]' index 10 out of bounds\n", errout.str());
}
@ -1231,12 +1231,12 @@ private:
" ptest->b[10][2] = 4;\n"
" ptest->b[0][19] = 4;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:9]: (error) Array 'a[10]' index 10 out of bounds\n"
"[test.cpp:14]: (error) Array 'a[10]' index 10 out of bounds\n"
"[test.cpp:10]: (error) Array 'b[10][5]' index b[10][2] out of bounds\n"
ASSERT_EQUALS("[test.cpp:10]: (error) Array 'b[10][5]' index b[10][2] out of bounds\n"
"[test.cpp:11]: (error) Array 'b[10][5]' index b[0][19] out of bounds\n"
"[test.cpp:15]: (error) Array 'b[10][5]' index b[10][2] out of bounds\n"
"[test.cpp:16]: (error) Array 'b[10][5]' index b[0][19] out of bounds\n", errout.str());
"[test.cpp:16]: (error) Array 'b[10][5]' index b[0][19] out of bounds\n"
"[test.cpp:9]: (error) Array 'test.a[10]' index 10 out of bounds\n"
"[test.cpp:14]: (error) Array 'ptest.a[10]' index 10 out of bounds\n", errout.str());
check("struct TEST\n"
"{\n"
@ -1264,14 +1264,14 @@ private:
" struct Struct { unsigned m_Var[1]; } s;\n"
" s.m_Var[1] = 1;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (error) Array 'm_Var[1]' index 1 out of bounds\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (error) Array 's.m_Var[1]' index 1 out of bounds\n", errout.str());
check("struct Struct { unsigned m_Var[1]; };\n"
"void f() {\n"
" struct Struct s;\n"
" s.m_Var[1] = 1;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Array 'm_Var[1]' index 1 out of bounds\n", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (error) Array 's.m_Var[1]' index 1 out of bounds\n", errout.str());
check("struct Struct { unsigned m_Var[1]; };\n"
"void f() {\n"
@ -2794,7 +2794,7 @@ private:
" Fred *f = new Fred;\n"
" return f->c[10];\n"
"}\n");
ASSERT_EQUALS("[test.cpp:5]: (error) Array 'c[10]' index 10 out of bounds\n", errout.str());
ASSERT_EQUALS("[test.cpp:5]: (error) Array 'f.c[10]' index 10 out of bounds\n", errout.str());
check("void foo()\n"
"{\n"