From dc201d110dd657ebeb6f398d7086b937cfcd5ab0 Mon Sep 17 00:00:00 2001 From: Paul Fultz II Date: Tue, 3 Sep 2019 06:43:54 +0200 Subject: [PATCH] Fix issue 9274: false negative: (error) Buffer is accessed out of bounds (std::string, std::wstring) --- lib/valueflow.cpp | 14 +++++++++++++- test/teststl.cpp | 9 +++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index aacc4fef9..a124fff7d 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -5249,6 +5249,18 @@ static void valueFlowContainerForward(Token *tok, nonneg int containerId, ValueF if (isContainerSizeChanged(containerId, start, start->link())) break; } + if (Token::simpleMatch(tok, ") {") && Token::Match(tok->link()->previous(), "while|for|if (")) { + const Token *start = tok->next(); + if (isContainerSizeChanged(containerId, start, start->link())) + break; + tok = start->link(); + if (Token::simpleMatch(tok, "} else {")) { + start = tok->tokAt(2); + if (isContainerSizeChanged(containerId, start, start->link())) + break; + tok = start->link(); + } + } if (tok->varId() != containerId) continue; if (Token::Match(tok, "%name% =")) @@ -5292,7 +5304,7 @@ static bool isContainerSizeChanged(nonneg int varId, const Token *start, const T continue; if (!tok->valueType() || !tok->valueType()->container) return true; - if (Token::Match(tok, "%name% =")) + if (Token::Match(tok, "%name% %assign%|<<")) return true; if (Token::Match(tok, "%name% . %name% (")) { Library::Container::Action action = tok->valueType()->container->getAction(tok->strAt(2)); diff --git a/test/teststl.cpp b/test/teststl.cpp index a7faf8f0c..eb007543f 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -312,6 +312,15 @@ private: "}"); ASSERT_EQUALS("", errout.str()); + // # 9274 + checkNormal("char f(bool b) {\n" + " const std::string s = \"\";\n" + " int x = 6;\n" + " if(b) ++x;\n" + " return s[x];\n" + "}\n"); + ASSERT_EQUALS("test.cpp:5:error:Out of bounds access in 's[x]', if 's' size is 6 and 'x' is 6\n", errout.str()); + checkNormal("void f() {\n" " static const int N = 4;\n" " std::array x;\n"