From 82ffa7b35bcc5a8b1d8cbe6aeba24c280093265d Mon Sep 17 00:00:00 2001 From: chrchr Date: Wed, 3 Jan 2024 13:03:34 +0100 Subject: [PATCH 1/4] Fix FN deallocuse with function call (refs #11409) --- lib/checkleakautovar.cpp | 2 ++ test/testleakautovar.cpp | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 86f1ab8164b..2818ea3ee79 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -1045,6 +1045,8 @@ void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpenin const VarInfo::AllocInfo sp_allocation(sp_af ? sp_af->groupId : (arrayDelete ? NEW_ARRAY : NEW), VarInfo::OWNED, allocTok); changeAllocStatus(varInfo, sp_allocation, vtok, vtok); } else { + while (arg->isUnaryOp("*") || arg->isUnaryOp("&")) + arg = arg->astOperand1(); checkTokenInsideExpression(arg, varInfo); } // TODO: check each token in argument expression (could contain multiple variables) diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index ad2212ff298..c03029fe909 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -942,6 +942,14 @@ class TestLeakAutoVar : public TestFixture { "}\n"); ASSERT_EQUALS("[test.c:4]: (error) Dereferencing 'p' after it is deallocated / released\n", errout.str()); + + check("void g(int);\n" + "void f(int* p) {\n" + " free(p);\n" + " g(*p);\n" + "}\n"); + ASSERT_EQUALS("[test.c:4]: (error) Dereferencing 'p' after it is deallocated / released\n", + errout.str()); } void doublefree1() { // #3895 From 9a10eadca522f4c0e4ead61aeab44268a9f3a47a Mon Sep 17 00:00:00 2001 From: chrchr Date: Wed, 3 Jan 2024 13:07:49 +0100 Subject: [PATCH 2/4] Add test --- test/testleakautovar.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index c03029fe909..70ca30fbb34 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -950,6 +950,14 @@ class TestLeakAutoVar : public TestFixture { "}\n"); ASSERT_EQUALS("[test.c:4]: (error) Dereferencing 'p' after it is deallocated / released\n", errout.str()); + + check("int g(int);\n" + "int f(int* p) {\n" + " free(p);\n" + " return g(*p);\n" + "}\n"); + ASSERT_EQUALS("[test.c:3] -> [test.c:4]: (error) Returning/dereferencing 'p' after it is deallocated / released\n", + errout.str()); } void doublefree1() { // #3895 From 3bd7a4536965add263bfc9f99afdebec908be57a Mon Sep 17 00:00:00 2001 From: chrchr Date: Wed, 3 Jan 2024 16:17:47 +0100 Subject: [PATCH 3/4] Fix more FNs --- lib/checkleakautovar.cpp | 10 ++++++---- test/testleakautovar.cpp | 18 ++++++++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 2818ea3ee79..07ccbf140e1 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -1045,9 +1045,11 @@ void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpenin const VarInfo::AllocInfo sp_allocation(sp_af ? sp_af->groupId : (arrayDelete ? NEW_ARRAY : NEW), VarInfo::OWNED, allocTok); changeAllocStatus(varInfo, sp_allocation, vtok, vtok); } else { - while (arg->isUnaryOp("*") || arg->isUnaryOp("&")) - arg = arg->astOperand1(); - checkTokenInsideExpression(arg, varInfo); + const Token* const nextArg = funcArg->nextArgument(); + do { + checkTokenInsideExpression(arg, varInfo); + arg = arg->next(); + } while ((nextArg && arg != nextArg) || (!nextArg && arg != tokOpeningPar->link())); } // TODO: check each token in argument expression (could contain multiple variables) argNr++; @@ -1113,7 +1115,7 @@ void CheckLeakAutoVar::ret(const Token *tok, VarInfo &varInfo, const bool isEndO for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) { if (tok2->str() == ";") break; - if (!Token::Match(tok2, "return|(|{|,")) + if (!Token::Match(tok2, "return|(|{|,|*")) continue; const Token* tok3 = tok2->next(); diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index 70ca30fbb34..ac751bd37d7 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -947,16 +947,26 @@ class TestLeakAutoVar : public TestFixture { "void f(int* p) {\n" " free(p);\n" " g(*p);\n" + "}\n" + "int h(int* p) {\n" + " free(p);\n" + " return g(*p);\n" "}\n"); - ASSERT_EQUALS("[test.c:4]: (error) Dereferencing 'p' after it is deallocated / released\n", + ASSERT_EQUALS("[test.c:4]: (error) Dereferencing 'p' after it is deallocated / released\n" + "[test.c:7] -> [test.c:8]: (error) Returning/dereferencing 'p' after it is deallocated / released\n", errout.str()); check("int g(int);\n" - "int f(int* p) {\n" + "void f(int* p) {\n" " free(p);\n" - " return g(*p);\n" + " g(1 + *p);\n" + "}\n" + "int h(int* p) {\n" + " free(p);\n" + " return g(1 + *p);\n" "}\n"); - ASSERT_EQUALS("[test.c:3] -> [test.c:4]: (error) Returning/dereferencing 'p' after it is deallocated / released\n", + ASSERT_EQUALS("[test.c:4]: (error) Dereferencing 'p' after it is deallocated / released\n" + "[test.c:7] -> [test.c:8]: (error) Returning/dereferencing 'p' after it is deallocated / released\n", errout.str()); } From e0c1813023487495c9307681434247ebd3b91d92 Mon Sep 17 00:00:00 2001 From: chrchr Date: Wed, 3 Jan 2024 16:22:16 +0100 Subject: [PATCH 4/4] Add test --- test/testleakautovar.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index ac751bd37d7..280c428345c 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -943,7 +943,7 @@ class TestLeakAutoVar : public TestFixture { ASSERT_EQUALS("[test.c:4]: (error) Dereferencing 'p' after it is deallocated / released\n", errout.str()); - check("void g(int);\n" + check("int g(int);\n" "void f(int* p) {\n" " free(p);\n" " g(*p);\n" @@ -968,6 +968,19 @@ class TestLeakAutoVar : public TestFixture { ASSERT_EQUALS("[test.c:4]: (error) Dereferencing 'p' after it is deallocated / released\n" "[test.c:7] -> [test.c:8]: (error) Returning/dereferencing 'p' after it is deallocated / released\n", errout.str()); + + check("int g(int, int);\n" + "void f(int* p) {\n" + " free(p);\n" + " g(0, 1 + *p);\n" + "}\n" + "int h(int* p) {\n" + " free(p);\n" + " return g(0, 1 + *p);\n" + "}\n"); + ASSERT_EQUALS("[test.c:4]: (error) Dereferencing 'p' after it is deallocated / released\n" + "[test.c:7] -> [test.c:8]: (error) Returning/dereferencing 'p' after it is deallocated / released\n", + errout.str()); } void doublefree1() { // #3895