@@ -401,10 +401,11 @@ class MallocChecker
401
401
};
402
402
403
403
const CallDescriptionMap<CheckFn> FreeingMemFnMap{
404
- {{{" free" }, 1 }, &MallocChecker::checkFree},
405
- {{{" if_freenameindex" }, 1 }, &MallocChecker::checkIfFreeNameIndex},
406
- {{{" kfree" }, 1 }, &MallocChecker::checkFree},
407
- {{{" g_free" }, 1 }, &MallocChecker::checkFree},
404
+ {{CDM::CLibrary, {" free" }, 1 }, &MallocChecker::checkFree},
405
+ {{CDM::CLibrary, {" if_freenameindex" }, 1 },
406
+ &MallocChecker::checkIfFreeNameIndex},
407
+ {{CDM::CLibrary, {" kfree" }, 1 }, &MallocChecker::checkFree},
408
+ {{CDM::CLibrary, {" g_free" }, 1 }, &MallocChecker::checkFree},
408
409
};
409
410
410
411
bool isFreeingCall (const CallEvent &Call) const ;
@@ -413,41 +414,46 @@ class MallocChecker
413
414
friend class NoOwnershipChangeVisitor ;
414
415
415
416
CallDescriptionMap<CheckFn> AllocatingMemFnMap{
416
- {{{" alloca" }, 1 }, &MallocChecker::checkAlloca},
417
- {{{" _alloca" }, 1 }, &MallocChecker::checkAlloca},
418
- {{{" malloc" }, 1 }, &MallocChecker::checkBasicAlloc},
419
- {{{" malloc" }, 3 }, &MallocChecker::checkKernelMalloc},
420
- {{{" calloc" }, 2 }, &MallocChecker::checkCalloc},
421
- {{{" valloc" }, 1 }, &MallocChecker::checkBasicAlloc},
417
+ {{CDM::CLibrary, {" alloca" }, 1 }, &MallocChecker::checkAlloca},
418
+ {{CDM::CLibrary, {" _alloca" }, 1 }, &MallocChecker::checkAlloca},
419
+ // The line for "alloca" also covers "__builtin_alloca", but the
420
+ // _with_align variant must be listed separately because it takes an
421
+ // extra argument:
422
+ {{CDM::CLibrary, {" __builtin_alloca_with_align" }, 2 },
423
+ &MallocChecker::checkAlloca},
424
+ {{CDM::CLibrary, {" malloc" }, 1 }, &MallocChecker::checkBasicAlloc},
425
+ {{CDM::CLibrary, {" malloc" }, 3 }, &MallocChecker::checkKernelMalloc},
426
+ {{CDM::CLibrary, {" calloc" }, 2 }, &MallocChecker::checkCalloc},
427
+ {{CDM::CLibrary, {" valloc" }, 1 }, &MallocChecker::checkBasicAlloc},
422
428
{{CDM::CLibrary, {" strndup" }, 2 }, &MallocChecker::checkStrdup},
423
429
{{CDM::CLibrary, {" strdup" }, 1 }, &MallocChecker::checkStrdup},
424
- {{{" _strdup" }, 1 }, &MallocChecker::checkStrdup},
425
- {{{" kmalloc" }, 2 }, &MallocChecker::checkKernelMalloc},
426
- {{{" if_nameindex" }, 1 }, &MallocChecker::checkIfNameIndex},
430
+ {{CDM::CLibrary, {" _strdup" }, 1 }, &MallocChecker::checkStrdup},
431
+ {{CDM::CLibrary, {" kmalloc" }, 2 }, &MallocChecker::checkKernelMalloc},
432
+ {{CDM::CLibrary, {" if_nameindex" }, 1 }, &MallocChecker::checkIfNameIndex},
427
433
{{CDM::CLibrary, {" wcsdup" }, 1 }, &MallocChecker::checkStrdup},
428
434
{{CDM::CLibrary, {" _wcsdup" }, 1 }, &MallocChecker::checkStrdup},
429
- {{{" g_malloc" }, 1 }, &MallocChecker::checkBasicAlloc},
430
- {{{" g_malloc0" }, 1 }, &MallocChecker::checkGMalloc0},
431
- {{{" g_try_malloc" }, 1 }, &MallocChecker::checkBasicAlloc},
432
- {{{" g_try_malloc0" }, 1 }, &MallocChecker::checkGMalloc0},
433
- {{{" g_memdup" }, 2 }, &MallocChecker::checkGMemdup},
434
- {{{" g_malloc_n" }, 2 }, &MallocChecker::checkGMallocN},
435
- {{{" g_malloc0_n" }, 2 }, &MallocChecker::checkGMallocN0},
436
- {{{" g_try_malloc_n" }, 2 }, &MallocChecker::checkGMallocN},
437
- {{{" g_try_malloc0_n" }, 2 }, &MallocChecker::checkGMallocN0},
435
+ {{CDM::CLibrary, {" g_malloc" }, 1 }, &MallocChecker::checkBasicAlloc},
436
+ {{CDM::CLibrary, {" g_malloc0" }, 1 }, &MallocChecker::checkGMalloc0},
437
+ {{CDM::CLibrary, {" g_try_malloc" }, 1 }, &MallocChecker::checkBasicAlloc},
438
+ {{CDM::CLibrary, {" g_try_malloc0" }, 1 }, &MallocChecker::checkGMalloc0},
439
+ {{CDM::CLibrary, {" g_memdup" }, 2 }, &MallocChecker::checkGMemdup},
440
+ {{CDM::CLibrary, {" g_malloc_n" }, 2 }, &MallocChecker::checkGMallocN},
441
+ {{CDM::CLibrary, {" g_malloc0_n" }, 2 }, &MallocChecker::checkGMallocN0},
442
+ {{CDM::CLibrary, {" g_try_malloc_n" }, 2 }, &MallocChecker::checkGMallocN},
443
+ {{CDM::CLibrary, {" g_try_malloc0_n" }, 2 }, &MallocChecker::checkGMallocN0},
438
444
};
439
445
440
446
CallDescriptionMap<CheckFn> ReallocatingMemFnMap{
441
- {{{" realloc" }, 2 },
447
+ {{CDM::CLibrary, {" realloc" }, 2 },
442
448
std::bind (&MallocChecker::checkRealloc, _1, _2, _3, false )},
443
- {{{" reallocf" }, 2 },
449
+ {{CDM::CLibrary, {" reallocf" }, 2 },
444
450
std::bind (&MallocChecker::checkRealloc, _1, _2, _3, true )},
445
- {{{" g_realloc" }, 2 },
451
+ {{CDM::CLibrary, {" g_realloc" }, 2 },
446
452
std::bind (&MallocChecker::checkRealloc, _1, _2, _3, false )},
447
- {{{" g_try_realloc" }, 2 },
453
+ {{CDM::CLibrary, {" g_try_realloc" }, 2 },
448
454
std::bind (&MallocChecker::checkRealloc, _1, _2, _3, false )},
449
- {{{" g_realloc_n" }, 3 }, &MallocChecker::checkReallocN},
450
- {{{" g_try_realloc_n" }, 3 }, &MallocChecker::checkReallocN},
455
+ {{CDM::CLibrary, {" g_realloc_n" }, 3 }, &MallocChecker::checkReallocN},
456
+ {{CDM::CLibrary, {" g_try_realloc_n" }, 3 }, &MallocChecker::checkReallocN},
451
457
452
458
// NOTE: the following CallDescription also matches the C++ standard
453
459
// library function std::getline(); the callback will filter it out.
@@ -1259,9 +1265,6 @@ static bool isStandardRealloc(const CallEvent &Call) {
1259
1265
assert (FD);
1260
1266
ASTContext &AC = FD->getASTContext ();
1261
1267
1262
- if (isa<CXXMethodDecl>(FD))
1263
- return false ;
1264
-
1265
1268
return FD->getDeclaredReturnType ().getDesugaredType (AC) == AC.VoidPtrTy &&
1266
1269
FD->getParamDecl (0 )->getType ().getDesugaredType (AC) == AC.VoidPtrTy &&
1267
1270
FD->getParamDecl (1 )->getType ().getDesugaredType (AC) ==
@@ -1273,9 +1276,6 @@ static bool isGRealloc(const CallEvent &Call) {
1273
1276
assert (FD);
1274
1277
ASTContext &AC = FD->getASTContext ();
1275
1278
1276
- if (isa<CXXMethodDecl>(FD))
1277
- return false ;
1278
-
1279
1279
return FD->getDeclaredReturnType ().getDesugaredType (AC) == AC.VoidPtrTy &&
1280
1280
FD->getParamDecl (0 )->getType ().getDesugaredType (AC) == AC.VoidPtrTy &&
1281
1281
FD->getParamDecl (1 )->getType ().getDesugaredType (AC) ==
@@ -1284,14 +1284,14 @@ static bool isGRealloc(const CallEvent &Call) {
1284
1284
1285
1285
void MallocChecker::checkRealloc (const CallEvent &Call, CheckerContext &C,
1286
1286
bool ShouldFreeOnFail) const {
1287
- // HACK: CallDescription currently recognizes non-standard realloc functions
1288
- // as standard because it doesn't check the type, or wether its a non-method
1289
- // function. This should be solved by making CallDescription smarter.
1290
- // Mind that this came from a bug report, and all other functions suffer from
1291
- // this.
1292
- // https://bugs.llvm.org/show_bug.cgi?id=46253
1287
+ // Ignore calls to functions whose type does not match the expected type of
1288
+ // either the standard realloc or g_realloc from GLib.
1289
+ // FIXME: Should we perform this kind of checking consistently for each
1290
+ // function? If yes, then perhaps extend the `CallDescription` interface to
1291
+ // handle this.
1293
1292
if (!isStandardRealloc (Call) && !isGRealloc (Call))
1294
1293
return ;
1294
+
1295
1295
ProgramStateRef State = C.getState ();
1296
1296
State = ReallocMemAux (C, Call, ShouldFreeOnFail, State, AF_Malloc);
1297
1297
State = ProcessZeroAllocCheck (Call, 1 , State);
@@ -1842,9 +1842,18 @@ static ProgramStateRef MallocUpdateRefState(CheckerContext &C, const Expr *E,
1842
1842
return nullptr ;
1843
1843
1844
1844
SymbolRef Sym = RetVal->getAsLocSymbol ();
1845
+
1845
1846
// This is a return value of a function that was not inlined, such as malloc()
1846
1847
// or new(). We've checked that in the caller. Therefore, it must be a symbol.
1847
1848
assert (Sym);
1849
+ // FIXME: In theory this assertion should fail for `alloca()` calls (because
1850
+ // `AllocaRegion`s are not symbolic); but in practice this does not happen.
1851
+ // As the current code appears to work correctly, I'm not touching this issue
1852
+ // now, but it would be good to investigate and clarify this.
1853
+ // Also note that perhaps the special `AllocaRegion` should be replaced by
1854
+ // `SymbolicRegion` (or turned into a subclass of `SymbolicRegion`) to enable
1855
+ // proper tracking of memory allocated by `alloca()` -- and after that change
1856
+ // this assertion would become valid again.
1848
1857
1849
1858
// Set the symbol's state to Allocated.
1850
1859
return State->set <RegionState>(Sym, RefState::getAllocated (Family, E));
0 commit comments