From ed6c76ce04dcb4b851683821cb27cb72a5be1e67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Fri, 31 Dec 2010 17:43:38 +0100 Subject: [PATCH] Fixed #2385 (False positive: array index out of bounds) --- lib/checkbufferoverrun.cpp | 73 ++++++++++++++++++++++++-------------- test/testbufferoverrun.cpp | 12 +++++++ 2 files changed, 59 insertions(+), 26 deletions(-) diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index 8bb441f97..f436e19e9 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -186,6 +186,52 @@ private: const std::string value; }; + +/** + * bailout if variable is used inside if/else/switch block or if there is "break" + * @param tok token for "if" or "switch" + * @param varid variable id + * @return is bailout recommended? + */ +static bool bailoutIfSwitch(const Token *tok, const unsigned int varid) +{ + const std::string str1(tok->str()); + + unsigned int indentlevel = 0; + for (; tok; tok = tok->next()) + { + if (tok->str() == "{") + indentlevel++; + else if (tok->str() == "}") + { + // scan the else-block + if (indentlevel == 1 && Token::simpleMatch(tok, "} else {")) + { + --indentlevel; + continue; + } + else if (indentlevel <= 1) + { + break; + } + + --indentlevel; + } + + // If scanning a "if" block then bailout for "break" + else if (str1 == "if" && tok->str() == "break") + return true; + + + // bailout if varid is found + else if (tok->varId() == varid) + return true; + } + + // No bailout stuff found => return false + return false; +} + /** * Parse for loop initialization statement. Look for a counter variable * \param tok [in] first token inside the parentheses @@ -407,32 +453,7 @@ void CheckBufferOverrun::parse_for_body(const Token *tok2, const ArrayInfo &arra if (Token::Match(tok2, "if|switch")) { - bool bailout = false; - unsigned int indentlevel3 = 0; - for (const Token *tok3 = tok2; tok3; tok3 = tok3->next()) - { - if (tok3->str() == "{") - indentlevel3++; - else if (tok3->str() == "}") - { - if (indentlevel3 <= 1) - break; - --indentlevel3; - } - else if (tok3->str() == "break" && tok2->str() == "if") - { - bailout = true; - break; - } - else if (tok3->varId() == arrayInfo.varid) - { - bailout = true; - break; - } - } - - // Bailout - if (bailout) + if (bailoutIfSwitch(tok2, arrayInfo.varid)) break; } diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index 0708837cc..94634c979 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -1338,6 +1338,18 @@ private: " }\n" "}\n"); ASSERT_EQUALS("[test.cpp:6]: (error) Buffer access out-of-bounds: a\n", errout.str()); + + // Ticket #2385 - No false positive + check("void f() {\n" + " int a[10];\n" + " for (int i = 0; i < 20; ++i) {\n" + " if (i<10) {\n" + " } else {\n" + " a[i-10] = 0;\n" + " }\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); }