Fixed #4751 (CheckBufferOverrun: better handling when struct member instance doesn't have same varid as struct member declaration)

This commit is contained in:
Daniel Marjamäki 2013-05-28 16:52:23 +02:00
parent ae7363fe54
commit a861817a01
3 changed files with 29 additions and 4 deletions

View File

@ -1384,7 +1384,7 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable()
for (unsigned int i = 1; i <= _tokenizer->varIdCount(); i++) {
const Variable *var = symbolDatabase->getVariableFromVarId(i);
if (var && var->isArray() && var->dimension(0) > 0) {
const ArrayInfo arrayInfo(var, _tokenizer);
const ArrayInfo arrayInfo(var, _tokenizer, i);
const Token *tok = var->nameToken();
while (tok && tok->str() != ";") {
if (tok->str() == "{") {
@ -1972,8 +1972,8 @@ CheckBufferOverrun::ArrayInfo::ArrayInfo(const CheckBufferOverrun::ArrayInfo &ai
*this = ai;
}
CheckBufferOverrun::ArrayInfo::ArrayInfo(const Variable *var, const Tokenizer *tokenizer)
: _varname(var->name()), _varid(var->varId())
CheckBufferOverrun::ArrayInfo::ArrayInfo(const Variable *var, const Tokenizer *tokenizer, const unsigned int forcevarid)
: _varname(var->name()), _varid((forcevarid == 0U) ? var->varId() : forcevarid)
{
for (std::size_t i = 0; i < var->dimensions().size(); i++)
_num.push_back(var->dimension(i));

View File

@ -131,7 +131,7 @@ public:
public:
ArrayInfo();
ArrayInfo(const ArrayInfo &);
ArrayInfo(const Variable *var, const Tokenizer *tokenizer);
ArrayInfo(const Variable *var, const Tokenizer *tokenizer, const unsigned int forcevarid = 0);
ArrayInfo & operator=(const ArrayInfo &ai);
/**

View File

@ -140,6 +140,7 @@ private:
TEST_CASE(array_index_extern); // FP when using 'extern'. #1684
TEST_CASE(array_index_cast); // FP after cast. #2841
TEST_CASE(array_index_string_literal);
TEST_CASE(array_index_same_struct_and_var_name); // #4751 - not handled well when struct name and var name is same
TEST_CASE(buffer_overrun_1_standard_functions);
TEST_CASE(buffer_overrun_2_struct);
@ -1991,6 +1992,30 @@ private:
}
void array_index_same_struct_and_var_name() {
// don't throw internal error
check("struct tt {\n"
" char typename[21];\n"
"} ;\n"
"void doswitch(struct tt *x)\n"
"{\n"
" struct tt *tt=x;\n"
" tt->typename;\n"
"}");
ASSERT_EQUALS("", errout.str());
// detect error
check("struct tt {\n"
" char typename[21];\n"
"} ;\n"
"void doswitch(struct tt *x)\n"
"{\n"
" struct tt *tt=x;\n"
" tt->typename[22] = 123;\n"
"}");
ASSERT_EQUALS("[test.cpp:7]: (error) Array 'tt.typename[21]' accessed at index 22, which is out of bounds.\n", errout.str());
}
void buffer_overrun_1_standard_functions() {
check("void f()\n"
"{\n"