10153: Check that string.find() is compared with 0 before recommending starts_with() (#3099)
This commit is contained in:
parent
1b9865be12
commit
4e35f19659
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue