Skip to content

Commit

Permalink
Fix #12994 FN knownConditionTrueFalse for string size after concatena…
Browse files Browse the repository at this point in the history
…tion (#6669)
  • Loading branch information
chrchr-github authored Aug 8, 2024
1 parent 9b79f3b commit 9c3c0ed
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 12 deletions.
40 changes: 28 additions & 12 deletions lib/valueflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7094,6 +7094,20 @@ static void valueFlowContainerSize(const TokenList& tokenlist,
}
}

auto forwardMinimumContainerSize = [&](MathLib::bigint size, Token* opTok, const Token* exprTok) -> void {
if (size == 0)
return;

ValueFlow::Value value(size - 1);
value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
value.bound = ValueFlow::Value::Bound::Upper;
value.setImpossible();
Token* next = nextAfterAstRightmostLeaf(opTok);
if (!next)
next = opTok->next();
valueFlowForward(next, exprTok, std::move(value), tokenlist, errorLogger, settings);
};

// after assignment
for (const Scope *functionScope : symboldatabase.functionScopes) {
for (auto* tok = const_cast<Token*>(functionScope->bodyStart); tok != functionScope->bodyEnd; tok = tok->next()) {
Expand Down Expand Up @@ -7161,20 +7175,22 @@ static void valueFlowContainerSize(const TokenList& tokenlist,
value.setImpossible();
valueFlowForward(tok->linkAt(2), containerTok, std::move(value), tokenlist, errorLogger, settings);
}
} else if (Token::simpleMatch(tok, "+=") && astIsContainer(tok->astOperand1())) {

} else if (tok->str() == "+=" && astIsContainer(tok->astOperand1())) {
const Token* containerTok = tok->astOperand1();
const Token* valueTok = tok->astOperand2();
MathLib::bigint size = valueFlowGetStrLength(valueTok);
if (size == 0)
continue;
ValueFlow::Value value(size - 1);
value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
value.bound = ValueFlow::Value::Bound::Upper;
value.setImpossible();
Token* next = nextAfterAstRightmostLeaf(tok);
if (!next)
next = tok->next();
valueFlowForward(next, containerTok, std::move(value), tokenlist, errorLogger, settings);
const MathLib::bigint size = valueFlowGetStrLength(valueTok);
forwardMinimumContainerSize(size, tok, containerTok);

} else if (tok->str() == "=" && Token::simpleMatch(tok->astOperand2(), "+") && astIsContainerString(tok)) {
const Token* tok2 = tok->astOperand2();
MathLib::bigint size = 0;
while (Token::simpleMatch(tok2, "+") && tok2->astOperand2()) {
size += valueFlowGetStrLength(tok2->astOperand2());
tok2 = tok2->astOperand1();
}
size += valueFlowGetStrLength(tok2);
forwardMinimumContainerSize(size, tok, tok->astOperand1());
}
}
}
Expand Down
36 changes: 36 additions & 0 deletions test/testvalueflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6949,6 +6949,42 @@ class TestValueFlow : public TestFixture {
" return a[0];\n"
"}\n";
ASSERT(!isKnownContainerSizeValue(tokenValues(code, "a [ 0"), 0).empty());

code = "void f(const std::string& a) {\n" // #12994
" std::string b = a + \"123\";\n"
" if (b.empty()) {}\n"
"}";
ASSERT_EQUALS("", isImpossibleContainerSizeValue(tokenValues(code, "b ."), 2));

code = "void f(const std::string& a) {\n"
" std::string b = \"123\" + a;\n"
" if (b.empty()) {}\n"
"}";
ASSERT_EQUALS("", isImpossibleContainerSizeValue(tokenValues(code, "b ."), 2));

code = "void f(const std::string& a, const std::string& b) {\n"
" std::string c = a + b + \"123\";\n"
" if (c.empty()) {}\n"
"}";
ASSERT_EQUALS("", isImpossibleContainerSizeValue(tokenValues(code, "c ."), 2));

code = "void f(const std::string& a) {\n"
" std::string b = a + \"123\" + \"456\";\n"
" if (b.empty()) {}\n"
"}";
ASSERT_EQUALS("", isImpossibleContainerSizeValue(tokenValues(code, "b ."), 5));

code = "void f(const std::string& a) {\n"
" std::string b = \"123\" + a + \"456\";\n"
" if (b.empty()) {}\n"
"}";
ASSERT_EQUALS("", isImpossibleContainerSizeValue(tokenValues(code, "b ."), 5));

code = "void f(const std::string& a, const std::string& b) {\n"
" std::string c = \"123\" + a + b;\n"
" if (c.empty()) {}\n"
"}";
ASSERT_EQUALS("", isImpossibleContainerSizeValue(tokenValues(code, "c ."), 2));
}

void valueFlowContainerElement()
Expand Down

0 comments on commit 9c3c0ed

Please sign in to comment.