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
This commit is contained in:
Paul Fultz II 2023-04-06 11:42:24 -05:00 committed by GitHub
parent 47fdd1e1e3
commit e22a740f0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 83 additions and 1 deletions

View File

@ -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<const Token*> args1 = getArguments(tok1);
std::vector<const Token*> 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;
}

View File

@ -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<int> v1 = {1, 2};\n"
" std::vector<int> 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<int> v1 = {1, 2};\n"
" std::vector<int> 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<int> v1 = {i, i+1};\n"
" std::vector<int> 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<int> v1 = {i, i};\n"
" std::vector<int> 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)