diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index 2c93f6055..bb6016211 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -407,8 +407,33 @@ void CheckBufferOverrun::parse_for_body(const Token *tok2, const ArrayInfo &arra if (Token::Match(tok2, "if|switch")) { + bool bailout = false; + unsigned int indentlevel3 = 0; + for (const Token *tok3 = tok2; tok3; tok3 = tok3->next()) + { + if (tok3->str() == "{") + indentlevel3++; + else if (tok3->str() == "}") + { + if (indentlevel3 <= 1) + break; + --indentlevel3; + } + else if (tok3->str() == "break" && tok2->str() == "if") + { + bailout = true; + break; + } + else if (tok3->varId() == arrayInfo.varid) + { + bailout = true; + break; + } + } + // Bailout - break; + if (bailout) + break; } if (condition_out_of_bounds && Token::Match(tok2, pattern.c_str(), arrayInfo.varid)) diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index 333da1b61..ad192fc97 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -113,6 +113,7 @@ private: TEST_CASE(array_index_for_decr); TEST_CASE(array_index_varnames); // FP: struct member. #1576 TEST_CASE(array_index_for_break); // FP: for,break + TEST_CASE(array_index_for); // FN: for,if TEST_CASE(buffer_overrun_1); TEST_CASE(buffer_overrun_2); @@ -1325,6 +1326,20 @@ private: ASSERT_EQUALS("", errout.str()); } + void array_index_for() + { + // Ticket #2370 - No false negative when there is no "break" + check("void f() {\n" + " int a[10];\n" + " for (int i = 0; i < 20; ++i) {\n" + " if (i==1) {\n" + " }\n" + " a[i] = 0;\n" + " }\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:6]: (error) Buffer access out-of-bounds: a\n", errout.str()); + } + void buffer_overrun_1() {