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)
|
if (updateRecursive(condTok) == Progress::Break)
|
||||||
return 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
|
// condition is false, we don't enter the loop
|
||||||
if (checkElse)
|
if (checkElse)
|
||||||
return Progress::Continue;
|
return Progress::Continue;
|
||||||
|
|
|
@ -153,8 +153,27 @@ bool conditionIsTrue(const Token *condition, const ProgramMemory &programMemory)
|
||||||
return !error && result == 1;
|
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)
|
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 (Token::Match(tok, "==|>=|<=|<|>|!=")) {
|
||||||
if (then && !Token::Match(tok, "==|>=|<=|<|>"))
|
if (then && !Token::Match(tok, "==|>=|<=|<|>"))
|
||||||
return;
|
return;
|
||||||
|
@ -162,16 +181,7 @@ void programMemoryParseCondition(ProgramMemory& pm, const Token* tok, const Toke
|
||||||
return;
|
return;
|
||||||
ValueFlow::Value truevalue;
|
ValueFlow::Value truevalue;
|
||||||
ValueFlow::Value falsevalue;
|
ValueFlow::Value falsevalue;
|
||||||
const Token* vartok = parseCompareInt(tok, truevalue, falsevalue, [&](const Token* t) -> std::vector<MathLib::bigint> {
|
const Token* vartok = parseCompareInt(tok, truevalue, falsevalue, eval);
|
||||||
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 (!vartok)
|
if (!vartok)
|
||||||
return;
|
return;
|
||||||
if (vartok->exprId() == 0)
|
if (vartok->exprId() == 0)
|
||||||
|
@ -194,6 +204,15 @@ void programMemoryParseCondition(ProgramMemory& pm, const Token* tok, const Toke
|
||||||
} else if (!then && Token::simpleMatch(tok, "||")) {
|
} else if (!then && Token::simpleMatch(tok, "||")) {
|
||||||
programMemoryParseCondition(pm, tok->astOperand1(), endTok, settings, then);
|
programMemoryParseCondition(pm, tok->astOperand1(), endTok, settings, then);
|
||||||
programMemoryParseCondition(pm, tok->astOperand2(), 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) {
|
} else if (tok->exprId() > 0) {
|
||||||
if (then && !astIsPointer(tok) && !astIsBool(tok))
|
if (then && !astIsPointer(tok) && !astIsBool(tok))
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -118,6 +118,7 @@ private:
|
||||||
TEST_CASE(nullpointer76); // #10408
|
TEST_CASE(nullpointer76); // #10408
|
||||||
TEST_CASE(nullpointer77);
|
TEST_CASE(nullpointer77);
|
||||||
TEST_CASE(nullpointer78); // #7802
|
TEST_CASE(nullpointer78); // #7802
|
||||||
|
TEST_CASE(nullpointer79); // #10400
|
||||||
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
|
||||||
|
@ -2418,6 +2419,18 @@ private:
|
||||||
ASSERT_EQUALS("[test.cpp:6]: (error) Null pointer dereference: *pp\n", errout.str());
|
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
|
void nullpointer_addressOf() { // address of
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" struct X *x = 0;\n"
|
" struct X *x = 0;\n"
|
||||||
|
|
|
@ -3125,6 +3125,20 @@ private:
|
||||||
"}";
|
"}";
|
||||||
ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
|
ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
|
||||||
ASSERT_EQUALS(false, testValueOfX(code, 4U, 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() {
|
void valueFlowForwardModifiedVariables() {
|
||||||
|
|
Loading…
Reference in New Issue