From 5aebb2cdaf62c02db6dd1f0e8e19c9ec3806d221 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Fri, 19 Jul 2024 10:22:38 +0200 Subject: [PATCH] Fix #12506 FP memleak when not calling freeaddrinfo() in error path (#6604) --- lib/checkleakautovar.cpp | 48 +++++++++++++++++++++++++++------------- test/cfg/posix.c | 11 +++++++++ 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 80a3a862893..432b786edee 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -263,6 +263,30 @@ static const Token * isFunctionCall(const Token * nameToken) return nullptr; } +static const Token* getOutparamAllocation(const Token* tok, const Settings& settings) +{ + if (!tok) + return nullptr; + int argn{}; + const Token* ftok = getTokenArgumentFunction(tok, argn); + if (!ftok) + return nullptr; + if (const Library::AllocFunc* allocFunc = settings.library.getAllocFuncInfo(ftok)) { + if (allocFunc->arg == argn + 1) + return ftok; + } + return nullptr; +} + +static const Token* getReturnValueFromOutparamAlloc(const Token* alloc, const Settings& settings) +{ + if (const Token* ftok = getOutparamAllocation(alloc, settings)) { + if (Token::simpleMatch(ftok->astParent()->astParent(), "=")) + return ftok->next()->astParent()->astOperand1(); + } + return nullptr; +} + bool CheckLeakAutoVar::checkScope(const Token * const startToken, VarInfo &varInfo, std::set notzero, @@ -526,6 +550,15 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken, if (astIsVariableComparison(tok3, "!=", "0", &vartok) && (notzero.find(vartok->varId()) != notzero.end())) varInfo2.clear(); + + if (std::any_of(varInfo1.alloctype.begin(), varInfo1.alloctype.end(), [&](const std::pair& info) { + if (info.second.status != VarInfo::ALLOC) + return false; + const Token* ret = getReturnValueFromOutparamAlloc(info.second.allocTok, *mSettings); + return ret && ret->varId() && ret->varId() == vartok->varId(); + })) { + varInfo1.clear(); + } } else if (isVarTokComparison(tok3, &vartok, alloc_failed_conds)) { varInfo1.reallocToAlloc(vartok->varId()); varInfo1.erase(vartok->varId()); @@ -1056,21 +1089,6 @@ void CheckLeakAutoVar::leakIfAllocated(const Token *vartok, } } -static const Token* getOutparamAllocation(const Token* tok, const Settings& settings) -{ - if (!tok) - return nullptr; - int argn{}; - const Token* ftok = getTokenArgumentFunction(tok, argn); - if (!ftok) - return nullptr; - if (const Library::AllocFunc* allocFunc = settings.library.getAllocFuncInfo(ftok)) { - if (allocFunc->arg == argn + 1) - return ftok; - } - return nullptr; -} - void CheckLeakAutoVar::ret(const Token *tok, VarInfo &varInfo, const bool isEndOfScope) { const std::map &alloctype = varInfo.alloctype; diff --git a/test/cfg/posix.c b/test/cfg/posix.c index b4b8c9e4985..f135ea7d6de 100644 --- a/test/cfg/posix.c +++ b/test/cfg/posix.c @@ -1046,6 +1046,17 @@ void memleak_getaddrinfo() // #6994 // cppcheck-suppress memleak } +void memleak_getaddrinfo_if() // #12506 +{ + struct addrinfo hints = {}; + struct addrinfo* addrs; + int err = getaddrinfo("example.com", "https", &hints, &addrs); + if (err != 0) {} + else { + freeaddrinfo(addrs); + } +} + void memleak_mmap(int fd) { // cppcheck-suppress [unusedAllocatedMemory, unreadVariable, constVariablePointer]