From 54bea2847ac109eefd2a2fe0164d95d89213f678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Fri, 29 Mar 2019 15:20:17 +0100 Subject: [PATCH] STL: Better out of bounds checking for empty containers when index is unknown --- lib/checkstl.cpp | 13 +++++++++---- test/teststl.cpp | 6 ++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index 87f1823f2..80ee8a518 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -76,13 +76,16 @@ void CheckStl::outOfBounds() if (Token::Match(tok, "%name% . %name% (") && container->getYield(tok->strAt(2)) == Library::Container::Yield::START_ITERATOR) { const Token *parent = tok->tokAt(3)->astParent(); const Token *other = nullptr; - if (Token::simpleMatch(parent, "+") && parent->astOperand1() && parent->astOperand1()->hasKnownIntValue()) - other = parent->astOperand1(); - else if (Token::simpleMatch(parent, "+") && parent->astOperand2() && parent->astOperand2()->hasKnownIntValue()) + if (Token::simpleMatch(parent, "+") && parent->astOperand1() == tok->tokAt(3)) other = parent->astOperand2(); - if (other && other->getKnownIntValue() > value.intvalue) { + else if (Token::simpleMatch(parent, "+") && parent->astOperand2() == tok->tokAt(3)) + other = parent->astOperand1(); + if (other && other->hasKnownIntValue() && other->getKnownIntValue() > value.intvalue) { outOfBoundsError(parent, tok->str(), &value, other->expressionString(), &other->values().back()); continue; + } else if (other && !other->hasKnownIntValue() && value.isKnown() && value.intvalue==0) { + outOfBoundsError(parent, tok->str(), &value, other->expressionString(), nullptr); + continue; } } if (!container->arrayLike_indexOp && !container->stdStringLike) @@ -124,6 +127,8 @@ void CheckStl::outOfBoundsError(const Token *tok, const std::string &containerNa else if (containerSize->intvalue == 0) { if (containerSize->condition) errmsg = ValueFlow::eitherTheConditionIsRedundant(containerSize->condition) + " or expression '" + expression + "' cause access out of bounds."; + else if (indexValue == nullptr && !index.empty()) + errmsg = "Out of bounds access in expression '" + expression + "' because '$symbol' is empty and '" + index + "' may be non-zero."; else errmsg = "Out of bounds access in expression '" + expression + "' because '$symbol' is empty."; } else if (indexValue) { diff --git a/test/teststl.cpp b/test/teststl.cpp index e9e359fab..a5a258b91 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -280,6 +280,12 @@ private: " x = s.begin() + 1;\n" "}\n"); ASSERT_EQUALS("test.cpp:3:error:Out of bounds access in expression 's.begin()+1' because 's' is empty.\n", errout.str()); + + checkNormal("void f(int x) {\n" + " std::string s;\n" + " x = s.begin() + x;\n" + "}\n"); + ASSERT_EQUALS("test.cpp:3:error:Out of bounds access in expression 's.begin()+x' because 's' is empty and 'x' may be non-zero.\n", errout.str()); } void outOfBoundsIndexExpression() {