Skip to content

Commit 918eca6

Browse files
Fix #2767 FP resourceLeak (regression) / #12248 FP memleak / #12204 FP memleak (#5723)
1 parent e766fba commit 918eca6

4 files changed

Lines changed: 72 additions & 12 deletions

File tree

cfg/posix.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6268,6 +6268,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s
62686268
<alloc init="true">openat</alloc>
62696269
<alloc init="true">socket</alloc>
62706270
<dealloc>close</dealloc>
6271+
<dealloc>fdopen</dealloc>
62716272
</resource>
62726273
<resource>
62736274
<alloc init="true">opendir</alloc>

lib/checkleakautovar.cpp

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -967,7 +967,7 @@ void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpenin
967967
while (Token::Match(arg, "%name% .|:: %name%"))
968968
arg = arg->tokAt(2);
969969

970-
if (Token::Match(arg, "%var% [-,)] !!.") || Token::Match(arg, "& %var%")) {
970+
if (Token::Match(arg, "%var% [-,)] !!.") || Token::Match(arg, "& %var% !!.")) {
971971
// goto variable
972972
if (arg->str() == "&")
973973
arg = arg->next();
@@ -979,6 +979,9 @@ void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpenin
979979
const Library::AllocFunc* deallocFunc = mSettings->library.getDeallocFuncInfo(tokName);
980980
VarInfo::AllocInfo dealloc(deallocFunc ? deallocFunc->groupId : 0, VarInfo::DEALLOC, tokName);
981981
if (const Library::AllocFunc* allocFunc = mSettings->library.getAllocFuncInfo(tokName)) {
982+
if (mSettings->library.getDeallocFuncInfo(tokName)) {
983+
changeAllocStatus(varInfo, dealloc.type == 0 ? allocation : dealloc, tokName, arg);
984+
}
982985
if (allocFunc->arg == argNr && !(arg->variable() && arg->variable()->isArgument() && arg->valueType() && arg->valueType()->pointer > 1)) {
983986
leakIfAllocated(arg, varInfo);
984987
VarInfo::AllocInfo& varAlloc = varInfo.alloctype[arg->varId()];
@@ -1063,6 +1066,21 @@ void CheckLeakAutoVar::leakIfAllocated(const Token *vartok,
10631066
}
10641067
}
10651068

1069+
static const Token* getOutparamAllocation(const Token* tok, const Settings* settings)
1070+
{
1071+
if (!tok)
1072+
return nullptr;
1073+
int argn{};
1074+
const Token* ftok = getTokenArgumentFunction(tok, argn);
1075+
if (!ftok)
1076+
return nullptr;
1077+
if (const Library::AllocFunc* allocFunc = settings->library.getAllocFuncInfo(ftok)) {
1078+
if (allocFunc->arg == argn + 1)
1079+
return ftok;
1080+
}
1081+
return nullptr;
1082+
}
1083+
10661084
void CheckLeakAutoVar::ret(const Token *tok, VarInfo &varInfo, const bool isEndOfScope)
10671085
{
10681086
const std::map<int, VarInfo::AllocInfo> &alloctype = varInfo.alloctype;
@@ -1117,19 +1135,32 @@ void CheckLeakAutoVar::ret(const Token *tok, VarInfo &varInfo, const bool isEndO
11171135
}
11181136

11191137
// don't warn when returning after checking return value of outparam allocation
1120-
if (it->second.allocTok && (tok->scope()->type == Scope::ScopeType::eIf || tok->scope()->type== Scope::ScopeType::eElse)) {
1138+
const Token* outparamFunc{};
1139+
if ((tok->scope()->type == Scope::ScopeType::eIf || tok->scope()->type== Scope::ScopeType::eElse) &&
1140+
(outparamFunc = getOutparamAllocation(it->second.allocTok, mSettings))) {
11211141
const Scope* scope = tok->scope();
11221142
if (scope->type == Scope::ScopeType::eElse) {
11231143
scope = scope->bodyStart->tokAt(-2)->scope();
11241144
}
11251145
const Token* const ifEnd = scope->bodyStart->previous();
11261146
const Token* const ifStart = ifEnd->link();
11271147
const Token* const alloc = it->second.allocTok;
1128-
if (precedes(ifStart, alloc) && succeeds(ifEnd, alloc)) {
1129-
int argn{};
1130-
if (const Token* ftok = getTokenArgumentFunction(alloc, argn))
1131-
if (Token::Match(ftok->next()->astParent(), "%comp%"))
1148+
if (precedes(ifStart, alloc) && succeeds(ifEnd, alloc)) { // allocation and check in if
1149+
if (Token::Match(outparamFunc->next()->astParent(), "%comp%"))
1150+
continue;
1151+
} else { // allocation result assigned to variable
1152+
const Token* const retAssign = outparamFunc->next()->astParent();
1153+
if (Token::simpleMatch(retAssign, "=") && retAssign->astOperand1()->varId()) {
1154+
bool isRetComp = false;
1155+
for (const Token* tok2 = ifStart; tok2 != ifEnd; tok2 = tok2->next()) {
1156+
if (tok2->varId() == retAssign->astOperand1()->varId()) {
1157+
isRetComp = true;
1158+
break;
1159+
}
1160+
}
1161+
if (isRetComp)
11321162
continue;
1163+
}
11331164
}
11341165
}
11351166

test/cfg/gnu.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,17 @@ void memleak_asprintf7(const char* fmt, const int arg) {
398398
return;
399399
}
400400

401+
void memleak_asprintf8(const char *fmt, const int arg) // #12204
402+
{
403+
char* ptr;
404+
int ret = asprintf(&ptr, fmt, arg);
405+
if (-1 == ret) {
406+
return;
407+
}
408+
printf("%s", ptr);
409+
free(ptr);
410+
}
411+
401412
void memleak_xmalloc()
402413
{
403414
char *p = (char*)xmalloc(10);

test/cfg/posix.c

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,22 @@ void validCode(va_list valist_arg1, va_list valist_arg2)
891891
}
892892
}
893893

894+
typedef struct {
895+
size_t N;
896+
int* data;
897+
} S_memalign;
898+
899+
S_memalign* posix_memalign_memleak(size_t n) { // #12248
900+
S_memalign* s = malloc(sizeof(*s));
901+
s->N = n;
902+
if (0 != posix_memalign((void**)&s->data, 16, n * sizeof(int))) {
903+
free(s);
904+
return NULL;
905+
}
906+
memset(s->data, 0, n * sizeof(int));
907+
return s;
908+
}
909+
894910
ssize_t nullPointer_send(int socket, const void *buf, size_t len, int flags)
895911
{
896912
// cppcheck-suppress nullPointer
@@ -1060,6 +1076,13 @@ void resourceLeak_fdopen(int fd)
10601076
// cppcheck-suppress resourceLeak
10611077
}
10621078

1079+
void resourceLeak_fdopen2(const char* fn) // #2767
1080+
{
1081+
int fi = open(fn, O_RDONLY);
1082+
FILE* fd = fdopen(fi, "r");
1083+
fclose(fd);
1084+
}
1085+
10631086
void resourceLeak_mkstemp(char *template)
10641087
{
10651088
// cppcheck-suppress unreadVariable
@@ -1125,12 +1148,6 @@ void noleak(int x, int y, int z)
11251148
close(fd1);
11261149
int fd2 = open("a", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
11271150
close(fd2);
1128-
/* TODO: add configuration for open/fdopen
1129-
// #2830
1130-
int fd = open("path", O_RDONLY);
1131-
FILE *f = fdopen(fd, "rt");
1132-
fclose(f);
1133-
*/
11341151
}
11351152

11361153

0 commit comments

Comments
 (0)