Fix issue 8296: ValueFlow: value not set in conditional scope in subfunction (#2071)

* Fix issue 8296: ValueFlow: value not set in conditional scope in subfunction

* Refactor condition checkingg

* Make test case TODO
This commit is contained in:
Paul Fultz II 2019-08-11 08:39:37 -05:00 committed by Daniel Marjamäki
parent 46c93779d8
commit 9aa97cbb95
3 changed files with 46 additions and 10 deletions

View File

@ -2145,16 +2145,16 @@ static bool valueFlowForward(Token * const startToken,
continue; continue;
} }
const ProgramMemory &programMemory = getProgramMemory(tok2, varid, v); const ProgramMemory &programMemory = getProgramMemory(tok2, varid, v);
if (subFunction && conditionIsTrue(condTok, programMemory)) const bool isTrue = conditionIsTrue(condTok, programMemory);
const bool isFalse = conditionIsFalse(condTok, programMemory);
if (isTrue)
truevalues.push_back(v); truevalues.push_back(v);
else if (!conditionIsFalse(condTok, programMemory)) if (isFalse)
truevalues.push_back(v);
if (conditionIsFalse(condTok, programMemory))
falsevalues.push_back(v);
else if (!subFunction && !conditionIsTrue(condTok, programMemory))
falsevalues.push_back(v); falsevalues.push_back(v);
} }
if (truevalues.size() != values.size() || condAlwaysTrue) { if (!truevalues.empty() || !falsevalues.empty()) {
// '{' // '{'
const Token * const startToken1 = tok2->linkAt(1)->next(); const Token * const startToken1 = tok2->linkAt(1)->next();
@ -2211,7 +2211,8 @@ static bool valueFlowForward(Token * const startToken,
removeValues(values, falsevalues); removeValues(values, falsevalues);
} }
} }
if (values.empty())
return false;
continue; continue;
} }

View File

@ -74,6 +74,7 @@ private:
TEST_CASE(nullpointer32); // #8460 TEST_CASE(nullpointer32); // #8460
TEST_CASE(nullpointer33); TEST_CASE(nullpointer33);
TEST_CASE(nullpointer34); TEST_CASE(nullpointer34);
TEST_CASE(nullpointer35);
TEST_CASE(nullpointer_addressOf); // address of TEST_CASE(nullpointer_addressOf); // address of
TEST_CASE(nullpointerSwitch); // #2626 TEST_CASE(nullpointerSwitch); // #2626
TEST_CASE(nullpointer_cast); // #4692 TEST_CASE(nullpointer_cast); // #4692
@ -1413,6 +1414,19 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void nullpointer35() {
check("bool f(int*);\n"
"void g(int* x) {\n"
" if (f(x)) {\n"
" *x = 1;\n"
" }\n"
"}\n"
"void h() {\n"
" g(0);\n"
"}\n", true);
ASSERT_EQUALS("", errout.str());
}
void nullpointer_addressOf() { // address of void nullpointer_addressOf() { // address of
check("void f() {\n" check("void f() {\n"
" struct X *x = 0;\n" " struct X *x = 0;\n"
@ -2574,7 +2588,7 @@ private:
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("void f(int *p = 0) {\n" check("void f(int a, int *p = 0) {\n"
" if (a != 0)\n" " if (a != 0)\n"
" *p = 0;\n" " *p = 0;\n"
"}", true); "}", true);

View File

@ -94,6 +94,7 @@ private:
TEST_CASE(valueFlowSwitchVariable); TEST_CASE(valueFlowSwitchVariable);
TEST_CASE(valueFlowForLoop); TEST_CASE(valueFlowForLoop);
TEST_CASE(valueFlowSubFunction);
TEST_CASE(valueFlowFunctionReturn); TEST_CASE(valueFlowFunctionReturn);
TEST_CASE(valueFlowFunctionDefaultParameter); TEST_CASE(valueFlowFunctionDefaultParameter);
@ -2203,7 +2204,7 @@ private:
" else\n" " else\n"
" b = x;\n" " b = x;\n"
"}"; "}";
TODO_ASSERT_EQUALS(true, false, testValueOfX(code, 4U, 2)); ASSERT_EQUALS(true, testValueOfX(code, 4U, 2));
ASSERT_EQUALS(false, testValueOfX(code, 6U, 2)); ASSERT_EQUALS(false, testValueOfX(code, 6U, 2));
// condition with 2nd variable // condition with 2nd variable
@ -2925,6 +2926,26 @@ private:
ASSERT_EQUALS(true, testValueOfX(code, 5U, 3)); ASSERT_EQUALS(true, testValueOfX(code, 5U, 3));
} }
void valueFlowSubFunction() {
const char *code;
code = "int f(int size) {\n"
" int x = 0;\n"
" if(size>16) {\n"
" x = size;\n"
" int a = x;\n"
" }\n"
" return x;\n"
"}\n"
"void g(){\n"
" f(42);\n"
"}";
ASSERT_EQUALS(true, testValueOfX(code, 5U, 17));
ASSERT_EQUALS(true, testValueOfX(code, 5U, 42));
ASSERT_EQUALS(true, testValueOfX(code, 7U, 0));
ASSERT_EQUALS(true, testValueOfX(code, 7U, 17));
ASSERT_EQUALS(true, testValueOfX(code, 7U, 42));
}
void valueFlowFunctionReturn() { void valueFlowFunctionReturn() {
const char *code; const char *code;