From 0d6592dd2e3c9529c14dd979d413049f57297108 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Sun, 11 Sep 2011 19:21:13 -0400 Subject: [PATCH] use correct checkScope function in CheckBufferOverrun for single dimension member arrays --- lib/checkbufferoverrun.cpp | 53 ++++++++++++++++++++++++-------------- lib/checkbufferoverrun.h | 4 +++ test/testbufferoverrun.cpp | 32 +++++++++++------------ 3 files changed, 54 insertions(+), 35 deletions(-) diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index ca5fd8f82..47829a994 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -847,16 +847,16 @@ void CheckBufferOverrun::checkScopeForBody(const Token *tok, const ArrayInfo &ar } -void CheckBufferOverrun::checkScope(const Token *tok, const std::vector &varname, const ArrayInfo &info) +void CheckBufferOverrun::checkScope(const Token *tok, const std::vector &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 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 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 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::vectornameToken(); 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); } } diff --git a/lib/checkbufferoverrun.h b/lib/checkbufferoverrun.h index 26bdf3bb1..389d36220 100644 --- a/lib/checkbufferoverrun.h +++ b/lib/checkbufferoverrun.h @@ -188,6 +188,10 @@ public: { return _varname; } + void varname(const std::string &name) + { + _varname = name; + } }; /** Check for buffer overruns (based on ArrayInfo) */ diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index b860f537b..c79e27858 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -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"