Merge pull request #2783 from pfultz2/out-of-bounds-at-index

This commit is contained in:
Daniel Marjamäki 2020-09-08 20:30:31 +02:00 committed by GitHub
commit 5376decbe7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 3 deletions

View File

@ -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,9 +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) {
outOfBoundsError(parent->tokAt(2), tok->expressionString(), &value, parent->strAt(1), nullptr);
continue;
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->getMaxValue(false);
if (indexValue && indexValue->intvalue >= value.intvalue) {
outOfBoundsError(
parent, tok->expressionString(), &value, indexTok->expressionString(), indexValue);
continue;
}
if (mSettings->isEnabled(Settings::WARNING)) {
indexValue = indexTok->getMaxValue(true);
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();

View File

@ -347,6 +347,24 @@ 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() {