Fix 10400: FP nullPointer - for loop condition (#3417)
This commit is contained in:
parent
11916171fe
commit
8aa37218c2
|
@ -411,6 +411,8 @@ struct ForwardTraversal {
|
|||
if (updateRecursive(condTok) == Progress::Break)
|
||||
return Break();
|
||||
}
|
||||
if (!checkThen && !checkElse && !isDoWhile && analyzer->stopOnCondition(condTok) && stopUpdates())
|
||||
return Break(Analyzer::Terminate::Conditional);
|
||||
// condition is false, we don't enter the loop
|
||||
if (checkElse)
|
||||
return Progress::Continue;
|
||||
|
|
|
@ -153,8 +153,27 @@ bool conditionIsTrue(const Token *condition, const ProgramMemory &programMemory)
|
|||
return !error && result == 1;
|
||||
}
|
||||
|
||||
static bool frontIs(const std::vector<MathLib::bigint>& v, bool i)
|
||||
{
|
||||
if (v.empty())
|
||||
return false;
|
||||
if (v.front())
|
||||
return i;
|
||||
return !i;
|
||||
}
|
||||
|
||||
void programMemoryParseCondition(ProgramMemory& pm, const Token* tok, const Token* endTok, const Settings* settings, bool then)
|
||||
{
|
||||
auto eval = [&](const Token* t) -> std::vector<MathLib::bigint> {
|
||||
if (t->hasKnownIntValue())
|
||||
return {t->values().front().intvalue};
|
||||
MathLib::bigint result = 0;
|
||||
bool error = false;
|
||||
execute(t, &pm, &result, &error);
|
||||
if (!error)
|
||||
return {result};
|
||||
return std::vector<MathLib::bigint>{};
|
||||
};
|
||||
if (Token::Match(tok, "==|>=|<=|<|>|!=")) {
|
||||
if (then && !Token::Match(tok, "==|>=|<=|<|>"))
|
||||
return;
|
||||
|
@ -162,16 +181,7 @@ void programMemoryParseCondition(ProgramMemory& pm, const Token* tok, const Toke
|
|||
return;
|
||||
ValueFlow::Value truevalue;
|
||||
ValueFlow::Value falsevalue;
|
||||
const Token* vartok = parseCompareInt(tok, truevalue, falsevalue, [&](const Token* t) -> std::vector<MathLib::bigint> {
|
||||
if (t->hasKnownIntValue())
|
||||
return {t->values().front().intvalue};
|
||||
MathLib::bigint result = 0;
|
||||
bool error = false;
|
||||
execute(t, &pm, &result, &error);
|
||||
if (!error)
|
||||
return {result};
|
||||
return std::vector<MathLib::bigint>{};
|
||||
});
|
||||
const Token* vartok = parseCompareInt(tok, truevalue, falsevalue, eval);
|
||||
if (!vartok)
|
||||
return;
|
||||
if (vartok->exprId() == 0)
|
||||
|
@ -194,6 +204,15 @@ void programMemoryParseCondition(ProgramMemory& pm, const Token* tok, const Toke
|
|||
} else if (!then && Token::simpleMatch(tok, "||")) {
|
||||
programMemoryParseCondition(pm, tok->astOperand1(), endTok, settings, then);
|
||||
programMemoryParseCondition(pm, tok->astOperand2(), endTok, settings, then);
|
||||
} else if (Token::Match(tok, "&&|%oror%")) {
|
||||
std::vector<MathLib::bigint> lhs = eval(tok->astOperand1());
|
||||
std::vector<MathLib::bigint> rhs = eval(tok->astOperand2());
|
||||
if (lhs.empty() || rhs.empty()) {
|
||||
if (frontIs(lhs, !then))
|
||||
programMemoryParseCondition(pm, tok->astOperand2(), endTok, settings, then);
|
||||
if (frontIs(rhs, !then))
|
||||
programMemoryParseCondition(pm, tok->astOperand1(), endTok, settings, then);
|
||||
}
|
||||
} else if (tok->exprId() > 0) {
|
||||
if (then && !astIsPointer(tok) && !astIsBool(tok))
|
||||
return;
|
||||
|
|
|
@ -118,6 +118,7 @@ private:
|
|||
TEST_CASE(nullpointer76); // #10408
|
||||
TEST_CASE(nullpointer77);
|
||||
TEST_CASE(nullpointer78); // #7802
|
||||
TEST_CASE(nullpointer79); // #10400
|
||||
TEST_CASE(nullpointer_addressOf); // address of
|
||||
TEST_CASE(nullpointerSwitch); // #2626
|
||||
TEST_CASE(nullpointer_cast); // #4692
|
||||
|
@ -2418,6 +2419,18 @@ private:
|
|||
ASSERT_EQUALS("[test.cpp:6]: (error) Null pointer dereference: *pp\n", errout.str());
|
||||
}
|
||||
|
||||
void nullpointer79() // #10400
|
||||
{
|
||||
check("void resize(size_t nF, size_t nT) {\n"
|
||||
" double* pValues = nullptr;\n"
|
||||
" if (nF > 0 && nT > 0)\n"
|
||||
" pValues = new double[nF * nT];\n"
|
||||
" for (size_t cc = 0; cc < nF * nT; ++cc)\n"
|
||||
" pValues[cc] = 42;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void nullpointer_addressOf() { // address of
|
||||
check("void f() {\n"
|
||||
" struct X *x = 0;\n"
|
||||
|
|
|
@ -3125,6 +3125,20 @@ private:
|
|||
"}";
|
||||
ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
|
||||
ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
|
||||
|
||||
code = "int g();\n"
|
||||
"int f(bool i, bool j) {\n"
|
||||
" if (i && j) {}\n"
|
||||
" else {\n"
|
||||
" int x = 0;\n"
|
||||
" if (i)\n"
|
||||
" x = g();\n"
|
||||
" return x;\n"
|
||||
" }\n"
|
||||
" return 0;\n"
|
||||
"}\n";
|
||||
ASSERT_EQUALS(false, testValueOfXKnown(code, 8U, 0));
|
||||
ASSERT_EQUALS(true, testValueOfX(code, 8U, 0));
|
||||
}
|
||||
|
||||
void valueFlowForwardModifiedVariables() {
|
||||
|
|
Loading…
Reference in New Issue