From e88a0c00c1f0febc372115f6500aea34785a417a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Thu, 28 Mar 2019 12:49:52 +0100 Subject: [PATCH] Fixed #9039 (STL: array index out of bounds: str.begin() + 1) --- lib/checkstl.cpp | 12 ++++++++++++ test/teststl.cpp | 10 ++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index 2a44904a7..8fe75b2e7 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -73,6 +73,18 @@ void CheckStl::outOfBounds() outOfBoundsError(tok, &value, nullptr); continue; } + 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()) + other = parent->astOperand2(); + if (other && other->getKnownIntValue() > value.intvalue) { + outOfBoundsError(tok, &value, &other->values().back()); + continue; + } + } if (!container->arrayLike_indexOp && !container->stdStringLike) continue; if (value.intvalue == 0 && Token::Match(tok, "%name% [")) { diff --git a/test/teststl.cpp b/test/teststl.cpp index 087d3857c..1a54a88c4 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -274,6 +274,12 @@ private: " x[0];\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + checkNormal("void f() {\n" + " std::string s;\n" + " x = s.begin() + 1;\n" + "}\n"); + ASSERT_EQUALS("test.cpp:3:error:Out of bounds access in s because s is empty.\n", errout.str()); } void outOfBoundsIndexExpression() { @@ -1130,7 +1136,7 @@ private: void dereference() { check("void f()\n" "{\n" - " std::vector ints;\n" + " std::vector ints{1,2,3,4,5};\n" " std::vector::iterator iter;\n" " iter = ints.begin() + 2;\n" " ints.erase(iter);\n" @@ -1202,7 +1208,7 @@ private: void dereference_auto() { check("void f()\n" "{\n" - " std::vector ints;\n" + " std::vector ints{1,2,3,4,5};\n" " auto iter = ints.begin() + 2;\n" " ints.erase(iter);\n" " std::cout << (*iter) << std::endl;\n"