Fix issue 8869: false negative: (error) Invalid v.at() argument nr 1
This commit is contained in:
parent
136ac2c643
commit
04c85baf03
|
@ -59,6 +59,11 @@ static const struct CWE CWE825(825U); // Expired Pointer Dereference
|
|||
static const struct CWE CWE833(833U); // Deadlock
|
||||
static const struct CWE CWE834(834U); // Excessive Iteration
|
||||
|
||||
static bool isElementAccessYield(const Library::Container::Yield& yield)
|
||||
{
|
||||
return yield == Library::Container::Yield::ITEM || yield == Library::Container::Yield::AT_INDEX;
|
||||
}
|
||||
|
||||
void CheckStl::outOfBounds()
|
||||
{
|
||||
for (const Scope *function : mTokenizer->getSymbolDatabase()->functionScopes) {
|
||||
|
@ -76,10 +81,28 @@ void CheckStl::outOfBounds()
|
|||
continue;
|
||||
if (!value.errorSeverity() && !mSettings->isEnabled(Settings::WARNING))
|
||||
continue;
|
||||
if (value.intvalue == 0 && Token::Match(parent, ". %name% (") && container->getYield(parent->strAt(1)) == Library::Container::Yield::ITEM) {
|
||||
if (Token::Match(parent, ". %name% (") && isElementAccessYield(container->getYield(parent->strAt(1)))) {
|
||||
if (value.intvalue == 0) {
|
||||
outOfBoundsError(parent->tokAt(2), tok->expressionString(), &value, parent->strAt(1), nullptr);
|
||||
continue;
|
||||
}
|
||||
const Token* indexTok = parent->tokAt(2)->astOperand2();
|
||||
if (!indexTok)
|
||||
continue;
|
||||
const ValueFlow::Value *indexValue = indexTok ? indexTok->getMaxValue(false) : nullptr;
|
||||
if (indexValue && indexValue->intvalue >= value.intvalue) {
|
||||
outOfBoundsError(parent, tok->expressionString(), &value, indexTok->expressionString(), indexValue);
|
||||
continue;
|
||||
}
|
||||
if (mSettings->isEnabled(Settings::WARNING)) {
|
||||
indexValue = indexTok ? indexTok->getMaxValue(true) : nullptr;
|
||||
if (indexValue && indexValue->intvalue >= value.intvalue) {
|
||||
outOfBoundsError(parent, tok->expressionString(), &value, indexTok->expressionString(), indexValue);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (Token::Match(tok, "%name% . %name% (") && container->getYield(tok->strAt(2)) == Library::Container::Yield::START_ITERATOR) {
|
||||
const Token *fparent = tok->tokAt(3)->astParent();
|
||||
const Token *other = nullptr;
|
||||
|
|
|
@ -347,6 +347,20 @@ private:
|
|||
" x[0] = 2;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
checkNormal("void f(bool b) {\n"
|
||||
" std::vector<int> v;\n"
|
||||
" if(v.at(b?42:0)) {}\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("test.cpp:3:error:Out of bounds access in expression 'v.at(b?42:0)' because 'v' is empty and 'at' may be non-zero.\n", errout.str());
|
||||
|
||||
checkNormal("void f(std::vector<int> v, bool b){\n"
|
||||
" if (v.size() == 1)\n"
|
||||
" if(v.at(b?42:0)) {}\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("test.cpp:3:warning:Either the condition 'v.size()==1' is redundant or v size can be 1. Expression 'v.at' cause access out of bounds.\n"
|
||||
"test.cpp:2:note:condition 'v.size()==1'\n"
|
||||
"test.cpp:3:note:Access out of bounds\n", errout.str());
|
||||
}
|
||||
|
||||
void outOfBoundsIndexExpression() {
|
||||
|
|
Loading…
Reference in New Issue