@@ -401,10 +401,11 @@ class MallocChecker
401401 };
402402
403403 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},
408409 };
409410
410411 bool isFreeingCall (const CallEvent &Call) const ;
@@ -413,41 +414,46 @@ class MallocChecker
413414 friend class NoOwnershipChangeVisitor ;
414415
415416 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},
422428 {{CDM::CLibrary, {" strndup" }, 2 }, &MallocChecker::checkStrdup},
423429 {{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},
427433 {{CDM::CLibrary, {" wcsdup" }, 1 }, &MallocChecker::checkStrdup},
428434 {{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},
438444 };
439445
440446 CallDescriptionMap<CheckFn> ReallocatingMemFnMap{
441- {{{" realloc" }, 2 },
447+ {{CDM::CLibrary, {" realloc" }, 2 },
442448 std::bind (&MallocChecker::checkRealloc, _1, _2, _3, false )},
443- {{{" reallocf" }, 2 },
449+ {{CDM::CLibrary, {" reallocf" }, 2 },
444450 std::bind (&MallocChecker::checkRealloc, _1, _2, _3, true )},
445- {{{" g_realloc" }, 2 },
451+ {{CDM::CLibrary, {" g_realloc" }, 2 },
446452 std::bind (&MallocChecker::checkRealloc, _1, _2, _3, false )},
447- {{{" g_try_realloc" }, 2 },
453+ {{CDM::CLibrary, {" g_try_realloc" }, 2 },
448454 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},
451457
452458 // NOTE: the following CallDescription also matches the C++ standard
453459 // library function std::getline(); the callback will filter it out.
@@ -1259,9 +1265,6 @@ static bool isStandardRealloc(const CallEvent &Call) {
12591265 assert (FD);
12601266 ASTContext &AC = FD->getASTContext ();
12611267
1262- if (isa<CXXMethodDecl>(FD))
1263- return false ;
1264-
12651268 return FD->getDeclaredReturnType ().getDesugaredType (AC) == AC.VoidPtrTy &&
12661269 FD->getParamDecl (0 )->getType ().getDesugaredType (AC) == AC.VoidPtrTy &&
12671270 FD->getParamDecl (1 )->getType ().getDesugaredType (AC) ==
@@ -1273,9 +1276,6 @@ static bool isGRealloc(const CallEvent &Call) {
12731276 assert (FD);
12741277 ASTContext &AC = FD->getASTContext ();
12751278
1276- if (isa<CXXMethodDecl>(FD))
1277- return false ;
1278-
12791279 return FD->getDeclaredReturnType ().getDesugaredType (AC) == AC.VoidPtrTy &&
12801280 FD->getParamDecl (0 )->getType ().getDesugaredType (AC) == AC.VoidPtrTy &&
12811281 FD->getParamDecl (1 )->getType ().getDesugaredType (AC) ==
@@ -1284,14 +1284,14 @@ static bool isGRealloc(const CallEvent &Call) {
12841284
12851285void MallocChecker::checkRealloc (const CallEvent &Call, CheckerContext &C,
12861286 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.
12931292 if (!isStandardRealloc (Call) && !isGRealloc (Call))
12941293 return ;
1294+
12951295 ProgramStateRef State = C.getState ();
12961296 State = ReallocMemAux (C, Call, ShouldFreeOnFail, State, AF_Malloc);
12971297 State = ProcessZeroAllocCheck (Call, 1 , State);
@@ -1842,9 +1842,18 @@ static ProgramStateRef MallocUpdateRefState(CheckerContext &C, const Expr *E,
18421842 return nullptr ;
18431843
18441844 SymbolRef Sym = RetVal->getAsLocSymbol ();
1845+
18451846 // This is a return value of a function that was not inlined, such as malloc()
18461847 // or new(). We've checked that in the caller. Therefore, it must be a symbol.
18471848 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.
18481857
18491858 // Set the symbol's state to Allocated.
18501859 return State->set <RegionState>(Sym, RefState::getAllocated (Family, E));
0 commit comments