better detection of variable sized structure in CheckBufferOverrun::checkStructVariable()
This commit is contained in:
parent
27bfa2a346
commit
b0eab2587d
|
@ -1571,18 +1571,41 @@ void CheckBufferOverrun::checkStructVariable()
|
||||||
// is variable public struct member?
|
// is variable public struct member?
|
||||||
if (scope->type == Scope::eStruct && var->isPublic())
|
if (scope->type == Scope::eStruct && var->isPublic())
|
||||||
{
|
{
|
||||||
// last member of a struct with array size of 0 or 1 could be a variable struct
|
// last member of a struct with array size of 0 or 1 could be a variable sized struct
|
||||||
if (var->dimensions().size() == 1 && var->dimension(0) < 2 &&
|
if (var->dimensions().size() == 1 && var->dimension(0) < 2 &&
|
||||||
var->index() == (scope->varlist.size() - 1))
|
var->index() == (scope->varlist.size() - 1))
|
||||||
{
|
{
|
||||||
// dynamically allocated so could be variable sized array
|
// dynamically allocated so could be variable sized array
|
||||||
|
if (tok3->next()->str() == "*")
|
||||||
|
{
|
||||||
|
if ((Token::Match(tok3->tokAt(3), "; %var% = malloc ( %num% ) ;") ||
|
||||||
|
(Token::Match(tok3->tokAt(3), "; %var% = (") &&
|
||||||
|
Token::Match(tok3->tokAt(6)->link(), ") malloc ( %num% ) ;"))) &&
|
||||||
|
(tok3->strAt(4) == tok3->strAt(2)))
|
||||||
|
{
|
||||||
|
MathLib::bigint size;
|
||||||
|
|
||||||
|
// find size of allocation
|
||||||
|
if (tok3->strAt(3) == "(") // has cast
|
||||||
|
size = MathLib::toLongNumber(tok3->tokAt(6)->link()->strAt(3));
|
||||||
|
else
|
||||||
|
size = MathLib::toLongNumber(tok3->strAt(8));
|
||||||
|
|
||||||
|
if (size != 100) // magic number for size of class or struct
|
||||||
|
{
|
||||||
/** @todo false negatives: only true if dynamically allocated with size larger that struct */
|
/** @todo false negatives: only true if dynamically allocated with size larger that struct */
|
||||||
/** @todo false negatives: calculate real array size based on allocated size */
|
/** @todo false negatives: calculate real array size based on allocated size */
|
||||||
if (tok3->next()->str() == "*")
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// size unknown so assume it is a dynamically sized struct
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Goto end of statement.
|
// Goto end of statement.
|
||||||
const Token *CheckTok = NULL;
|
const Token *CheckTok = NULL;
|
||||||
while (tok3 && tok3 != func_scope->classEnd)
|
while (tok3 && tok3 != func_scope->classEnd)
|
||||||
|
|
|
@ -2435,7 +2435,16 @@ private:
|
||||||
check("struct Foo { char a[1]; };\n"
|
check("struct Foo { char a[1]; };\n"
|
||||||
"void f()\n"
|
"void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" struct Foo *x = malloc(10);\n"
|
" struct Foo *x = malloc(sizeof(Foo));\n"
|
||||||
|
" sprintf(x.a, \"aa\");\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:5]: (error) Buffer access out-of-bounds\n", errout.str());
|
||||||
|
|
||||||
|
check("struct Foo { char a[1]; };\n"
|
||||||
|
"void f()\n"
|
||||||
|
"{\n"
|
||||||
|
" struct Foo *x = malloc(sizeof(Foo) + 10);\n"
|
||||||
" sprintf(x.a, \"aa\");\n"
|
" sprintf(x.a, \"aa\");\n"
|
||||||
" free(x);\n"
|
" free(x);\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
|
@ -2526,7 +2535,16 @@ private:
|
||||||
check("struct Foo { char a[1]; };\n"
|
check("struct Foo { char a[1]; };\n"
|
||||||
"void f()\n"
|
"void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" struct Foo *x = malloc(10);\n"
|
" struct Foo *x = malloc(sizeof(Foo));\n"
|
||||||
|
" snprintf(x.a, 2, \"aa\");\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:5]: (error) snprintf size is out of bounds\n", errout.str());
|
||||||
|
|
||||||
|
check("struct Foo { char a[1]; };\n"
|
||||||
|
"void f()\n"
|
||||||
|
"{\n"
|
||||||
|
" struct Foo *x = malloc(sizeof(Foo) + 10);\n"
|
||||||
" snprintf(x.a, 2, \"aa\");\n"
|
" snprintf(x.a, 2, \"aa\");\n"
|
||||||
" free(x);\n"
|
" free(x);\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
|
|
Loading…
Reference in New Issue