Skip to content

Commit 9c3c0ed

Browse files
Fix #12994 FN knownConditionTrueFalse for string size after concatenation (#6669)
1 parent 9b79f3b commit 9c3c0ed

2 files changed

Lines changed: 64 additions & 12 deletions

File tree

lib/valueflow.cpp

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7094,6 +7094,20 @@ static void valueFlowContainerSize(const TokenList& tokenlist,
70947094
}
70957095
}
70967096

7097+
auto forwardMinimumContainerSize = [&](MathLib::bigint size, Token* opTok, const Token* exprTok) -> void {
7098+
if (size == 0)
7099+
return;
7100+
7101+
ValueFlow::Value value(size - 1);
7102+
value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
7103+
value.bound = ValueFlow::Value::Bound::Upper;
7104+
value.setImpossible();
7105+
Token* next = nextAfterAstRightmostLeaf(opTok);
7106+
if (!next)
7107+
next = opTok->next();
7108+
valueFlowForward(next, exprTok, std::move(value), tokenlist, errorLogger, settings);
7109+
};
7110+
70977111
// after assignment
70987112
for (const Scope *functionScope : symboldatabase.functionScopes) {
70997113
for (auto* tok = const_cast<Token*>(functionScope->bodyStart); tok != functionScope->bodyEnd; tok = tok->next()) {
@@ -7161,20 +7175,22 @@ static void valueFlowContainerSize(const TokenList& tokenlist,
71617175
value.setImpossible();
71627176
valueFlowForward(tok->linkAt(2), containerTok, std::move(value), tokenlist, errorLogger, settings);
71637177
}
7164-
} else if (Token::simpleMatch(tok, "+=") && astIsContainer(tok->astOperand1())) {
7178+
7179+
} else if (tok->str() == "+=" && astIsContainer(tok->astOperand1())) {
71657180
const Token* containerTok = tok->astOperand1();
71667181
const Token* valueTok = tok->astOperand2();
7167-
MathLib::bigint size = valueFlowGetStrLength(valueTok);
7168-
if (size == 0)
7169-
continue;
7170-
ValueFlow::Value value(size - 1);
7171-
value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
7172-
value.bound = ValueFlow::Value::Bound::Upper;
7173-
value.setImpossible();
7174-
Token* next = nextAfterAstRightmostLeaf(tok);
7175-
if (!next)
7176-
next = tok->next();
7177-
valueFlowForward(next, containerTok, std::move(value), tokenlist, errorLogger, settings);
7182+
const MathLib::bigint size = valueFlowGetStrLength(valueTok);
7183+
forwardMinimumContainerSize(size, tok, containerTok);
7184+
7185+
} else if (tok->str() == "=" && Token::simpleMatch(tok->astOperand2(), "+") && astIsContainerString(tok)) {
7186+
const Token* tok2 = tok->astOperand2();
7187+
MathLib::bigint size = 0;
7188+
while (Token::simpleMatch(tok2, "+") && tok2->astOperand2()) {
7189+
size += valueFlowGetStrLength(tok2->astOperand2());
7190+
tok2 = tok2->astOperand1();
7191+
}
7192+
size += valueFlowGetStrLength(tok2);
7193+
forwardMinimumContainerSize(size, tok, tok->astOperand1());
71787194
}
71797195
}
71807196
}

test/testvalueflow.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6949,6 +6949,42 @@ class TestValueFlow : public TestFixture {
69496949
" return a[0];\n"
69506950
"}\n";
69516951
ASSERT(!isKnownContainerSizeValue(tokenValues(code, "a [ 0"), 0).empty());
6952+
6953+
code = "void f(const std::string& a) {\n" // #12994
6954+
" std::string b = a + \"123\";\n"
6955+
" if (b.empty()) {}\n"
6956+
"}";
6957+
ASSERT_EQUALS("", isImpossibleContainerSizeValue(tokenValues(code, "b ."), 2));
6958+
6959+
code = "void f(const std::string& a) {\n"
6960+
" std::string b = \"123\" + a;\n"
6961+
" if (b.empty()) {}\n"
6962+
"}";
6963+
ASSERT_EQUALS("", isImpossibleContainerSizeValue(tokenValues(code, "b ."), 2));
6964+
6965+
code = "void f(const std::string& a, const std::string& b) {\n"
6966+
" std::string c = a + b + \"123\";\n"
6967+
" if (c.empty()) {}\n"
6968+
"}";
6969+
ASSERT_EQUALS("", isImpossibleContainerSizeValue(tokenValues(code, "c ."), 2));
6970+
6971+
code = "void f(const std::string& a) {\n"
6972+
" std::string b = a + \"123\" + \"456\";\n"
6973+
" if (b.empty()) {}\n"
6974+
"}";
6975+
ASSERT_EQUALS("", isImpossibleContainerSizeValue(tokenValues(code, "b ."), 5));
6976+
6977+
code = "void f(const std::string& a) {\n"
6978+
" std::string b = \"123\" + a + \"456\";\n"
6979+
" if (b.empty()) {}\n"
6980+
"}";
6981+
ASSERT_EQUALS("", isImpossibleContainerSizeValue(tokenValues(code, "b ."), 5));
6982+
6983+
code = "void f(const std::string& a, const std::string& b) {\n"
6984+
" std::string c = \"123\" + a + b;\n"
6985+
" if (c.empty()) {}\n"
6986+
"}";
6987+
ASSERT_EQUALS("", isImpossibleContainerSizeValue(tokenValues(code, "c ."), 2));
69526988
}
69536989

69546990
void valueFlowContainerElement()

0 commit comments

Comments
 (0)