From e22a740f0cf72b728e4da7a456e4253f1e3a4dfe Mon Sep 17 00:00:00 2001 From: Paul Fultz II Date: Thu, 6 Apr 2023 11:42:24 -0500 Subject: [PATCH] Fix 11647: FN knownConditionTrueFalse with strings of same length (#4936) * Fix 11647: FN knownConditionTrueFalse with strings of same length * Format * Remove extra size * Use simpleMatch --- lib/valueflow.cpp | 31 +++++++++++++++++++++++- test/testvalueflow.cpp | 53 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 6a4c0dd9b..d9955d5a4 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -503,7 +503,7 @@ static bool isComputableValue(const Token* parent, const ValueFlow::Value& value return false; if (value.isIteratorValue() && !Token::Match(parent, "+|-")) return false; - if (value.isTokValue() && (!parent->isComparisonOp() || value.tokvalue->tokType() != Token::eString)) + if (value.isTokValue() && (!parent->isComparisonOp() || !Token::Match(value.tokvalue, "{|%str%"))) return false; return true; } @@ -886,6 +886,35 @@ static void setTokenValue(Token* tok, result.intvalue = calculate(parent->str(), intValue1(), intValue2(), &error); if (error) continue; + } else if (value1.isTokValue() && value2.isTokValue() && + (astIsContainer(parent->astOperand1()) || astIsContainer(parent->astOperand2()))) { + const Token* tok1 = value1.tokvalue; + const Token* tok2 = value2.tokvalue; + bool equal = false; + if (Token::Match(tok1, "%str%") && Token::Match(tok2, "%str%")) { + equal = tok1->str() == tok2->str(); + } else if (Token::simpleMatch(tok1, "{") && Token::simpleMatch(tok2, "{")) { + std::vector args1 = getArguments(tok1); + std::vector args2 = getArguments(tok2); + if (args1.size() == args2.size()) { + if (!std::all_of(args1.begin(), args1.end(), std::mem_fn(&Token::hasKnownIntValue))) + continue; + if (!std::all_of(args2.begin(), args2.end(), std::mem_fn(&Token::hasKnownIntValue))) + continue; + equal = std::equal(args1.begin(), + args1.end(), + args2.begin(), + [&](const Token* atok, const Token* btok) { + return atok->values().front().intvalue == + btok->values().front().intvalue; + }); + } else { + equal = false; + } + } else { + continue; + } + result.intvalue = parent->str() == "==" ? equal : !equal; } else { continue; } diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index bc03bad77..a3eba70ff 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -163,6 +163,7 @@ private: TEST_CASE(valueFlowSmartPointer); TEST_CASE(valueFlowImpossibleMinMax); TEST_CASE(valueFlowImpossibleUnknownConstant); + TEST_CASE(valueFlowContainerEqual); } static bool isNotTokValue(const ValueFlow::Value &val) { @@ -7889,6 +7890,58 @@ private: "}\n"; ASSERT_EQUALS(true, testValueOfXImpossible(code, 4U, 0)); } + + void valueFlowContainerEqual() + { + const char* code; + + code = "bool f() {\n" + " std::string s = \"abc\";\n" + " bool x = (s == \"def\");\n" + " return x;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfXKnown(code, 4U, 0)); + + code = "bool f() {\n" + " std::string s = \"abc\";\n" + " bool x = (s != \"def\");\n" + " return x;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfXKnown(code, 4U, 1)); + + code = "bool f() {\n" + " std::vector v1 = {1, 2};\n" + " std::vector v2 = {1, 2};\n" + " bool x = (v1 == v2);\n" + " return x;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfXKnown(code, 5U, 1)); + + code = "bool f() {\n" + " std::vector v1 = {1, 2};\n" + " std::vector v2 = {1, 2};\n" + " bool x = (v1 != v2);\n" + " return x;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfXKnown(code, 5U, 0)); + + code = "bool f(int i) {\n" + " std::vector v1 = {i, i+1};\n" + " std::vector v2 = {i};\n" + " bool x = (v1 == v2);\n" + " return x;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfXKnown(code, 5U, 0)); + + code = "bool f(int i, int j) {\n" + " std::vector v1 = {i, i};\n" + " std::vector v2 = {i, j};\n" + " bool x = (v1 == v2);\n" + " return x;\n" + "}\n"; + ASSERT_EQUALS(false, testValueOfX(code, 5U, 1)); + ASSERT_EQUALS(false, testValueOfX(code, 5U, 0)); + } }; REGISTER_TEST(TestValueFlow)