Fix some false positive in loop forward analysis (#2669)

* Fix some false positive in loop forward analysis

In cases like:
```
bool b();
void f()
{
    int val[50];
    int i, sum=0;
    for (i = 1; b() && i < 50; i++)
        sum += val[i];
    for (; i < 50; i++)
        sum -= val[i];
}
```
The forward analysis assumed the second loop was entered, and we ended
up with false positive in it:
 `Array 'val[50]' accessed at index 50, which is out of bounds`

* Fix style
This commit is contained in:
Ken-Patrick Lehrmann 2020-06-05 18:06:03 +02:00 committed by GitHub
parent 92f95c850e
commit 8c2c81dbcd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 2 deletions

View File

@ -220,8 +220,17 @@ struct ForwardTraversal {
return Progress::Break; return Progress::Break;
} }
// Traverse condition after lowering // Traverse condition after lowering
if (condTok && updateRecursive(condTok) == Progress::Break) if (condTok) {
return Progress::Break; if (updateRecursive(condTok) == Progress::Break)
return Progress::Break;
bool checkThen, checkElse;
std::tie(checkThen, checkElse) = evalCond(condTok);
if (checkElse)
// condition is false, we don't enter the loop
return Progress::Break;
}
forkScope(endBlock, allAnalysis.isModified()); forkScope(endBlock, allAnalysis.isModified());
if (bodyAnalysis.isModified()) { if (bodyAnalysis.isModified()) {
Token* writeTok = findRange(endBlock->link(), endBlock, std::mem_fn(&ForwardAnalyzer::Action::isModified)); Token* writeTok = findRange(endBlock->link(), endBlock, std::mem_fn(&ForwardAnalyzer::Action::isModified));

View File

@ -156,6 +156,7 @@ private:
TEST_CASE(array_index_function_parameter); TEST_CASE(array_index_function_parameter);
TEST_CASE(array_index_enum_array); // #8439 TEST_CASE(array_index_enum_array); // #8439
TEST_CASE(array_index_container); // #9386 TEST_CASE(array_index_container); // #9386
TEST_CASE(array_index_two_for_loops);
TEST_CASE(buffer_overrun_2_struct); TEST_CASE(buffer_overrun_2_struct);
TEST_CASE(buffer_overrun_3); TEST_CASE(buffer_overrun_3);
@ -2211,6 +2212,46 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void array_index_two_for_loops() {
check("bool b();\n"
"void f()\n"
"{\n"
" int val[50];\n"
" int i, sum=0;\n"
" for (i = 1; b() && i < 50; i++)\n"
" sum += val[i];\n"
" if (i < 50)\n"
" sum -= val[i];\n"
"}");
ASSERT_EQUALS("", errout.str());
check("bool b();\n"
"void f()\n"
"{\n"
" int val[50];\n"
" int i, sum=0;\n"
" for (i = 1; b() && i < 50; i++)\n"
" sum += val[i];\n"
" for (; i < 50;) {\n"
" sum -= val[i];\n"
" break;\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
check("bool b();\n"
"void f()\n"
"{\n"
" int val[50];\n"
" int i, sum=0;\n"
" for (i = 1; b() && i < 50; i++)\n"
" sum += val[i];\n"
" for (; i < 50; i++)\n"
" sum -= val[i];\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void buffer_overrun_2_struct() { void buffer_overrun_2_struct() {
check("struct ABC\n" check("struct ABC\n"
"{\n" "{\n"