From 07e00d57d996f166e68a1deb1963f6c27dc928f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 5 Jun 2010 09:45:35 +0200 Subject: [PATCH] Fixed #1725 (segfault in ExecutionPath::bailOutVar (probably caused by #1721 fix)) --- lib/executionpath.cpp | 164 ++++++++++++++++++------------------------ test/testother.cpp | 15 ++++ 2 files changed, 86 insertions(+), 93 deletions(-) diff --git a/lib/executionpath.cpp b/lib/executionpath.cpp index a72902ca1..e576d6e15 100644 --- a/lib/executionpath.cpp +++ b/lib/executionpath.cpp @@ -25,6 +25,9 @@ #include +static void checkExecutionPaths_(const Token *tok, std::list &checks); + + // default : bail out if the condition is has variable handling bool ExecutionPath::parseCondition(const Token &tok, std::list & checks) { @@ -80,6 +83,61 @@ static void printchecks(const std::list &checks) #endif + +/** + * @brief Parse If/Switch body recursively. + * @param tok First token in body. + * @param checks The current checks + * @param newchecks new checks + * @param countif The countif set - count number of if for each execution path + */ +static void parseIfSwitchBody(const Token * const tok, + const std::list &checks, + std::list &newchecks, + std::set &countif) +{ + std::set countif2; + std::list c; + if (!checks.empty()) + { + std::list::const_iterator it; + for (it = checks.begin(); it != checks.end(); ++it) + { + c.push_back((*it)->copy()); + if ((*it)->varId != 0) + countif2.insert((*it)->varId); + } + } + checkExecutionPaths_(tok, c); + while (!c.empty()) + { + if (c.back()->varId == 0) + { + c.pop_back(); + continue; + } + + bool duplicate = false; + std::list::const_iterator it; + for (it = checks.begin(); it != checks.end(); ++it) + { + if (*(*it) == *c.back()) + { + duplicate = true; + countif2.erase((*it)->varId); + break; + } + } + if (!duplicate) + newchecks.push_back(c.back()); + c.pop_back(); + } + + // Add countif2 ids to countif.. countif. + countif.insert(countif2.begin(), countif2.end()); +} + + static void checkExecutionPaths_(const Token *tok, std::list &checks) { if (!tok || tok->str() == "}" || checks.empty()) @@ -138,62 +196,22 @@ static void checkExecutionPaths_(const Token *tok, std::list &c tok2 = tok2->link(); else if (tok2->str() == "}") break; - else if (tok2->str() == "case") + else if (tok2->str() == "case" && + !Token::Match(tok2, "case %num% : ; case")) { - if (Token::Match(tok2, "case %num% : ; case")) - continue; - - std::set countif2; - std::list c; - if (!checks.empty()) - { - std::list::const_iterator it; - for (it = checks.begin(); it != checks.end(); ++it) - { - c.push_back((*it)->copy()); - if ((*it)->varId != 0) - countif2.insert((*it)->varId); - } - } - checkExecutionPaths_(tok2, c); - while (!c.empty()) - { - if (c.back()->varId == 0) - { - c.pop_back(); - continue; - } - - bool duplicate = false; - std::list::const_iterator it; - for (it = checks.begin(); it != checks.end(); ++it) - { - if (*(*it) == *c.back()) - { - duplicate = true; - countif2.erase((*it)->varId); - break; - } - } - if (!duplicate) - newchecks.push_back(c.back()); - c.pop_back(); - } - - // Add countif2 ids to countif.. countif. - countif.insert(countif2.begin(), countif2.end()); + parseIfSwitchBody(tok2, checks, newchecks, countif); } + } - // Add newchecks to checks.. - std::copy(newchecks.begin(), newchecks.end(), std::back_inserter(checks)); + // Add newchecks to checks.. + std::copy(newchecks.begin(), newchecks.end(), std::back_inserter(checks)); - // Increase numberOfIf - std::list::iterator it; - for (it = checks.begin(); it != checks.end(); ++it) - { - if (countif.find((*it)->varId) != countif.end()) - (*it)->numberOfIf++; - } + // Increase numberOfIf + std::list::iterator it; + for (it = checks.begin(); it != checks.end(); ++it) + { + if (countif.find((*it)->varId) != countif.end()) + (*it)->numberOfIf++; } } } @@ -336,47 +354,7 @@ static void checkExecutionPaths_(const Token *tok, std::list &c } // Recursively check into the if .. - { - std::set countif2; - std::list c; - if (!checks.empty()) - { - std::list::const_iterator it; - for (it = checks.begin(); it != checks.end(); ++it) - { - c.push_back((*it)->copy()); - if ((*it)->varId != 0) - countif2.insert((*it)->varId); - } - } - checkExecutionPaths_(tok->next(), c); - while (!c.empty()) - { - if (c.back()->varId == 0) - { - c.pop_back(); - continue; - } - - bool duplicate = false; - std::list::const_iterator it; - for (it = checks.begin(); it != checks.end(); ++it) - { - if (*(*it) == *c.back()) - { - duplicate = true; - countif2.erase((*it)->varId); - break; - } - } - if (!duplicate) - newchecks.push_back(c.back()); - c.pop_back(); - } - - // Add countif2 ids to countif.. - countif.insert(countif2.begin(), countif2.end()); - } + parseIfSwitchBody(tok->next(), checks, newchecks, countif); // goto "}" tok = tok->link(); diff --git a/test/testother.cpp b/test/testother.cpp index 4b360e029..def0d767c 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -1754,6 +1754,21 @@ private: " return i;\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + // No segmentation fault + checkUninitVar("void a() try\n" + "{\n" + " {\n" + " while (1) {\n" + " switch (1) {\n" + " case 1: {\n" + " int i;\n" + " }\n" + " }\n" + " }\n" + " } catch (...) {\n" + " }\n" + "}\n"); } // arrays..