diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index a5d493f6f..f2b123d6a 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -132,7 +132,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const char *varname[], con unsigned int varc = 0; std::string varnames; - while (varname[varc]) + while (varname && varname[varc]) { if (varc > 0) varnames += " . "; @@ -148,7 +148,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const char *varname[], con varc = 2 * (varc - 1); // Array index.. - if (varid > 0) + if (varid > 0 && Token::Match(tok, "%varid% [ %num% ]", varid)) { if (Token::Match(tok, "%varid% [ %num% ]", varid)) { @@ -449,7 +449,8 @@ void CheckBufferOverrun::checkScope(const Token *tok, const char *varname[], con // Writing data into array.. - if (Token::Match(tok, ("strcpy|strcat ( " + varnames + " , %str% )").c_str())) + if ((varid > 0 && Token::Match(tok, "strcpy|strcat ( %varid% , %str% )", varid)) || + (varid == 0 && Token::Match(tok, ("strcpy|strcat ( " + varnames + " , %str% )").c_str()))) { size_t len = Token::getStrLength(tok->tokAt(varc + 4)); if (len >= static_cast(size)) @@ -459,7 +460,6 @@ void CheckBufferOverrun::checkScope(const Token *tok, const char *varname[], con } } - // Dangerous usage of strncat.. if (varid > 0 && Token::Match(tok, "strncat ( %varid% , %any% , %num% )", varid)) { @@ -551,10 +551,14 @@ void CheckBufferOverrun::checkScope(const Token *tok, const char *varname[], con ++par; } - if (parlevel == 1 && Token::Match(tok2, std::string("[(,] " + varnames + " [,)]").c_str())) + if (parlevel == 1) { - ++par; - break; + if ((varid > 0 && Token::Match(tok2, std::string("[(,] %varid% [,)]").c_str(), varid)) || + (varid == 0 && Token::Match(tok2, std::string("[(,] " + varnames + " [,)]").c_str()))) + { + ++par; + break; + } } } @@ -623,7 +627,6 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable() else if (tok->str() == "}") --indentlevel; - const char *varname[2] = {0}; unsigned int size = 0; const char *type = 0; unsigned int varid = 0; @@ -638,7 +641,6 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable() unsigned int varpos = 1; if (tok->next()->str() == "*") ++varpos; - varname[0] = tok->strAt(varpos); size = std::strtoul(tok->strAt(varpos + 2), NULL, 10); type = tok->strAt(varpos - 1); varid = tok->tokAt(varpos)->varId(); @@ -646,7 +648,6 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable() } else if (indentlevel > 0 && Token::Match(tok, "[*;{}] %var% = new %type% [ %num% ]")) { - varname[0] = tok->strAt(1); size = std::strtoul(tok->strAt(6), NULL, 10); type = tok->strAt(4); varid = tok->tokAt(1)->varId(); @@ -654,7 +655,6 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable() } else if (indentlevel > 0 && Token::Match(tok, "[*;{}] %var% = malloc ( %num% ) ;")) { - varname[0] = tok->strAt(1); size = std::strtoul(tok->strAt(5), NULL, 10); type = "char"; varid = tok->tokAt(1)->varId(); @@ -673,7 +673,7 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable() // The callstack is empty _callStack.clear(); - checkScope(tok->tokAt(nextTok), varname, size, total_size, varid); + checkScope(tok->tokAt(nextTok), 0, size, total_size, varid); } } //--------------------------------------------------------------------------- diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index 0182ec2ef..7aeacbae3 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -89,6 +89,7 @@ private: TEST_CASE(array_index_17); TEST_CASE(array_index_18); TEST_CASE(array_index_19); + TEST_CASE(array_index_multidim); TEST_CASE(buffer_overrun_1); TEST_CASE(buffer_overrun_2); @@ -623,6 +624,65 @@ private: ASSERT_EQUALS("[test.cpp:4]: (error) Array index out of bounds\n", errout.str()); } + void array_index_multidim() + { + check("void f()\n" + "{\n" + " char a[2][2];\n" + " a[1][1] = 'a';\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + check("void f()\n" + "{\n" + " char a[2][2][2];\n" + " a[1][1][1] = 'a';\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + check("void f()\n" + "{\n" + " char a[2][2];\n" + " a[2][1] = 'a';\n" + "}\n"); + TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Array index out of bounds\n", errout.str()); + + check("void f()\n" + "{\n" + " char a[2][2];\n" + " a[1][2] = 'a';\n" + "}\n"); + TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Array index out of bounds\n", errout.str()); + + check("void f()\n" + "{\n" + " char a[2][2][2];\n" + " a[2][1][1] = 'a';\n" + "}\n"); + TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Array index out of bounds\n", errout.str()); + + check("void f()\n" + "{\n" + " char a[2][2][2];\n" + " a[1][2][1] = 'a';\n" + "}\n"); + TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Array index out of bounds\n", errout.str()); + + check("void f()\n" + "{\n" + " char a[2][2][2];\n" + " a[1][1][2] = 'a';\n" + "}\n"); + TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Array index out of bounds\n", errout.str()); + + check("void f()\n" + "{\n" + " char a[2][2][2];\n" + " a[1][1][2] = 'a';\n" + "}\n"); + TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Array index out of bounds\n", errout.str()); + } + void buffer_overrun_1() { check("void f()\n"