From fb4fce466e5148a63ae45a6764786bb76c4a3efa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Fri, 3 Sep 2010 07:18:01 +0200 Subject: [PATCH] Fixed #2014 (False positive with longjmp) --- lib/checkmemoryleak.cpp | 8 ++++++++ lib/executionpath.cpp | 8 ++++---- test/testmemleak.cpp | 27 +++++++++++++++++++++++++++ test/testother.cpp | 14 +++++++++++++- 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 5e0db0211..a9f485e00 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -1360,6 +1360,14 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list bail out + else if (Token::Match(tok, "setjmp|longjmp")) + { + while (rethead->next()) + rethead->deleteNext(); + return rethead; + } + // Inside class function.. if the var is passed as a parameter then // just add a "::use" // The "::use" means that a member function was probably called but it wasn't analyzed further diff --git a/lib/executionpath.cpp b/lib/executionpath.cpp index 4dac6afb9..b06b9b16d 100644 --- a/lib/executionpath.cpp +++ b/lib/executionpath.cpp @@ -76,13 +76,13 @@ void ExecutionPath::print() const } // I use this function when debugging ExecutionPaths with GDB -#ifdef __GNUC__ +/* static void printchecks(const std::list &checks) { for (std::list::const_iterator it = checks.begin(); it != checks.end(); ++it) (*it)->print(); } -#endif +*/ @@ -176,8 +176,8 @@ static void checkExecutionPaths_(const Token *tok, std::list &c } } - // goto => bailout - if (tok->str() == "goto") + // goto/setjmp/longjmp => bailout + if (Token::Match(tok, "goto|setjmp|longjmp")) { ExecutionPath::bailOut(checks); return; diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index 8b0e8434f..0fa69c68c 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -403,6 +403,9 @@ private: // #1440 - Check function parameters also.. TEST_CASE(functionParameter); + + // setjmp/longjmp.. + TEST_CASE(jmp); } @@ -2913,6 +2916,30 @@ private: "}\n"); ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: p\n", errout.str()); } + + // Ticket #2014 - setjmp / longjmp + void jmp() + { + check("int main()\n" + "{\n" + " jmp_buf env;\n" + " int val;\n" + " char *a;\n" + "\n" + " val = setjmp(env);\n" + " if(val)\n" + " {\n" + " delete a;\n" + " return 0;\n" + " }\n" + "\n" + " a = new char(1);\n" + " longjmp(env, 1);\n" + "\n" + " return 0;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + } }; static TestMemleakInFunction testMemleakInFunction; diff --git a/test/testother.cpp b/test/testother.cpp index b0dfaf1c6..49518cfa2 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -1589,7 +1589,7 @@ private: "}\n"); ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: a\n", errout.str()); - // goto.. + // goto/setjmp/longjmp.. checkUninitVar("void foo(int x)\n" "{\n" " long b;\n" @@ -1605,6 +1605,18 @@ private: "}\n"); ASSERT_EQUALS("", errout.str()); + checkUninitVar("int foo()\n" + "{\n" + " jmp_buf env;\n" + " int a;\n" + " int val = setjmp(env);\n" + " if(val)\n" + " return a;\n" + " a = 1;\n" + " longjmp(env, 1);\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + // macro_for.. checkUninitVar("int foo()\n" "{\n"