From 79af6f65d7bbf961572a33933b18b11c4b0d5228 Mon Sep 17 00:00:00 2001 From: Ahti Legonkov Date: Sun, 22 Apr 2012 06:49:42 +0200 Subject: [PATCH] Fixed #3699 (cppcheck hangs with 100% cpu load on parsing preprocessor code) --- lib/preprocessor.cpp | 14 +++++++++++--- test/testpreprocessor.cpp | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 05fc23089..303c8915e 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -890,10 +890,18 @@ static void simplifyVarMap(std::map &variables) // TODO: 1. tokenize the value, replace each token like this. // TODO: 2. handle function-macros too. + std::set seenVariables; std::map::iterator it = variables.find(varValue); - while (it != variables.end() && it->first != it->second && it != i) { - varValue = it->second; - it = variables.find(varValue); + while (it != variables.end() && it->first != it->second) { + if (seenVariables.find(it->first) != seenVariables.end()) { + // We have already seen this variable. there is a cycle of #define that we can't process at + // this time. Stop trying to simplify the current variable and leave it as is. + break; + } else { + seenVariables.insert(it->first); + varValue = it->second; + it = variables.find(varValue); + } } } } diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index cddf6e19e..0c2363198 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -132,6 +132,7 @@ private: TEST_CASE(if_macro_eq_macro); // #3536 TEST_CASE(ticket_3675); + TEST_CASE(ticket_3699); TEST_CASE(multiline1); TEST_CASE(multiline2); @@ -1550,6 +1551,24 @@ private: // There's nothing to assert. It just needs to not hang. } + void ticket_3699() { + const std::string code("#define INLINE __forceinline\n" + "#define inline __forceinline\n" + "#define __forceinline inline\n" + "#if !defined(_WIN32)\n" + "#endif\n" + "INLINE inline __forceinline\n" + ); + Settings settings; + Preprocessor preprocessor(&settings, this); + std::istringstream istr(code); + std::map actual; + preprocessor.preprocess(istr, actual, "file.c"); + + // First, it must not hang. Second, inline must becomes inline, and __forceinline must become __forceinline. + ASSERT_EQUALS("\n\n\n\n\n$$$__forceinline $$inline $$__forceinline\n", actual[""]); + } + void multiline1() { const char filedata[] = "#define str \"abc\" \\\n" " \"def\" \n"