CheckBufferOverrun: Refactorizations

- Improved/Optimized conditions in checkBufferAllocatedWithStrlen()
- Avoid copying strings for checkScope()
This commit is contained in:
PKEuS 2017-03-27 11:48:34 +02:00
parent 680828788b
commit 83b1e1c329
2 changed files with 25 additions and 23 deletions

View File

@ -540,7 +540,7 @@ void CheckBufferOverrun::checkFunctionCall(const Token *tok, const ArrayInfo &ar
}
}
void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::string> &varname, const ArrayInfo &arrayInfo)
void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<const std::string*> &varname, const ArrayInfo &arrayInfo)
{
const MathLib::bigint size = arrayInfo.num(0);
if (size <= 0) // unknown size
@ -558,7 +558,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::str
std::string varnames;
for (std::size_t i = 0; i < varname.size(); ++i)
varnames += (i == 0 ? "" : " . ") + varname[i];
varnames += (i == 0 ? "" : " . ") + *varname[i];
const int varcount = varname.empty() ? 0 : static_cast<int>((varname.size() - 1) * 2U);
@ -594,7 +594,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::str
// Array index..
if ((declarationId > 0 && ((tok->str() == "return" || (!tok->isName() && !Token::Match(tok, "[.&]"))) && Token::Match(tok->next(), "%varid% [", declarationId))) ||
(declarationId == 0 && ((tok->str() == "return" || (!tok->isName() && !Token::Match(tok, "[.&]"))) && (Token::Match(tok->next(), (varnames + " [").c_str()) || Token::Match(tok->next(), (varname[0] +" [ %num% ] . " + varname[1] + " [ %num% ]").c_str()))))) {
(declarationId == 0 && ((tok->str() == "return" || (!tok->isName() && !Token::Match(tok, "[.&]"))) && (Token::Match(tok->next(), (varnames + " [").c_str()) || Token::Match(tok->next(), (*varname[0] +" [ %num% ] . " + *varname[1] + " [ %num% ]").c_str()))))) {
std::vector<MathLib::bigint> indexes;
const Token *tok2 = tok->tokAt(2 + varcount);
for (; Token::Match(tok2, "[ %num% ]"); tok2 = tok2->tokAt(3)) {
@ -1202,6 +1202,8 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable()
checkScope(scope->classStart ? scope->classStart : _tokenizer->tokens(), arrayInfos);
}
const std::vector<const std::string*> v;
// find all dynamically allocated arrays next
const std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) {
@ -1280,7 +1282,6 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable()
if (totalSize == 0)
continue;
std::vector<std::string> v;
ArrayInfo temp(var->declarationId(), tok->next()->str(), totalSize / size, size);
checkScope(nextTok, v, temp);
}
@ -1334,9 +1335,8 @@ void CheckBufferOverrun::checkStructVariable()
if (scope->nestedIn->isClassOrStruct())
continue;
std::vector<std::string> varname;
varname.push_back("");
varname.push_back(arrayInfo.varname());
std::vector<const std::string*> varname(2, nullptr);
varname[1] = &arrayInfo.varname();
// search the function and it's parameters
for (const Token *tok3 = func_scope->classDef; tok3 && tok3 != func_scope->classEnd; tok3 = tok3->next()) {
@ -1349,10 +1349,10 @@ void CheckBufferOverrun::checkStructVariable()
// Declare variable: Fred fred1;
if (Token::Match(tok3->next(), "%var% ;"))
varname[0] = tok3->strAt(1);
varname[0] = &tok3->strAt(1);
else if (isArrayOfStruct(tok3,posOfSemicolon)) {
varname[0] = tok3->strAt(1);
varname[0] = &tok3->strAt(1);
int pos = 2;
for (int k = 0 ; k < posOfSemicolon; k++) {
@ -1364,7 +1364,7 @@ void CheckBufferOverrun::checkStructVariable()
// Declare pointer or reference: Fred *fred1
else if (Token::Match(tok3->next(), "*|& %var% [,);=]"))
varname[0] = tok3->strAt(2);
varname[0] = &tok3->strAt(2);
else
continue;
@ -1450,7 +1450,7 @@ void CheckBufferOverrun::checkStructVariable()
temp.declarationId(0); // do variable lookup by variable and member names rather than varid
std::string varnames; // use class and member name for messages
for (std::size_t k = 0; k < varname.size(); ++k)
varnames += (k == 0 ? "" : ".") + varname[k];
varnames += (k == 0 ? "" : ".") + *varname[k];
temp.varname(varnames);
checkScope(checkTok, varname, temp);
@ -1647,22 +1647,24 @@ void CheckBufferOverrun::checkBufferAllocatedWithStrlen()
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token *tok = scope->classStart->next(); tok && tok != scope->classEnd; tok = tok->next()) {
unsigned int dstVarId;
unsigned int dstVarId = tok->varId();
unsigned int srcVarId;
if (!dstVarId || tok->strAt(1) != "=")
continue;
tok = tok->tokAt(2);
// Look for allocation of a buffer based on the size of a string
if (Token::Match(tok, "%var% = malloc|g_malloc|g_try_malloc ( strlen ( %name% ) )")) {
dstVarId = tok->varId();
if (Token::Match(tok, "malloc|g_malloc|g_try_malloc|alloca ( strlen ( %var% ) )")) {
srcVarId = tok->tokAt(4)->varId();
tok = tok->tokAt(6);
} else if (_tokenizer->isCPP() && Token::Match(tok, "new char [ strlen ( %var% ) ]")) {
srcVarId = tok->tokAt(5)->varId();
tok = tok->tokAt(7);
} else if (Token::Match(tok, "realloc|g_realloc|g_try_realloc ( %name% , strlen ( %var% ) )")) {
srcVarId = tok->tokAt(6)->varId();
tok = tok->tokAt(8);
} else if (_tokenizer->isCPP() && Token::Match(tok, "%var% = new char [ strlen ( %name% ) ]")) {
dstVarId = tok->varId();
srcVarId = tok->tokAt(7)->varId();
tok = tok->tokAt(9);
} else if (Token::Match(tok, "%var% = realloc|g_realloc|g_try_realloc ( %name% , strlen ( %name% ) )")) {
dstVarId = tok->varId();
srcVarId = tok->tokAt(8)->varId();
tok = tok->tokAt(10);
} else
continue;

View File

@ -184,7 +184,7 @@ public:
void checkScope_inner(const Token *tok, const ArrayInfo &arrayInfo);
/** Check for buffer overruns */
void checkScope(const Token *tok, const std::vector<std::string> &varname, const ArrayInfo &arrayInfo);
void checkScope(const Token *tok, const std::vector<const std::string*> &varname, const ArrayInfo &arrayInfo);
/**
* Helper function for checkFunctionCall - check a function parameter