10153: Check that string.find() is compared with 0 before recommending starts_with() (#3099)

This commit is contained in:
Ken-Patrick Lehrmann 2021-01-31 12:05:38 +01:00 committed by GitHub
parent 1b9865be12
commit 4e35f19659
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 5 deletions

View File

@ -1340,19 +1340,24 @@ void CheckStl::stlBoundariesError(const Token *tok)
"container is not guaranteed. One should use operator!= instead to compare iterators.", CWE664, false); "container is not guaranteed. One should use operator!= instead to compare iterators.", CWE664, false);
} }
static bool if_findCompare(const Token * const tokBack) static bool if_findCompare(const Token * const tokBack, bool stdStringLike)
{ {
const Token *tok = tokBack->astParent(); const Token *tok = tokBack->astParent();
if (!tok) if (!tok)
return true; return true;
if (tok->isComparisonOp()) if (tok->isComparisonOp()) {
if (stdStringLike) {
const Token * const tokOther = tokBack->astSibling();
return !tokOther->hasKnownIntValue() || tokOther->getKnownIntValue() != 0;
}
return (!tok->astOperand1()->isNumber() && !tok->astOperand2()->isNumber()); return (!tok->astOperand1()->isNumber() && !tok->astOperand2()->isNumber());
}
if (tok->isArithmeticalOp()) // result is used in some calculation if (tok->isArithmeticalOp()) // result is used in some calculation
return true; // TODO: check if there is a comparison of the result somewhere return true; // TODO: check if there is a comparison of the result somewhere
if (tok->str() == ".") if (tok->str() == ".")
return true; // Dereferencing is OK, the programmer might know that the element exists - TODO: An inconclusive warning might be appropriate return true; // Dereferencing is OK, the programmer might know that the element exists - TODO: An inconclusive warning might be appropriate
if (tok->isAssignmentOp()) if (tok->isAssignmentOp())
return if_findCompare(tok); // Go one step upwards in the AST return if_findCompare(tok, stdStringLike); // Go one step upwards in the AST
return false; return false;
} }
@ -1411,7 +1416,7 @@ void CheckStl::if_find()
} }
if (container && container->getAction(funcTok->str()) == Library::Container::Action::FIND) { if (container && container->getAction(funcTok->str()) == Library::Container::Action::FIND) {
if (if_findCompare(funcTok->next())) if (if_findCompare(funcTok->next(), container->stdStringLike))
continue; continue;
if (printWarning && container->getYield(funcTok->str()) == Library::Container::Yield::ITERATOR) if (printWarning && container->getYield(funcTok->str()) == Library::Container::Yield::ITERATOR)
@ -1420,7 +1425,7 @@ void CheckStl::if_find()
if_findError(tok, true); if_findError(tok, true);
} else if (printWarning && Token::Match(tok, "std :: find|find_if (")) { } else if (printWarning && Token::Match(tok, "std :: find|find_if (")) {
// check that result is checked properly // check that result is checked properly
if (!if_findCompare(tok->tokAt(3))) { if (!if_findCompare(tok->tokAt(3), false)) {
if_findError(tok, false); if_findError(tok, false);
} }
} }

View File

@ -2732,6 +2732,17 @@ private:
" if (s.find_first_of(\"abc\")==0) { }\n" " if (s.find_first_of(\"abc\")==0) { }\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// # 10153
check("int main() {\n"
" for (;;) {\n"
" std::string line = getLine();\n"
" if (line.find(\" GL_EXTENSIONS =\") < 12)\n"
" return 1;\n"
" }\n"
" return 0;\n"
"}");
ASSERT_EQUALS("", errout.str());
} }