Skip to content

Commit e3ef82e

Browse files
Fix #14342 FN containerOutOfBounds (std::string_view of array, constructor call) (#8190)
1 parent 70d3545 commit e3ef82e

2 files changed

Lines changed: 40 additions & 17 deletions

File tree

lib/valueflow.cpp

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6490,6 +6490,9 @@ static std::vector<ValueFlow::Value> getContainerSizeFromConstructorArgs(const s
64906490
if (astIsPointer(args[0])) {
64916491
if (args.size() == 1 && args[0]->tokType() == Token::Type::eString)
64926492
return {makeContainerSizeValue(Token::getStrLength(args[0]), known)};
6493+
if (args.size() == 1 && args[0]->variable() && args[0]->variable()->isArray() &&
6494+
args[0]->variable()->isConst() && args[0]->variable()->dimensions().size() == 1)
6495+
return {makeContainerSizeValue(args[0]->variable()->dimensions()[0].num, known)};
64936496
if (args.size() == 2 && astIsIntegral(args[1], false)) // { char*, count }
64946497
return {makeContainerSizeValue(args[1], known)};
64956498
} else if (astIsContainer(args[0])) {
@@ -6707,23 +6710,25 @@ static void valueFlowContainerSize(const TokenList& tokenlist,
67076710
for (const ValueFlow::Value& value : values)
67086711
setTokenValue(tok, value, settings);
67096712
}
6710-
else if (Token::Match(tok->previous(), ",|( {|%str%")) {
6711-
int nArg{};
6712-
if (const Token* funcTok = getTokenArgumentFunction(tok, nArg)) {
6713-
if (const Function* func = funcTok->function()) {
6714-
if (const Variable* var = func->getArgumentVar(nArg)) {
6715-
if (var->valueType() && var->valueType()->container && var->valueType()->container->size_templateArgNo < 0) {
6716-
auto values = tok->tokType() == Token::Type::eString
6717-
? std::vector<ValueFlow::Value>{makeContainerSizeValue(Token::getStrLength(tok))}
6718-
: getInitListSize(tok, var->valueType(), settings, true);
6719-
ValueFlow::Value tokValue;
6720-
tokValue.valueType = ValueFlow::Value::ValueType::TOK;
6721-
tokValue.tokvalue = tok;
6722-
tokValue.setKnown();
6723-
values.push_back(std::move(tokValue));
6724-
6725-
for (const ValueFlow::Value &value : values)
6726-
setTokenValue(tok, value, settings);
6713+
else if (Token::Match(tok->previous(), ",|(") && (Token::Match(tok, "{|%str%") || settings.library.detectContainer(tok))) {
6714+
if (Token* argTok = tok->previous()->astOperand2()) {
6715+
int nArg{};
6716+
if (const Token* funcTok = getTokenArgumentFunction(argTok, nArg)) {
6717+
if (const Function* func = funcTok->function()) {
6718+
if (const Variable* var = func->getArgumentVar(nArg)) {
6719+
if (var->valueType() && var->valueType()->container && var->valueType()->container->size_templateArgNo < 0) {
6720+
auto values = argTok->tokType() == Token::Type::eString
6721+
? std::vector<ValueFlow::Value>{makeContainerSizeValue(Token::getStrLength(argTok))}
6722+
: getInitListSize(argTok, var->valueType(), settings, true);
6723+
ValueFlow::Value tokValue;
6724+
tokValue.valueType = ValueFlow::Value::ValueType::TOK;
6725+
tokValue.tokvalue = argTok;
6726+
tokValue.setKnown();
6727+
values.push_back(std::move(tokValue));
6728+
6729+
for (const ValueFlow::Value& value : values)
6730+
setTokenValue(argTok, value, settings);
6731+
}
67276732
}
67286733
}
67296734
}

test/teststl.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,24 @@ class TestStl : public TestFixture {
980980
"}\n");
981981
ASSERT_EQUALS("[test.cpp:4:13]: error: Out of bounds access in 'x[3]', if 'x' size is 1 and '3' is 3 [containerOutOfBounds]\n",
982982
errout_str());
983+
984+
checkNormal("int main() {\n"
985+
" const char a[] = \"abc\";\n"
986+
" std::string_view x{ a };\n"
987+
" return x[5];\n"
988+
"}\n");
989+
ASSERT_EQUALS("[test.cpp:4:13]: error: Out of bounds access in 'x[5]', if 'x' size is 4 and '5' is 5 [containerOutOfBounds]\n",
990+
errout_str());
991+
992+
checkNormal("int f(const std::string& v) {\n"
993+
" return v[2];\n"
994+
"}\n"
995+
"int main() {\n"
996+
" std::string_view x{ \"a\" };\n"
997+
" return f(std::string(x));\n"
998+
"}\n");
999+
ASSERT_EQUALS("[test.cpp:2:13]: error: Out of bounds access in 'v[2]', if 'v' size is 1 and '2' is 2 [containerOutOfBounds]\n",
1000+
errout_str());
9831001
}
9841002

9851003
void outOfBoundsSymbolic()

0 commit comments

Comments
 (0)