Fix #2767 FP resourceLeak (regression) / #12248 FP memleak / #12204 FP memleak (#5723)

This commit is contained in:
chrchr-github 2023-12-06 10:17:32 +01:00 committed by GitHub
parent e766fba813
commit 918eca635d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 72 additions and 12 deletions

View File

@ -6268,6 +6268,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s
<alloc init="true">openat</alloc>
<alloc init="true">socket</alloc>
<dealloc>close</dealloc>
<dealloc>fdopen</dealloc>
</resource>
<resource>
<alloc init="true">opendir</alloc>

View File

@ -967,7 +967,7 @@ void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpenin
while (Token::Match(arg, "%name% .|:: %name%"))
arg = arg->tokAt(2);
if (Token::Match(arg, "%var% [-,)] !!.") || Token::Match(arg, "& %var%")) {
if (Token::Match(arg, "%var% [-,)] !!.") || Token::Match(arg, "& %var% !!.")) {
// goto variable
if (arg->str() == "&")
arg = arg->next();
@ -979,6 +979,9 @@ void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpenin
const Library::AllocFunc* deallocFunc = mSettings->library.getDeallocFuncInfo(tokName);
VarInfo::AllocInfo dealloc(deallocFunc ? deallocFunc->groupId : 0, VarInfo::DEALLOC, tokName);
if (const Library::AllocFunc* allocFunc = mSettings->library.getAllocFuncInfo(tokName)) {
if (mSettings->library.getDeallocFuncInfo(tokName)) {
changeAllocStatus(varInfo, dealloc.type == 0 ? allocation : dealloc, tokName, arg);
}
if (allocFunc->arg == argNr && !(arg->variable() && arg->variable()->isArgument() && arg->valueType() && arg->valueType()->pointer > 1)) {
leakIfAllocated(arg, varInfo);
VarInfo::AllocInfo& varAlloc = varInfo.alloctype[arg->varId()];
@ -1063,6 +1066,21 @@ 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<int, VarInfo::AllocInfo> &alloctype = varInfo.alloctype;
@ -1117,7 +1135,9 @@ void CheckLeakAutoVar::ret(const Token *tok, VarInfo &varInfo, const bool isEndO
}
// don't warn when returning after checking return value of outparam allocation
if (it->second.allocTok && (tok->scope()->type == Scope::ScopeType::eIf || tok->scope()->type== Scope::ScopeType::eElse)) {
const Token* outparamFunc{};
if ((tok->scope()->type == Scope::ScopeType::eIf || tok->scope()->type== Scope::ScopeType::eElse) &&
(outparamFunc = getOutparamAllocation(it->second.allocTok, mSettings))) {
const Scope* scope = tok->scope();
if (scope->type == Scope::ScopeType::eElse) {
scope = scope->bodyStart->tokAt(-2)->scope();
@ -1125,11 +1145,22 @@ void CheckLeakAutoVar::ret(const Token *tok, VarInfo &varInfo, const bool isEndO
const Token* const ifEnd = scope->bodyStart->previous();
const Token* const ifStart = ifEnd->link();
const Token* const alloc = it->second.allocTok;
if (precedes(ifStart, alloc) && succeeds(ifEnd, alloc)) {
int argn{};
if (const Token* ftok = getTokenArgumentFunction(alloc, argn))
if (Token::Match(ftok->next()->astParent(), "%comp%"))
if (precedes(ifStart, alloc) && succeeds(ifEnd, alloc)) { // allocation and check in if
if (Token::Match(outparamFunc->next()->astParent(), "%comp%"))
continue;
} else { // allocation result assigned to variable
const Token* const retAssign = outparamFunc->next()->astParent();
if (Token::simpleMatch(retAssign, "=") && retAssign->astOperand1()->varId()) {
bool isRetComp = false;
for (const Token* tok2 = ifStart; tok2 != ifEnd; tok2 = tok2->next()) {
if (tok2->varId() == retAssign->astOperand1()->varId()) {
isRetComp = true;
break;
}
}
if (isRetComp)
continue;
}
}
}

View File

@ -398,6 +398,17 @@ void memleak_asprintf7(const char* fmt, const int arg) {
return;
}
void memleak_asprintf8(const char *fmt, const int arg) // #12204
{
char* ptr;
int ret = asprintf(&ptr, fmt, arg);
if (-1 == ret) {
return;
}
printf("%s", ptr);
free(ptr);
}
void memleak_xmalloc()
{
char *p = (char*)xmalloc(10);

View File

@ -891,6 +891,22 @@ void validCode(va_list valist_arg1, va_list valist_arg2)
}
}
typedef struct {
size_t N;
int* data;
} S_memalign;
S_memalign* posix_memalign_memleak(size_t n) { // #12248
S_memalign* s = malloc(sizeof(*s));
s->N = n;
if (0 != posix_memalign((void**)&s->data, 16, n * sizeof(int))) {
free(s);
return NULL;
}
memset(s->data, 0, n * sizeof(int));
return s;
}
ssize_t nullPointer_send(int socket, const void *buf, size_t len, int flags)
{
// cppcheck-suppress nullPointer
@ -1060,6 +1076,13 @@ void resourceLeak_fdopen(int fd)
// cppcheck-suppress resourceLeak
}
void resourceLeak_fdopen2(const char* fn) // #2767
{
int fi = open(fn, O_RDONLY);
FILE* fd = fdopen(fi, "r");
fclose(fd);
}
void resourceLeak_mkstemp(char *template)
{
// cppcheck-suppress unreadVariable
@ -1125,12 +1148,6 @@ void noleak(int x, int y, int z)
close(fd1);
int fd2 = open("a", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
close(fd2);
/* TODO: add configuration for open/fdopen
// #2830
int fd = open("path", O_RDONLY);
FILE *f = fdopen(fd, "rt");
fclose(f);
*/
}