From ff0eee4d7720716cb04a9cd2240cb6a1b2103767 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Sat, 18 Feb 2023 17:35:12 +0100 Subject: [PATCH] Fix #11558 FP knownConditionTrueFalse when checking for zero character (#4794) * Fix #11558 FP knownConditionTrueFalse when checking for zero characte * Fix test * Set impossible value only for non-Boolean conditions, rename * Fix condition --- lib/valueflow.cpp | 8 +++++++- test/testcondition.cpp | 10 ++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index f295278be..74e923f3d 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -5033,11 +5033,16 @@ static const Token* findIncompleteVar(const Token* start, const Token* end) static ValueFlow::Value makeConditionValue(long long val, const Token* condTok, bool assume, + bool impossible = false, const Settings* settings = nullptr, SourceLocation loc = SourceLocation::current()) { ValueFlow::Value v(val); v.setKnown(); + if (impossible) { + v.intvalue = !v.intvalue; + v.setImpossible(); + } v.condition = condTok; if (assume) v.errorPath.emplace_back(condTok, "Assuming condition '" + condTok->expressionString() + "' is true"); @@ -5116,7 +5121,8 @@ static void valueFlowConditionExpressions(TokenList *tokenlist, SymbolDatabase* { for (const Token* condTok2 : getConditions(condTok, "&&")) { if (is1) { - SameExpressionAnalyzer a1(condTok2, makeConditionValue(1, condTok2, true), tokenlist); + const bool isBool = astIsBool(condTok2) || Token::Match(condTok2, "%comp%|%oror%|&&"); + SameExpressionAnalyzer a1(condTok2, makeConditionValue(1, condTok2, /*assume*/ true, !isBool), tokenlist); // don't set '1' for non-boolean expressions valueFlowGenericForward(startTok, startTok->link(), a1, settings); } diff --git a/test/testcondition.cpp b/test/testcondition.cpp index f5da61c95..34a114c0c 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -4483,6 +4483,16 @@ private: " g(s ? s->get() : 0);\n" "}\n"); ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:7]: (style) Condition 's' is always true\n", errout.str()); + + check("void f(const char* o) {\n" // #11558 + " if (!o || !o[0])\n" + " return;\n" + " if (o[0] == '-' && o[1]) {\n" + " if (o[1] == '-') {}\n" + " if (o[1] == '\\0') {}\n" + " }\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:6]: (style) Condition 'o[1]=='\\0'' is always false\n", errout.str()); } void alwaysTrueSymbolic()