Skip to content

Commit 4e35f19

Browse files
authored
10153: Check that string.find() is compared with 0 before recommending starts_with() (cppcheck-opensource#3099)
1 parent 1b9865b commit 4e35f19

2 files changed

Lines changed: 21 additions & 5 deletions

File tree

lib/checkstl.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,19 +1340,24 @@ void CheckStl::stlBoundariesError(const Token *tok)
13401340
"container is not guaranteed. One should use operator!= instead to compare iterators.", CWE664, false);
13411341
}
13421342

1343-
static bool if_findCompare(const Token * const tokBack)
1343+
static bool if_findCompare(const Token * const tokBack, bool stdStringLike)
13441344
{
13451345
const Token *tok = tokBack->astParent();
13461346
if (!tok)
13471347
return true;
1348-
if (tok->isComparisonOp())
1348+
if (tok->isComparisonOp()) {
1349+
if (stdStringLike) {
1350+
const Token * const tokOther = tokBack->astSibling();
1351+
return !tokOther->hasKnownIntValue() || tokOther->getKnownIntValue() != 0;
1352+
}
13491353
return (!tok->astOperand1()->isNumber() && !tok->astOperand2()->isNumber());
1354+
}
13501355
if (tok->isArithmeticalOp()) // result is used in some calculation
13511356
return true; // TODO: check if there is a comparison of the result somewhere
13521357
if (tok->str() == ".")
13531358
return true; // Dereferencing is OK, the programmer might know that the element exists - TODO: An inconclusive warning might be appropriate
13541359
if (tok->isAssignmentOp())
1355-
return if_findCompare(tok); // Go one step upwards in the AST
1360+
return if_findCompare(tok, stdStringLike); // Go one step upwards in the AST
13561361
return false;
13571362
}
13581363

@@ -1411,7 +1416,7 @@ void CheckStl::if_find()
14111416
}
14121417

14131418
if (container && container->getAction(funcTok->str()) == Library::Container::Action::FIND) {
1414-
if (if_findCompare(funcTok->next()))
1419+
if (if_findCompare(funcTok->next(), container->stdStringLike))
14151420
continue;
14161421

14171422
if (printWarning && container->getYield(funcTok->str()) == Library::Container::Yield::ITERATOR)
@@ -1420,7 +1425,7 @@ void CheckStl::if_find()
14201425
if_findError(tok, true);
14211426
} else if (printWarning && Token::Match(tok, "std :: find|find_if (")) {
14221427
// check that result is checked properly
1423-
if (!if_findCompare(tok->tokAt(3))) {
1428+
if (!if_findCompare(tok->tokAt(3), false)) {
14241429
if_findError(tok, false);
14251430
}
14261431
}

test/teststl.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2732,6 +2732,17 @@ class TestStl : public TestFixture {
27322732
" if (s.find_first_of(\"abc\")==0) { }\n"
27332733
"}");
27342734
ASSERT_EQUALS("", errout.str());
2735+
2736+
// # 10153
2737+
check("int main() {\n"
2738+
" for (;;) {\n"
2739+
" std::string line = getLine();\n"
2740+
" if (line.find(\" GL_EXTENSIONS =\") < 12)\n"
2741+
" return 1;\n"
2742+
" }\n"
2743+
" return 0;\n"
2744+
"}");
2745+
ASSERT_EQUALS("", errout.str());
27352746
}
27362747

27372748

0 commit comments

Comments
 (0)