1 //=== MallocChecker.cpp - A malloc/free checker -------------------*- C++ -*--//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines a variety of memory management related checkers, such as
10 // leak, double free, and use-after-free.
11 //
12 // The following checkers are defined here:
13 //
14 // * MallocChecker
15 // Despite its name, it models all sorts of memory allocations and
16 // de- or reallocation, including but not limited to malloc, free,
17 // relloc, new, delete. It also reports on a variety of memory misuse
18 // errors.
19 // Many other checkers interact very closely with this checker, in fact,
20 // most are merely options to this one. Other checkers may register
21 // MallocChecker, but do not enable MallocChecker's reports (more details
22 // to follow around its field, ChecksEnabled).
23 // It also has a boolean "Optimistic" checker option, which if set to true
24 // will cause the checker to model user defined memory management related
25 // functions annotated via the attribute ownership_takes, ownership_holds
26 // and ownership_returns.
27 //
28 // * NewDeleteChecker
29 // Enables the modeling of new, new[], delete, delete[] in MallocChecker,
30 // and checks for related double-free and use-after-free errors.
31 //
32 // * NewDeleteLeaksChecker
33 // Checks for leaks related to new, new[], delete, delete[].
34 // Depends on NewDeleteChecker.
35 //
36 // * MismatchedDeallocatorChecker
37 // Enables checking whether memory is deallocated with the correspending
38 // allocation function in MallocChecker, such as malloc() allocated
39 // regions are only freed by free(), new by delete, new[] by delete[].
40 //
41 // InnerPointerChecker interacts very closely with MallocChecker, but unlike
42 // the above checkers, it has it's own file, hence the many InnerPointerChecker
43 // related headers and non-static functions.
44 //
45 //===----------------------------------------------------------------------===//
46
47 #include "AllocationState.h"
48 #include "InterCheckerAPI.h"
49 #include "clang/AST/Attr.h"
50 #include "clang/AST/DeclCXX.h"
51 #include "clang/AST/DeclTemplate.h"
52 #include "clang/AST/Expr.h"
53 #include "clang/AST/ExprCXX.h"
54 #include "clang/AST/ParentMap.h"
55 #include "clang/ASTMatchers/ASTMatchFinder.h"
56 #include "clang/ASTMatchers/ASTMatchers.h"
57 #include "clang/Analysis/ProgramPoint.h"
58 #include "clang/Basic/LLVM.h"
59 #include "clang/Basic/SourceManager.h"
60 #include "clang/Basic/TargetInfo.h"
61 #include "clang/Lex/Lexer.h"
62 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
63 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
64 #include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h"
65 #include "clang/StaticAnalyzer/Core/Checker.h"
66 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
67 #include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
68 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
69 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
70 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
71 #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
72 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
73 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
74 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
75 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
76 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
77 #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
78 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
79 #include "llvm/ADT/STLExtras.h"
80 #include "llvm/ADT/SetOperations.h"
81 #include "llvm/ADT/SmallString.h"
82 #include "llvm/ADT/StringExtras.h"
83 #include "llvm/Support/Casting.h"
84 #include "llvm/Support/Compiler.h"
85 #include "llvm/Support/ErrorHandling.h"
86 #include "llvm/Support/raw_ostream.h"
87 #include <climits>
88 #include <functional>
89 #include <optional>
90 #include <utility>
91
92 using namespace clang;
93 using namespace ento;
94 using namespace std::placeholders;
95
96 //===----------------------------------------------------------------------===//
97 // The types of allocation we're modeling. This is used to check whether a
98 // dynamically allocated object is deallocated with the correct function, like
99 // not using operator delete on an object created by malloc(), or alloca regions
100 // aren't ever deallocated manually.
101 //===----------------------------------------------------------------------===//
102
103 namespace {
104
105 // Used to check correspondence between allocators and deallocators.
106 enum AllocationFamily {
107 AF_None,
108 AF_Malloc,
109 AF_CXXNew,
110 AF_CXXNewArray,
111 AF_IfNameIndex,
112 AF_Alloca,
113 AF_InnerBuffer
114 };
115
116 } // end of anonymous namespace
117
118 /// Print names of allocators and deallocators.
119 ///
120 /// \returns true on success.
121 static bool printMemFnName(raw_ostream &os, CheckerContext &C, const Expr *E);
122
123 /// Print expected name of an allocator based on the deallocator's family
124 /// derived from the DeallocExpr.
125 static void printExpectedAllocName(raw_ostream &os, AllocationFamily Family);
126
127 /// Print expected name of a deallocator based on the allocator's
128 /// family.
129 static void printExpectedDeallocName(raw_ostream &os, AllocationFamily Family);
130
131 //===----------------------------------------------------------------------===//
132 // The state of a symbol, in terms of memory management.
133 //===----------------------------------------------------------------------===//
134
135 namespace {
136
137 class RefState {
138 enum Kind {
139 // Reference to allocated memory.
140 Allocated,
141 // Reference to zero-allocated memory.
142 AllocatedOfSizeZero,
143 // Reference to released/freed memory.
144 Released,
145 // The responsibility for freeing resources has transferred from
146 // this reference. A relinquished symbol should not be freed.
147 Relinquished,
148 // We are no longer guaranteed to have observed all manipulations
149 // of this pointer/memory. For example, it could have been
150 // passed as a parameter to an opaque function.
151 Escaped
152 };
153
154 const Stmt *S;
155
156 Kind K;
157 AllocationFamily Family;
158
RefState(Kind k,const Stmt * s,AllocationFamily family)159 RefState(Kind k, const Stmt *s, AllocationFamily family)
160 : S(s), K(k), Family(family) {
161 assert(family != AF_None);
162 }
163
164 public:
isAllocated() const165 bool isAllocated() const { return K == Allocated; }
isAllocatedOfSizeZero() const166 bool isAllocatedOfSizeZero() const { return K == AllocatedOfSizeZero; }
isReleased() const167 bool isReleased() const { return K == Released; }
isRelinquished() const168 bool isRelinquished() const { return K == Relinquished; }
isEscaped() const169 bool isEscaped() const { return K == Escaped; }
getAllocationFamily() const170 AllocationFamily getAllocationFamily() const { return Family; }
getStmt() const171 const Stmt *getStmt() const { return S; }
172
operator ==(const RefState & X) const173 bool operator==(const RefState &X) const {
174 return K == X.K && S == X.S && Family == X.Family;
175 }
176
getAllocated(AllocationFamily family,const Stmt * s)177 static RefState getAllocated(AllocationFamily family, const Stmt *s) {
178 return RefState(Allocated, s, family);
179 }
getAllocatedOfSizeZero(const RefState * RS)180 static RefState getAllocatedOfSizeZero(const RefState *RS) {
181 return RefState(AllocatedOfSizeZero, RS->getStmt(),
182 RS->getAllocationFamily());
183 }
getReleased(AllocationFamily family,const Stmt * s)184 static RefState getReleased(AllocationFamily family, const Stmt *s) {
185 return RefState(Released, s, family);
186 }
getRelinquished(AllocationFamily family,const Stmt * s)187 static RefState getRelinquished(AllocationFamily family, const Stmt *s) {
188 return RefState(Relinquished, s, family);
189 }
getEscaped(const RefState * RS)190 static RefState getEscaped(const RefState *RS) {
191 return RefState(Escaped, RS->getStmt(), RS->getAllocationFamily());
192 }
193
Profile(llvm::FoldingSetNodeID & ID) const194 void Profile(llvm::FoldingSetNodeID &ID) const {
195 ID.AddInteger(K);
196 ID.AddPointer(S);
197 ID.AddInteger(Family);
198 }
199
dump(raw_ostream & OS) const200 LLVM_DUMP_METHOD void dump(raw_ostream &OS) const {
201 switch (K) {
202 #define CASE(ID) case ID: OS << #ID; break;
203 CASE(Allocated)
204 CASE(AllocatedOfSizeZero)
205 CASE(Released)
206 CASE(Relinquished)
207 CASE(Escaped)
208 }
209 }
210
dump() const211 LLVM_DUMP_METHOD void dump() const { dump(llvm::errs()); }
212 };
213
214 } // end of anonymous namespace
215
216 REGISTER_MAP_WITH_PROGRAMSTATE(RegionState, SymbolRef, RefState)
217
218 /// Check if the memory associated with this symbol was released.
219 static bool isReleased(SymbolRef Sym, CheckerContext &C);
220
221 /// Update the RefState to reflect the new memory allocation.
222 /// The optional \p RetVal parameter specifies the newly allocated pointer
223 /// value; if unspecified, the value of expression \p E is used.
224 static ProgramStateRef
225 MallocUpdateRefState(CheckerContext &C, const Expr *E, ProgramStateRef State,
226 AllocationFamily Family,
227 std::optional<SVal> RetVal = std::nullopt);
228
229 //===----------------------------------------------------------------------===//
230 // The modeling of memory reallocation.
231 //
232 // The terminology 'toPtr' and 'fromPtr' will be used:
233 // toPtr = realloc(fromPtr, 20);
234 //===----------------------------------------------------------------------===//
235
236 REGISTER_SET_WITH_PROGRAMSTATE(ReallocSizeZeroSymbols, SymbolRef)
237
238 namespace {
239
240 /// The state of 'fromPtr' after reallocation is known to have failed.
241 enum OwnershipAfterReallocKind {
242 // The symbol needs to be freed (e.g.: realloc)
243 OAR_ToBeFreedAfterFailure,
244 // The symbol has been freed (e.g.: reallocf)
245 OAR_FreeOnFailure,
246 // The symbol doesn't have to freed (e.g.: we aren't sure if, how and where
247 // 'fromPtr' was allocated:
248 // void Haha(int *ptr) {
249 // ptr = realloc(ptr, 67);
250 // // ...
251 // }
252 // ).
253 OAR_DoNotTrackAfterFailure
254 };
255
256 /// Stores information about the 'fromPtr' symbol after reallocation.
257 ///
258 /// This is important because realloc may fail, and that needs special modeling.
259 /// Whether reallocation failed or not will not be known until later, so we'll
260 /// store whether upon failure 'fromPtr' will be freed, or needs to be freed
261 /// later, etc.
262 struct ReallocPair {
263
264 // The 'fromPtr'.
265 SymbolRef ReallocatedSym;
266 OwnershipAfterReallocKind Kind;
267
ReallocPair__anon1e4601280311::ReallocPair268 ReallocPair(SymbolRef S, OwnershipAfterReallocKind K)
269 : ReallocatedSym(S), Kind(K) {}
Profile__anon1e4601280311::ReallocPair270 void Profile(llvm::FoldingSetNodeID &ID) const {
271 ID.AddInteger(Kind);
272 ID.AddPointer(ReallocatedSym);
273 }
operator ==__anon1e4601280311::ReallocPair274 bool operator==(const ReallocPair &X) const {
275 return ReallocatedSym == X.ReallocatedSym &&
276 Kind == X.Kind;
277 }
278 };
279
280 } // end of anonymous namespace
281
282 REGISTER_MAP_WITH_PROGRAMSTATE(ReallocPairs, SymbolRef, ReallocPair)
283
284 /// Tells if the callee is one of the builtin new/delete operators, including
285 /// placement operators and other standard overloads.
286 static bool isStandardNewDelete(const FunctionDecl *FD);
isStandardNewDelete(const CallEvent & Call)287 static bool isStandardNewDelete(const CallEvent &Call) {
288 if (!Call.getDecl() || !isa<FunctionDecl>(Call.getDecl()))
289 return false;
290 return isStandardNewDelete(cast<FunctionDecl>(Call.getDecl()));
291 }
292
293 //===----------------------------------------------------------------------===//
294 // Definition of the MallocChecker class.
295 //===----------------------------------------------------------------------===//
296
297 namespace {
298
299 class MallocChecker
300 : public Checker<check::DeadSymbols, check::PointerEscape,
301 check::ConstPointerEscape, check::PreStmt<ReturnStmt>,
302 check::EndFunction, check::PreCall, check::PostCall,
303 check::NewAllocator, check::PostStmt<BlockExpr>,
304 check::PostObjCMessage, check::Location, eval::Assume> {
305 public:
306 /// In pessimistic mode, the checker assumes that it does not know which
307 /// functions might free the memory.
308 /// In optimistic mode, the checker assumes that all user-defined functions
309 /// which might free a pointer are annotated.
310 bool ShouldIncludeOwnershipAnnotatedFunctions = false;
311
312 bool ShouldRegisterNoOwnershipChangeVisitor = false;
313
314 /// Many checkers are essentially built into this one, so enabling them will
315 /// make MallocChecker perform additional modeling and reporting.
316 enum CheckKind {
317 /// When a subchecker is enabled but MallocChecker isn't, model memory
318 /// management but do not emit warnings emitted with MallocChecker only
319 /// enabled.
320 CK_MallocChecker,
321 CK_NewDeleteChecker,
322 CK_NewDeleteLeaksChecker,
323 CK_MismatchedDeallocatorChecker,
324 CK_InnerPointerChecker,
325 CK_NumCheckKinds
326 };
327
328 using LeakInfo = std::pair<const ExplodedNode *, const MemRegion *>;
329
330 bool ChecksEnabled[CK_NumCheckKinds] = {false};
331 CheckerNameRef CheckNames[CK_NumCheckKinds];
332
333 void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
334 void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
335 void checkNewAllocator(const CXXAllocatorCall &Call, CheckerContext &C) const;
336 void checkPostObjCMessage(const ObjCMethodCall &Call, CheckerContext &C) const;
337 void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
338 void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
339 void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
340 void checkEndFunction(const ReturnStmt *S, CheckerContext &C) const;
341 ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
342 bool Assumption) const;
343 void checkLocation(SVal l, bool isLoad, const Stmt *S,
344 CheckerContext &C) const;
345
346 ProgramStateRef checkPointerEscape(ProgramStateRef State,
347 const InvalidatedSymbols &Escaped,
348 const CallEvent *Call,
349 PointerEscapeKind Kind) const;
350 ProgramStateRef checkConstPointerEscape(ProgramStateRef State,
351 const InvalidatedSymbols &Escaped,
352 const CallEvent *Call,
353 PointerEscapeKind Kind) const;
354
355 void printState(raw_ostream &Out, ProgramStateRef State,
356 const char *NL, const char *Sep) const override;
357
358 private:
359 mutable std::unique_ptr<BugType> BT_DoubleFree[CK_NumCheckKinds];
360 mutable std::unique_ptr<BugType> BT_DoubleDelete;
361 mutable std::unique_ptr<BugType> BT_Leak[CK_NumCheckKinds];
362 mutable std::unique_ptr<BugType> BT_UseFree[CK_NumCheckKinds];
363 mutable std::unique_ptr<BugType> BT_BadFree[CK_NumCheckKinds];
364 mutable std::unique_ptr<BugType> BT_FreeAlloca[CK_NumCheckKinds];
365 mutable std::unique_ptr<BugType> BT_MismatchedDealloc;
366 mutable std::unique_ptr<BugType> BT_OffsetFree[CK_NumCheckKinds];
367 mutable std::unique_ptr<BugType> BT_UseZerroAllocated[CK_NumCheckKinds];
368
369 #define CHECK_FN(NAME) \
370 void NAME(const CallEvent &Call, CheckerContext &C) const;
371
372 CHECK_FN(checkFree)
373 CHECK_FN(checkIfNameIndex)
374 CHECK_FN(checkBasicAlloc)
375 CHECK_FN(checkKernelMalloc)
376 CHECK_FN(checkCalloc)
377 CHECK_FN(checkAlloca)
378 CHECK_FN(checkStrdup)
379 CHECK_FN(checkIfFreeNameIndex)
380 CHECK_FN(checkCXXNewOrCXXDelete)
381 CHECK_FN(checkGMalloc0)
382 CHECK_FN(checkGMemdup)
383 CHECK_FN(checkGMallocN)
384 CHECK_FN(checkGMallocN0)
385 CHECK_FN(checkReallocN)
386 CHECK_FN(checkOwnershipAttr)
387
388 void checkRealloc(const CallEvent &Call, CheckerContext &C,
389 bool ShouldFreeOnFail) const;
390
391 using CheckFn = std::function<void(const MallocChecker *,
392 const CallEvent &Call, CheckerContext &C)>;
393
394 const CallDescriptionMap<CheckFn> FreeingMemFnMap{
395 {{{"free"}, 1}, &MallocChecker::checkFree},
396 {{{"if_freenameindex"}, 1}, &MallocChecker::checkIfFreeNameIndex},
397 {{{"kfree"}, 1}, &MallocChecker::checkFree},
398 {{{"g_free"}, 1}, &MallocChecker::checkFree},
399 };
400
401 bool isFreeingCall(const CallEvent &Call) const;
402 static bool isFreeingOwnershipAttrCall(const FunctionDecl *Func);
403
404 friend class NoOwnershipChangeVisitor;
405
406 CallDescriptionMap<CheckFn> AllocatingMemFnMap{
407 {{{"alloca"}, 1}, &MallocChecker::checkAlloca},
408 {{{"_alloca"}, 1}, &MallocChecker::checkAlloca},
409 {{{"malloc"}, 1}, &MallocChecker::checkBasicAlloc},
410 {{{"malloc"}, 3}, &MallocChecker::checkKernelMalloc},
411 {{{"calloc"}, 2}, &MallocChecker::checkCalloc},
412 {{{"valloc"}, 1}, &MallocChecker::checkBasicAlloc},
413 {{CDF_MaybeBuiltin, {"strndup"}, 2}, &MallocChecker::checkStrdup},
414 {{CDF_MaybeBuiltin, {"strdup"}, 1}, &MallocChecker::checkStrdup},
415 {{{"_strdup"}, 1}, &MallocChecker::checkStrdup},
416 {{{"kmalloc"}, 2}, &MallocChecker::checkKernelMalloc},
417 {{{"if_nameindex"}, 1}, &MallocChecker::checkIfNameIndex},
418 {{CDF_MaybeBuiltin, {"wcsdup"}, 1}, &MallocChecker::checkStrdup},
419 {{CDF_MaybeBuiltin, {"_wcsdup"}, 1}, &MallocChecker::checkStrdup},
420 {{{"g_malloc"}, 1}, &MallocChecker::checkBasicAlloc},
421 {{{"g_malloc0"}, 1}, &MallocChecker::checkGMalloc0},
422 {{{"g_try_malloc"}, 1}, &MallocChecker::checkBasicAlloc},
423 {{{"g_try_malloc0"}, 1}, &MallocChecker::checkGMalloc0},
424 {{{"g_memdup"}, 2}, &MallocChecker::checkGMemdup},
425 {{{"g_malloc_n"}, 2}, &MallocChecker::checkGMallocN},
426 {{{"g_malloc0_n"}, 2}, &MallocChecker::checkGMallocN0},
427 {{{"g_try_malloc_n"}, 2}, &MallocChecker::checkGMallocN},
428 {{{"g_try_malloc0_n"}, 2}, &MallocChecker::checkGMallocN0},
429 };
430
431 CallDescriptionMap<CheckFn> ReallocatingMemFnMap{
432 {{{"realloc"}, 2},
433 std::bind(&MallocChecker::checkRealloc, _1, _2, _3, false)},
434 {{{"reallocf"}, 2},
435 std::bind(&MallocChecker::checkRealloc, _1, _2, _3, true)},
436 {{{"g_realloc"}, 2},
437 std::bind(&MallocChecker::checkRealloc, _1, _2, _3, false)},
438 {{{"g_try_realloc"}, 2},
439 std::bind(&MallocChecker::checkRealloc, _1, _2, _3, false)},
440 {{{"g_realloc_n"}, 3}, &MallocChecker::checkReallocN},
441 {{{"g_try_realloc_n"}, 3}, &MallocChecker::checkReallocN},
442 };
443
444 bool isMemCall(const CallEvent &Call) const;
445
446 // TODO: Remove mutable by moving the initializtaion to the registry function.
447 mutable std::optional<uint64_t> KernelZeroFlagVal;
448
449 using KernelZeroSizePtrValueTy = std::optional<int>;
450 /// Store the value of macro called `ZERO_SIZE_PTR`.
451 /// The value is initialized at first use, before first use the outer
452 /// Optional is empty, afterwards it contains another Optional that indicates
453 /// if the macro value could be determined, and if yes the value itself.
454 mutable std::optional<KernelZeroSizePtrValueTy> KernelZeroSizePtrValue;
455
456 /// Process C++ operator new()'s allocation, which is the part of C++
457 /// new-expression that goes before the constructor.
458 [[nodiscard]] ProgramStateRef
459 processNewAllocation(const CXXAllocatorCall &Call, CheckerContext &C,
460 AllocationFamily Family) const;
461
462 /// Perform a zero-allocation check.
463 ///
464 /// \param [in] Call The expression that allocates memory.
465 /// \param [in] IndexOfSizeArg Index of the argument that specifies the size
466 /// of the memory that needs to be allocated. E.g. for malloc, this would be
467 /// 0.
468 /// \param [in] RetVal Specifies the newly allocated pointer value;
469 /// if unspecified, the value of expression \p E is used.
470 [[nodiscard]] static ProgramStateRef
471 ProcessZeroAllocCheck(const CallEvent &Call, const unsigned IndexOfSizeArg,
472 ProgramStateRef State,
473 std::optional<SVal> RetVal = std::nullopt);
474
475 /// Model functions with the ownership_returns attribute.
476 ///
477 /// User-defined function may have the ownership_returns attribute, which
478 /// annotates that the function returns with an object that was allocated on
479 /// the heap, and passes the ownertship to the callee.
480 ///
481 /// void __attribute((ownership_returns(malloc, 1))) *my_malloc(size_t);
482 ///
483 /// It has two parameters:
484 /// - first: name of the resource (e.g. 'malloc')
485 /// - (OPTIONAL) second: size of the allocated region
486 ///
487 /// \param [in] Call The expression that allocates memory.
488 /// \param [in] Att The ownership_returns attribute.
489 /// \param [in] State The \c ProgramState right before allocation.
490 /// \returns The ProgramState right after allocation.
491 [[nodiscard]] ProgramStateRef
492 MallocMemReturnsAttr(CheckerContext &C, const CallEvent &Call,
493 const OwnershipAttr *Att, ProgramStateRef State) const;
494
495 /// Models memory allocation.
496 ///
497 /// \param [in] Call The expression that allocates memory.
498 /// \param [in] SizeEx Size of the memory that needs to be allocated.
499 /// \param [in] Init The value the allocated memory needs to be initialized.
500 /// with. For example, \c calloc initializes the allocated memory to 0,
501 /// malloc leaves it undefined.
502 /// \param [in] State The \c ProgramState right before allocation.
503 /// \returns The ProgramState right after allocation.
504 [[nodiscard]] static ProgramStateRef
505 MallocMemAux(CheckerContext &C, const CallEvent &Call, const Expr *SizeEx,
506 SVal Init, ProgramStateRef State, AllocationFamily Family);
507
508 /// Models memory allocation.
509 ///
510 /// \param [in] Call The expression that allocates memory.
511 /// \param [in] Size Size of the memory that needs to be allocated.
512 /// \param [in] Init The value the allocated memory needs to be initialized.
513 /// with. For example, \c calloc initializes the allocated memory to 0,
514 /// malloc leaves it undefined.
515 /// \param [in] State The \c ProgramState right before allocation.
516 /// \returns The ProgramState right after allocation.
517 [[nodiscard]] static ProgramStateRef
518 MallocMemAux(CheckerContext &C, const CallEvent &Call, SVal Size, SVal Init,
519 ProgramStateRef State, AllocationFamily Family);
520
521 // Check if this malloc() for special flags. At present that means M_ZERO or
522 // __GFP_ZERO (in which case, treat it like calloc).
523 [[nodiscard]] std::optional<ProgramStateRef>
524 performKernelMalloc(const CallEvent &Call, CheckerContext &C,
525 const ProgramStateRef &State) const;
526
527 /// Model functions with the ownership_takes and ownership_holds attributes.
528 ///
529 /// User-defined function may have the ownership_takes and/or ownership_holds
530 /// attributes, which annotates that the function frees the memory passed as a
531 /// parameter.
532 ///
533 /// void __attribute((ownership_takes(malloc, 1))) my_free(void *);
534 /// void __attribute((ownership_holds(malloc, 1))) my_hold(void *);
535 ///
536 /// They have two parameters:
537 /// - first: name of the resource (e.g. 'malloc')
538 /// - second: index of the parameter the attribute applies to
539 ///
540 /// \param [in] Call The expression that frees memory.
541 /// \param [in] Att The ownership_takes or ownership_holds attribute.
542 /// \param [in] State The \c ProgramState right before allocation.
543 /// \returns The ProgramState right after deallocation.
544 [[nodiscard]] ProgramStateRef FreeMemAttr(CheckerContext &C,
545 const CallEvent &Call,
546 const OwnershipAttr *Att,
547 ProgramStateRef State) const;
548
549 /// Models memory deallocation.
550 ///
551 /// \param [in] Call The expression that frees memory.
552 /// \param [in] State The \c ProgramState right before allocation.
553 /// \param [in] Num Index of the argument that needs to be freed. This is
554 /// normally 0, but for custom free functions it may be different.
555 /// \param [in] Hold Whether the parameter at \p Index has the ownership_holds
556 /// attribute.
557 /// \param [out] IsKnownToBeAllocated Whether the memory to be freed is known
558 /// to have been allocated, or in other words, the symbol to be freed was
559 /// registered as allocated by this checker. In the following case, \c ptr
560 /// isn't known to be allocated.
561 /// void Haha(int *ptr) {
562 /// ptr = realloc(ptr, 67);
563 /// // ...
564 /// }
565 /// \param [in] ReturnsNullOnFailure Whether the memory deallocation function
566 /// we're modeling returns with Null on failure.
567 /// \returns The ProgramState right after deallocation.
568 [[nodiscard]] ProgramStateRef
569 FreeMemAux(CheckerContext &C, const CallEvent &Call, ProgramStateRef State,
570 unsigned Num, bool Hold, bool &IsKnownToBeAllocated,
571 AllocationFamily Family, bool ReturnsNullOnFailure = false) const;
572
573 /// Models memory deallocation.
574 ///
575 /// \param [in] ArgExpr The variable who's pointee needs to be freed.
576 /// \param [in] Call The expression that frees the memory.
577 /// \param [in] State The \c ProgramState right before allocation.
578 /// normally 0, but for custom free functions it may be different.
579 /// \param [in] Hold Whether the parameter at \p Index has the ownership_holds
580 /// attribute.
581 /// \param [out] IsKnownToBeAllocated Whether the memory to be freed is known
582 /// to have been allocated, or in other words, the symbol to be freed was
583 /// registered as allocated by this checker. In the following case, \c ptr
584 /// isn't known to be allocated.
585 /// void Haha(int *ptr) {
586 /// ptr = realloc(ptr, 67);
587 /// // ...
588 /// }
589 /// \param [in] ReturnsNullOnFailure Whether the memory deallocation function
590 /// we're modeling returns with Null on failure.
591 /// \returns The ProgramState right after deallocation.
592 [[nodiscard]] ProgramStateRef
593 FreeMemAux(CheckerContext &C, const Expr *ArgExpr, const CallEvent &Call,
594 ProgramStateRef State, bool Hold, bool &IsKnownToBeAllocated,
595 AllocationFamily Family, bool ReturnsNullOnFailure = false) const;
596
597 // TODO: Needs some refactoring, as all other deallocation modeling
598 // functions are suffering from out parameters and messy code due to how
599 // realloc is handled.
600 //
601 /// Models memory reallocation.
602 ///
603 /// \param [in] Call The expression that reallocated memory
604 /// \param [in] ShouldFreeOnFail Whether if reallocation fails, the supplied
605 /// memory should be freed.
606 /// \param [in] State The \c ProgramState right before reallocation.
607 /// \param [in] SuffixWithN Whether the reallocation function we're modeling
608 /// has an '_n' suffix, such as g_realloc_n.
609 /// \returns The ProgramState right after reallocation.
610 [[nodiscard]] ProgramStateRef
611 ReallocMemAux(CheckerContext &C, const CallEvent &Call, bool ShouldFreeOnFail,
612 ProgramStateRef State, AllocationFamily Family,
613 bool SuffixWithN = false) const;
614
615 /// Evaluates the buffer size that needs to be allocated.
616 ///
617 /// \param [in] Blocks The amount of blocks that needs to be allocated.
618 /// \param [in] BlockBytes The size of a block.
619 /// \returns The symbolic value of \p Blocks * \p BlockBytes.
620 [[nodiscard]] static SVal evalMulForBufferSize(CheckerContext &C,
621 const Expr *Blocks,
622 const Expr *BlockBytes);
623
624 /// Models zero initialized array allocation.
625 ///
626 /// \param [in] Call The expression that reallocated memory
627 /// \param [in] State The \c ProgramState right before reallocation.
628 /// \returns The ProgramState right after allocation.
629 [[nodiscard]] static ProgramStateRef
630 CallocMem(CheckerContext &C, const CallEvent &Call, ProgramStateRef State);
631
632 /// See if deallocation happens in a suspicious context. If so, escape the
633 /// pointers that otherwise would have been deallocated and return true.
634 bool suppressDeallocationsInSuspiciousContexts(const CallEvent &Call,
635 CheckerContext &C) const;
636
637 /// If in \p S \p Sym is used, check whether \p Sym was already freed.
638 bool checkUseAfterFree(SymbolRef Sym, CheckerContext &C, const Stmt *S) const;
639
640 /// If in \p S \p Sym is used, check whether \p Sym was allocated as a zero
641 /// sized memory region.
642 void checkUseZeroAllocated(SymbolRef Sym, CheckerContext &C,
643 const Stmt *S) const;
644
645 /// If in \p S \p Sym is being freed, check whether \p Sym was already freed.
646 bool checkDoubleDelete(SymbolRef Sym, CheckerContext &C) const;
647
648 /// Check if the function is known to free memory, or if it is
649 /// "interesting" and should be modeled explicitly.
650 ///
651 /// \param [out] EscapingSymbol A function might not free memory in general,
652 /// but could be known to free a particular symbol. In this case, false is
653 /// returned and the single escaping symbol is returned through the out
654 /// parameter.
655 ///
656 /// We assume that pointers do not escape through calls to system functions
657 /// not handled by this checker.
658 bool mayFreeAnyEscapedMemoryOrIsModeledExplicitly(const CallEvent *Call,
659 ProgramStateRef State,
660 SymbolRef &EscapingSymbol) const;
661
662 /// Implementation of the checkPointerEscape callbacks.
663 [[nodiscard]] ProgramStateRef
664 checkPointerEscapeAux(ProgramStateRef State,
665 const InvalidatedSymbols &Escaped,
666 const CallEvent *Call, PointerEscapeKind Kind,
667 bool IsConstPointerEscape) const;
668
669 // Implementation of the checkPreStmt and checkEndFunction callbacks.
670 void checkEscapeOnReturn(const ReturnStmt *S, CheckerContext &C) const;
671
672 ///@{
673 /// Tells if a given family/call/symbol is tracked by the current checker.
674 /// Sets CheckKind to the kind of the checker responsible for this
675 /// family/call/symbol.
676 std::optional<CheckKind> getCheckIfTracked(AllocationFamily Family,
677 bool IsALeakCheck = false) const;
678
679 std::optional<CheckKind> getCheckIfTracked(CheckerContext &C, SymbolRef Sym,
680 bool IsALeakCheck = false) const;
681 ///@}
682 static bool SummarizeValue(raw_ostream &os, SVal V);
683 static bool SummarizeRegion(raw_ostream &os, const MemRegion *MR);
684
685 void HandleNonHeapDealloc(CheckerContext &C, SVal ArgVal, SourceRange Range,
686 const Expr *DeallocExpr,
687 AllocationFamily Family) const;
688
689 void HandleFreeAlloca(CheckerContext &C, SVal ArgVal,
690 SourceRange Range) const;
691
692 void HandleMismatchedDealloc(CheckerContext &C, SourceRange Range,
693 const Expr *DeallocExpr, const RefState *RS,
694 SymbolRef Sym, bool OwnershipTransferred) const;
695
696 void HandleOffsetFree(CheckerContext &C, SVal ArgVal, SourceRange Range,
697 const Expr *DeallocExpr, AllocationFamily Family,
698 const Expr *AllocExpr = nullptr) const;
699
700 void HandleUseAfterFree(CheckerContext &C, SourceRange Range,
701 SymbolRef Sym) const;
702
703 void HandleDoubleFree(CheckerContext &C, SourceRange Range, bool Released,
704 SymbolRef Sym, SymbolRef PrevSym) const;
705
706 void HandleDoubleDelete(CheckerContext &C, SymbolRef Sym) const;
707
708 void HandleUseZeroAlloc(CheckerContext &C, SourceRange Range,
709 SymbolRef Sym) const;
710
711 void HandleFunctionPtrFree(CheckerContext &C, SVal ArgVal, SourceRange Range,
712 const Expr *FreeExpr,
713 AllocationFamily Family) const;
714
715 /// Find the location of the allocation for Sym on the path leading to the
716 /// exploded node N.
717 static LeakInfo getAllocationSite(const ExplodedNode *N, SymbolRef Sym,
718 CheckerContext &C);
719
720 void HandleLeak(SymbolRef Sym, ExplodedNode *N, CheckerContext &C) const;
721
722 /// Test if value in ArgVal equals to value in macro `ZERO_SIZE_PTR`.
723 bool isArgZERO_SIZE_PTR(ProgramStateRef State, CheckerContext &C,
724 SVal ArgVal) const;
725 };
726 } // end anonymous namespace
727
728 //===----------------------------------------------------------------------===//
729 // Definition of NoOwnershipChangeVisitor.
730 //===----------------------------------------------------------------------===//
731
732 namespace {
733 class NoOwnershipChangeVisitor final : public NoStateChangeFuncVisitor {
734 // The symbol whose (lack of) ownership change we are interested in.
735 SymbolRef Sym;
736 const MallocChecker &Checker;
737 using OwnerSet = llvm::SmallPtrSet<const MemRegion *, 8>;
738
739 // Collect which entities point to the allocated memory, and could be
740 // responsible for deallocating it.
741 class OwnershipBindingsHandler : public StoreManager::BindingsHandler {
742 SymbolRef Sym;
743 OwnerSet &Owners;
744
745 public:
OwnershipBindingsHandler(SymbolRef Sym,OwnerSet & Owners)746 OwnershipBindingsHandler(SymbolRef Sym, OwnerSet &Owners)
747 : Sym(Sym), Owners(Owners) {}
748
HandleBinding(StoreManager & SMgr,Store Store,const MemRegion * Region,SVal Val)749 bool HandleBinding(StoreManager &SMgr, Store Store, const MemRegion *Region,
750 SVal Val) override {
751 if (Val.getAsSymbol() == Sym)
752 Owners.insert(Region);
753 return true;
754 }
755
dump() const756 LLVM_DUMP_METHOD void dump() const { dumpToStream(llvm::errs()); }
dumpToStream(llvm::raw_ostream & out) const757 LLVM_DUMP_METHOD void dumpToStream(llvm::raw_ostream &out) const {
758 out << "Owners: {\n";
759 for (const MemRegion *Owner : Owners) {
760 out << " ";
761 Owner->dumpToStream(out);
762 out << ",\n";
763 }
764 out << "}\n";
765 }
766 };
767
768 protected:
getOwnersAtNode(const ExplodedNode * N)769 OwnerSet getOwnersAtNode(const ExplodedNode *N) {
770 OwnerSet Ret;
771
772 ProgramStateRef State = N->getState();
773 OwnershipBindingsHandler Handler{Sym, Ret};
774 State->getStateManager().getStoreManager().iterBindings(State->getStore(),
775 Handler);
776 return Ret;
777 }
778
779 LLVM_DUMP_METHOD static std::string
getFunctionName(const ExplodedNode * CallEnterN)780 getFunctionName(const ExplodedNode *CallEnterN) {
781 if (const CallExpr *CE = llvm::dyn_cast_or_null<CallExpr>(
782 CallEnterN->getLocationAs<CallEnter>()->getCallExpr()))
783 if (const FunctionDecl *FD = CE->getDirectCallee())
784 return FD->getQualifiedNameAsString();
785 return "";
786 }
787
788 /// Syntactically checks whether the callee is a deallocating function. Since
789 /// we have no path-sensitive information on this call (we would need a
790 /// CallEvent instead of a CallExpr for that), its possible that a
791 /// deallocation function was called indirectly through a function pointer,
792 /// but we are not able to tell, so this is a best effort analysis.
793 /// See namespace `memory_passed_to_fn_call_free_through_fn_ptr` in
794 /// clang/test/Analysis/NewDeleteLeaks.cpp.
isFreeingCallAsWritten(const CallExpr & Call) const795 bool isFreeingCallAsWritten(const CallExpr &Call) const {
796 if (Checker.FreeingMemFnMap.lookupAsWritten(Call) ||
797 Checker.ReallocatingMemFnMap.lookupAsWritten(Call))
798 return true;
799
800 if (const auto *Func =
801 llvm::dyn_cast_or_null<FunctionDecl>(Call.getCalleeDecl()))
802 return MallocChecker::isFreeingOwnershipAttrCall(Func);
803
804 return false;
805 }
806
807 /// Heuristically guess whether the callee intended to free memory. This is
808 /// done syntactically, because we are trying to argue about alternative
809 /// paths of execution, and as a consequence we don't have path-sensitive
810 /// information.
doesFnIntendToHandleOwnership(const Decl * Callee,ASTContext & ACtx)811 bool doesFnIntendToHandleOwnership(const Decl *Callee, ASTContext &ACtx) {
812 using namespace clang::ast_matchers;
813 const FunctionDecl *FD = dyn_cast<FunctionDecl>(Callee);
814
815 // Given that the stack frame was entered, the body should always be
816 // theoretically obtainable. In case of body farms, the synthesized body
817 // is not attached to declaration, thus triggering the '!FD->hasBody()'
818 // branch. That said, would a synthesized body ever intend to handle
819 // ownership? As of today they don't. And if they did, how would we
820 // put notes inside it, given that it doesn't match any source locations?
821 if (!FD || !FD->hasBody())
822 return false;
823
824 auto Matches = match(findAll(stmt(anyOf(cxxDeleteExpr().bind("delete"),
825 callExpr().bind("call")))),
826 *FD->getBody(), ACtx);
827 for (BoundNodes Match : Matches) {
828 if (Match.getNodeAs<CXXDeleteExpr>("delete"))
829 return true;
830
831 if (const auto *Call = Match.getNodeAs<CallExpr>("call"))
832 if (isFreeingCallAsWritten(*Call))
833 return true;
834 }
835 // TODO: Ownership might change with an attempt to store the allocated
836 // memory, not only through deallocation. Check for attempted stores as
837 // well.
838 return false;
839 }
840
wasModifiedInFunction(const ExplodedNode * CallEnterN,const ExplodedNode * CallExitEndN)841 bool wasModifiedInFunction(const ExplodedNode *CallEnterN,
842 const ExplodedNode *CallExitEndN) override {
843 if (!doesFnIntendToHandleOwnership(
844 CallExitEndN->getFirstPred()->getLocationContext()->getDecl(),
845 CallExitEndN->getState()->getAnalysisManager().getASTContext()))
846 return true;
847
848 if (CallEnterN->getState()->get<RegionState>(Sym) !=
849 CallExitEndN->getState()->get<RegionState>(Sym))
850 return true;
851
852 OwnerSet CurrOwners = getOwnersAtNode(CallEnterN);
853 OwnerSet ExitOwners = getOwnersAtNode(CallExitEndN);
854
855 // Owners in the current set may be purged from the analyzer later on.
856 // If a variable is dead (is not referenced directly or indirectly after
857 // some point), it will be removed from the Store before the end of its
858 // actual lifetime.
859 // This means that if the ownership status didn't change, CurrOwners
860 // must be a superset of, but not necessarily equal to ExitOwners.
861 return !llvm::set_is_subset(ExitOwners, CurrOwners);
862 }
863
emitNote(const ExplodedNode * N)864 static PathDiagnosticPieceRef emitNote(const ExplodedNode *N) {
865 PathDiagnosticLocation L = PathDiagnosticLocation::create(
866 N->getLocation(),
867 N->getState()->getStateManager().getContext().getSourceManager());
868 return std::make_shared<PathDiagnosticEventPiece>(
869 L, "Returning without deallocating memory or storing the pointer for "
870 "later deallocation");
871 }
872
873 PathDiagnosticPieceRef
maybeEmitNoteForObjCSelf(PathSensitiveBugReport & R,const ObjCMethodCall & Call,const ExplodedNode * N)874 maybeEmitNoteForObjCSelf(PathSensitiveBugReport &R,
875 const ObjCMethodCall &Call,
876 const ExplodedNode *N) override {
877 // TODO: Implement.
878 return nullptr;
879 }
880
881 PathDiagnosticPieceRef
maybeEmitNoteForCXXThis(PathSensitiveBugReport & R,const CXXConstructorCall & Call,const ExplodedNode * N)882 maybeEmitNoteForCXXThis(PathSensitiveBugReport &R,
883 const CXXConstructorCall &Call,
884 const ExplodedNode *N) override {
885 // TODO: Implement.
886 return nullptr;
887 }
888
889 PathDiagnosticPieceRef
maybeEmitNoteForParameters(PathSensitiveBugReport & R,const CallEvent & Call,const ExplodedNode * N)890 maybeEmitNoteForParameters(PathSensitiveBugReport &R, const CallEvent &Call,
891 const ExplodedNode *N) override {
892 // TODO: Factor the logic of "what constitutes as an entity being passed
893 // into a function call" out by reusing the code in
894 // NoStoreFuncVisitor::maybeEmitNoteForParameters, maybe by incorporating
895 // the printing technology in UninitializedObject's FieldChainInfo.
896 ArrayRef<ParmVarDecl *> Parameters = Call.parameters();
897 for (unsigned I = 0; I < Call.getNumArgs() && I < Parameters.size(); ++I) {
898 SVal V = Call.getArgSVal(I);
899 if (V.getAsSymbol() == Sym)
900 return emitNote(N);
901 }
902 return nullptr;
903 }
904
905 public:
NoOwnershipChangeVisitor(SymbolRef Sym,const MallocChecker * Checker)906 NoOwnershipChangeVisitor(SymbolRef Sym, const MallocChecker *Checker)
907 : NoStateChangeFuncVisitor(bugreporter::TrackingKind::Thorough), Sym(Sym),
908 Checker(*Checker) {}
909
Profile(llvm::FoldingSetNodeID & ID) const910 void Profile(llvm::FoldingSetNodeID &ID) const override {
911 static int Tag = 0;
912 ID.AddPointer(&Tag);
913 ID.AddPointer(Sym);
914 }
915 };
916
917 } // end anonymous namespace
918
919 //===----------------------------------------------------------------------===//
920 // Definition of MallocBugVisitor.
921 //===----------------------------------------------------------------------===//
922
923 namespace {
924 /// The bug visitor which allows us to print extra diagnostics along the
925 /// BugReport path. For example, showing the allocation site of the leaked
926 /// region.
927 class MallocBugVisitor final : public BugReporterVisitor {
928 protected:
929 enum NotificationMode { Normal, ReallocationFailed };
930
931 // The allocated region symbol tracked by the main analysis.
932 SymbolRef Sym;
933
934 // The mode we are in, i.e. what kind of diagnostics will be emitted.
935 NotificationMode Mode;
936
937 // A symbol from when the primary region should have been reallocated.
938 SymbolRef FailedReallocSymbol;
939
940 // A C++ destructor stack frame in which memory was released. Used for
941 // miscellaneous false positive suppression.
942 const StackFrameContext *ReleaseDestructorLC;
943
944 bool IsLeak;
945
946 public:
MallocBugVisitor(SymbolRef S,bool isLeak=false)947 MallocBugVisitor(SymbolRef S, bool isLeak = false)
948 : Sym(S), Mode(Normal), FailedReallocSymbol(nullptr),
949 ReleaseDestructorLC(nullptr), IsLeak(isLeak) {}
950
getTag()951 static void *getTag() {
952 static int Tag = 0;
953 return &Tag;
954 }
955
Profile(llvm::FoldingSetNodeID & ID) const956 void Profile(llvm::FoldingSetNodeID &ID) const override {
957 ID.AddPointer(getTag());
958 ID.AddPointer(Sym);
959 }
960
961 /// Did not track -> allocated. Other state (released) -> allocated.
isAllocated(const RefState * RSCurr,const RefState * RSPrev,const Stmt * Stmt)962 static inline bool isAllocated(const RefState *RSCurr, const RefState *RSPrev,
963 const Stmt *Stmt) {
964 return (isa_and_nonnull<CallExpr, CXXNewExpr>(Stmt) &&
965 (RSCurr &&
966 (RSCurr->isAllocated() || RSCurr->isAllocatedOfSizeZero())) &&
967 (!RSPrev ||
968 !(RSPrev->isAllocated() || RSPrev->isAllocatedOfSizeZero())));
969 }
970
971 /// Did not track -> released. Other state (allocated) -> released.
972 /// The statement associated with the release might be missing.
isReleased(const RefState * RSCurr,const RefState * RSPrev,const Stmt * Stmt)973 static inline bool isReleased(const RefState *RSCurr, const RefState *RSPrev,
974 const Stmt *Stmt) {
975 bool IsReleased =
976 (RSCurr && RSCurr->isReleased()) && (!RSPrev || !RSPrev->isReleased());
977 assert(!IsReleased || (isa_and_nonnull<CallExpr, CXXDeleteExpr>(Stmt)) ||
978 (!Stmt && RSCurr->getAllocationFamily() == AF_InnerBuffer));
979 return IsReleased;
980 }
981
982 /// Did not track -> relinquished. Other state (allocated) -> relinquished.
isRelinquished(const RefState * RSCurr,const RefState * RSPrev,const Stmt * Stmt)983 static inline bool isRelinquished(const RefState *RSCurr,
984 const RefState *RSPrev, const Stmt *Stmt) {
985 return (
986 isa_and_nonnull<CallExpr, ObjCMessageExpr, ObjCPropertyRefExpr>(Stmt) &&
987 (RSCurr && RSCurr->isRelinquished()) &&
988 (!RSPrev || !RSPrev->isRelinquished()));
989 }
990
991 /// If the expression is not a call, and the state change is
992 /// released -> allocated, it must be the realloc return value
993 /// check. If we have to handle more cases here, it might be cleaner just
994 /// to track this extra bit in the state itself.
hasReallocFailed(const RefState * RSCurr,const RefState * RSPrev,const Stmt * Stmt)995 static inline bool hasReallocFailed(const RefState *RSCurr,
996 const RefState *RSPrev,
997 const Stmt *Stmt) {
998 return ((!isa_and_nonnull<CallExpr>(Stmt)) &&
999 (RSCurr &&
1000 (RSCurr->isAllocated() || RSCurr->isAllocatedOfSizeZero())) &&
1001 (RSPrev &&
1002 !(RSPrev->isAllocated() || RSPrev->isAllocatedOfSizeZero())));
1003 }
1004
1005 PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
1006 BugReporterContext &BRC,
1007 PathSensitiveBugReport &BR) override;
1008
getEndPath(BugReporterContext & BRC,const ExplodedNode * EndPathNode,PathSensitiveBugReport & BR)1009 PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC,
1010 const ExplodedNode *EndPathNode,
1011 PathSensitiveBugReport &BR) override {
1012 if (!IsLeak)
1013 return nullptr;
1014
1015 PathDiagnosticLocation L = BR.getLocation();
1016 // Do not add the statement itself as a range in case of leak.
1017 return std::make_shared<PathDiagnosticEventPiece>(L, BR.getDescription(),
1018 false);
1019 }
1020
1021 private:
1022 class StackHintGeneratorForReallocationFailed
1023 : public StackHintGeneratorForSymbol {
1024 public:
StackHintGeneratorForReallocationFailed(SymbolRef S,StringRef M)1025 StackHintGeneratorForReallocationFailed(SymbolRef S, StringRef M)
1026 : StackHintGeneratorForSymbol(S, M) {}
1027
getMessageForArg(const Expr * ArgE,unsigned ArgIndex)1028 std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex) override {
1029 // Printed parameters start at 1, not 0.
1030 ++ArgIndex;
1031
1032 SmallString<200> buf;
1033 llvm::raw_svector_ostream os(buf);
1034
1035 os << "Reallocation of " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
1036 << " parameter failed";
1037
1038 return std::string(os.str());
1039 }
1040
getMessageForReturn(const CallExpr * CallExpr)1041 std::string getMessageForReturn(const CallExpr *CallExpr) override {
1042 return "Reallocation of returned value failed";
1043 }
1044 };
1045 };
1046 } // end anonymous namespace
1047
1048 // A map from the freed symbol to the symbol representing the return value of
1049 // the free function.
1050 REGISTER_MAP_WITH_PROGRAMSTATE(FreeReturnValue, SymbolRef, SymbolRef)
1051
1052 namespace {
1053 class StopTrackingCallback final : public SymbolVisitor {
1054 ProgramStateRef state;
1055
1056 public:
StopTrackingCallback(ProgramStateRef st)1057 StopTrackingCallback(ProgramStateRef st) : state(std::move(st)) {}
getState() const1058 ProgramStateRef getState() const { return state; }
1059
VisitSymbol(SymbolRef sym)1060 bool VisitSymbol(SymbolRef sym) override {
1061 state = state->remove<RegionState>(sym);
1062 return true;
1063 }
1064 };
1065 } // end anonymous namespace
1066
isStandardNewDelete(const FunctionDecl * FD)1067 static bool isStandardNewDelete(const FunctionDecl *FD) {
1068 if (!FD)
1069 return false;
1070
1071 OverloadedOperatorKind Kind = FD->getOverloadedOperator();
1072 if (Kind != OO_New && Kind != OO_Array_New && Kind != OO_Delete &&
1073 Kind != OO_Array_Delete)
1074 return false;
1075
1076 // This is standard if and only if it's not defined in a user file.
1077 SourceLocation L = FD->getLocation();
1078 // If the header for operator delete is not included, it's still defined
1079 // in an invalid source location. Check to make sure we don't crash.
1080 return !L.isValid() ||
1081 FD->getASTContext().getSourceManager().isInSystemHeader(L);
1082 }
1083
1084 //===----------------------------------------------------------------------===//
1085 // Methods of MallocChecker and MallocBugVisitor.
1086 //===----------------------------------------------------------------------===//
1087
isFreeingOwnershipAttrCall(const FunctionDecl * Func)1088 bool MallocChecker::isFreeingOwnershipAttrCall(const FunctionDecl *Func) {
1089 if (Func->hasAttrs()) {
1090 for (const auto *I : Func->specific_attrs<OwnershipAttr>()) {
1091 OwnershipAttr::OwnershipKind OwnKind = I->getOwnKind();
1092 if (OwnKind == OwnershipAttr::Takes || OwnKind == OwnershipAttr::Holds)
1093 return true;
1094 }
1095 }
1096 return false;
1097 }
1098
isFreeingCall(const CallEvent & Call) const1099 bool MallocChecker::isFreeingCall(const CallEvent &Call) const {
1100 if (FreeingMemFnMap.lookup(Call) || ReallocatingMemFnMap.lookup(Call))
1101 return true;
1102
1103 if (const auto *Func = dyn_cast_or_null<FunctionDecl>(Call.getDecl()))
1104 return isFreeingOwnershipAttrCall(Func);
1105
1106 return false;
1107 }
1108
isMemCall(const CallEvent & Call) const1109 bool MallocChecker::isMemCall(const CallEvent &Call) const {
1110 if (FreeingMemFnMap.lookup(Call) || AllocatingMemFnMap.lookup(Call) ||
1111 ReallocatingMemFnMap.lookup(Call))
1112 return true;
1113
1114 if (!ShouldIncludeOwnershipAnnotatedFunctions)
1115 return false;
1116
1117 const auto *Func = dyn_cast<FunctionDecl>(Call.getDecl());
1118 return Func && Func->hasAttr<OwnershipAttr>();
1119 }
1120
1121 std::optional<ProgramStateRef>
performKernelMalloc(const CallEvent & Call,CheckerContext & C,const ProgramStateRef & State) const1122 MallocChecker::performKernelMalloc(const CallEvent &Call, CheckerContext &C,
1123 const ProgramStateRef &State) const {
1124 // 3-argument malloc(), as commonly used in {Free,Net,Open}BSD Kernels:
1125 //
1126 // void *malloc(unsigned long size, struct malloc_type *mtp, int flags);
1127 //
1128 // One of the possible flags is M_ZERO, which means 'give me back an
1129 // allocation which is already zeroed', like calloc.
1130
1131 // 2-argument kmalloc(), as used in the Linux kernel:
1132 //
1133 // void *kmalloc(size_t size, gfp_t flags);
1134 //
1135 // Has the similar flag value __GFP_ZERO.
1136
1137 // This logic is largely cloned from O_CREAT in UnixAPIChecker, maybe some
1138 // code could be shared.
1139
1140 ASTContext &Ctx = C.getASTContext();
1141 llvm::Triple::OSType OS = Ctx.getTargetInfo().getTriple().getOS();
1142
1143 if (!KernelZeroFlagVal) {
1144 if (OS == llvm::Triple::FreeBSD)
1145 KernelZeroFlagVal = 0x0100;
1146 else if (OS == llvm::Triple::NetBSD)
1147 KernelZeroFlagVal = 0x0002;
1148 else if (OS == llvm::Triple::OpenBSD)
1149 KernelZeroFlagVal = 0x0008;
1150 else if (OS == llvm::Triple::Linux)
1151 // __GFP_ZERO
1152 KernelZeroFlagVal = 0x8000;
1153 else
1154 // FIXME: We need a more general way of getting the M_ZERO value.
1155 // See also: O_CREAT in UnixAPIChecker.cpp.
1156
1157 // Fall back to normal malloc behavior on platforms where we don't
1158 // know M_ZERO.
1159 return std::nullopt;
1160 }
1161
1162 // We treat the last argument as the flags argument, and callers fall-back to
1163 // normal malloc on a None return. This works for the FreeBSD kernel malloc
1164 // as well as Linux kmalloc.
1165 if (Call.getNumArgs() < 2)
1166 return std::nullopt;
1167
1168 const Expr *FlagsEx = Call.getArgExpr(Call.getNumArgs() - 1);
1169 const SVal V = C.getSVal(FlagsEx);
1170 if (!isa<NonLoc>(V)) {
1171 // The case where 'V' can be a location can only be due to a bad header,
1172 // so in this case bail out.
1173 return std::nullopt;
1174 }
1175
1176 NonLoc Flags = V.castAs<NonLoc>();
1177 NonLoc ZeroFlag = C.getSValBuilder()
1178 .makeIntVal(*KernelZeroFlagVal, FlagsEx->getType())
1179 .castAs<NonLoc>();
1180 SVal MaskedFlagsUC = C.getSValBuilder().evalBinOpNN(State, BO_And,
1181 Flags, ZeroFlag,
1182 FlagsEx->getType());
1183 if (MaskedFlagsUC.isUnknownOrUndef())
1184 return std::nullopt;
1185 DefinedSVal MaskedFlags = MaskedFlagsUC.castAs<DefinedSVal>();
1186
1187 // Check if maskedFlags is non-zero.
1188 ProgramStateRef TrueState, FalseState;
1189 std::tie(TrueState, FalseState) = State->assume(MaskedFlags);
1190
1191 // If M_ZERO is set, treat this like calloc (initialized).
1192 if (TrueState && !FalseState) {
1193 SVal ZeroVal = C.getSValBuilder().makeZeroVal(Ctx.CharTy);
1194 return MallocMemAux(C, Call, Call.getArgExpr(0), ZeroVal, TrueState,
1195 AF_Malloc);
1196 }
1197
1198 return std::nullopt;
1199 }
1200
evalMulForBufferSize(CheckerContext & C,const Expr * Blocks,const Expr * BlockBytes)1201 SVal MallocChecker::evalMulForBufferSize(CheckerContext &C, const Expr *Blocks,
1202 const Expr *BlockBytes) {
1203 SValBuilder &SB = C.getSValBuilder();
1204 SVal BlocksVal = C.getSVal(Blocks);
1205 SVal BlockBytesVal = C.getSVal(BlockBytes);
1206 ProgramStateRef State = C.getState();
1207 SVal TotalSize = SB.evalBinOp(State, BO_Mul, BlocksVal, BlockBytesVal,
1208 SB.getContext().getSizeType());
1209 return TotalSize;
1210 }
1211
checkBasicAlloc(const CallEvent & Call,CheckerContext & C) const1212 void MallocChecker::checkBasicAlloc(const CallEvent &Call,
1213 CheckerContext &C) const {
1214 ProgramStateRef State = C.getState();
1215 State = MallocMemAux(C, Call, Call.getArgExpr(0), UndefinedVal(), State,
1216 AF_Malloc);
1217 State = ProcessZeroAllocCheck(Call, 0, State);
1218 C.addTransition(State);
1219 }
1220
checkKernelMalloc(const CallEvent & Call,CheckerContext & C) const1221 void MallocChecker::checkKernelMalloc(const CallEvent &Call,
1222 CheckerContext &C) const {
1223 ProgramStateRef State = C.getState();
1224 std::optional<ProgramStateRef> MaybeState =
1225 performKernelMalloc(Call, C, State);
1226 if (MaybeState)
1227 State = *MaybeState;
1228 else
1229 State = MallocMemAux(C, Call, Call.getArgExpr(0), UndefinedVal(), State,
1230 AF_Malloc);
1231 C.addTransition(State);
1232 }
1233
isStandardRealloc(const CallEvent & Call)1234 static bool isStandardRealloc(const CallEvent &Call) {
1235 const FunctionDecl *FD = dyn_cast<FunctionDecl>(Call.getDecl());
1236 assert(FD);
1237 ASTContext &AC = FD->getASTContext();
1238
1239 if (isa<CXXMethodDecl>(FD))
1240 return false;
1241
1242 return FD->getDeclaredReturnType().getDesugaredType(AC) == AC.VoidPtrTy &&
1243 FD->getParamDecl(0)->getType().getDesugaredType(AC) == AC.VoidPtrTy &&
1244 FD->getParamDecl(1)->getType().getDesugaredType(AC) ==
1245 AC.getSizeType();
1246 }
1247
isGRealloc(const CallEvent & Call)1248 static bool isGRealloc(const CallEvent &Call) {
1249 const FunctionDecl *FD = dyn_cast<FunctionDecl>(Call.getDecl());
1250 assert(FD);
1251 ASTContext &AC = FD->getASTContext();
1252
1253 if (isa<CXXMethodDecl>(FD))
1254 return false;
1255
1256 return FD->getDeclaredReturnType().getDesugaredType(AC) == AC.VoidPtrTy &&
1257 FD->getParamDecl(0)->getType().getDesugaredType(AC) == AC.VoidPtrTy &&
1258 FD->getParamDecl(1)->getType().getDesugaredType(AC) ==
1259 AC.UnsignedLongTy;
1260 }
1261
checkRealloc(const CallEvent & Call,CheckerContext & C,bool ShouldFreeOnFail) const1262 void MallocChecker::checkRealloc(const CallEvent &Call, CheckerContext &C,
1263 bool ShouldFreeOnFail) const {
1264 // HACK: CallDescription currently recognizes non-standard realloc functions
1265 // as standard because it doesn't check the type, or wether its a non-method
1266 // function. This should be solved by making CallDescription smarter.
1267 // Mind that this came from a bug report, and all other functions suffer from
1268 // this.
1269 // https://bugs.llvm.org/show_bug.cgi?id=46253
1270 if (!isStandardRealloc(Call) && !isGRealloc(Call))
1271 return;
1272 ProgramStateRef State = C.getState();
1273 State = ReallocMemAux(C, Call, ShouldFreeOnFail, State, AF_Malloc);
1274 State = ProcessZeroAllocCheck(Call, 1, State);
1275 C.addTransition(State);
1276 }
1277
checkCalloc(const CallEvent & Call,CheckerContext & C) const1278 void MallocChecker::checkCalloc(const CallEvent &Call,
1279 CheckerContext &C) const {
1280 ProgramStateRef State = C.getState();
1281 State = CallocMem(C, Call, State);
1282 State = ProcessZeroAllocCheck(Call, 0, State);
1283 State = ProcessZeroAllocCheck(Call, 1, State);
1284 C.addTransition(State);
1285 }
1286
checkFree(const CallEvent & Call,CheckerContext & C) const1287 void MallocChecker::checkFree(const CallEvent &Call, CheckerContext &C) const {
1288 ProgramStateRef State = C.getState();
1289 bool IsKnownToBeAllocatedMemory = false;
1290 if (suppressDeallocationsInSuspiciousContexts(Call, C))
1291 return;
1292 State = FreeMemAux(C, Call, State, 0, false, IsKnownToBeAllocatedMemory,
1293 AF_Malloc);
1294 C.addTransition(State);
1295 }
1296
checkAlloca(const CallEvent & Call,CheckerContext & C) const1297 void MallocChecker::checkAlloca(const CallEvent &Call,
1298 CheckerContext &C) const {
1299 ProgramStateRef State = C.getState();
1300 State = MallocMemAux(C, Call, Call.getArgExpr(0), UndefinedVal(), State,
1301 AF_Alloca);
1302 State = ProcessZeroAllocCheck(Call, 0, State);
1303 C.addTransition(State);
1304 }
1305
checkStrdup(const CallEvent & Call,CheckerContext & C) const1306 void MallocChecker::checkStrdup(const CallEvent &Call,
1307 CheckerContext &C) const {
1308 ProgramStateRef State = C.getState();
1309 const auto *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
1310 if (!CE)
1311 return;
1312 State = MallocUpdateRefState(C, CE, State, AF_Malloc);
1313
1314 C.addTransition(State);
1315 }
1316
checkIfNameIndex(const CallEvent & Call,CheckerContext & C) const1317 void MallocChecker::checkIfNameIndex(const CallEvent &Call,
1318 CheckerContext &C) const {
1319 ProgramStateRef State = C.getState();
1320 // Should we model this differently? We can allocate a fixed number of
1321 // elements with zeros in the last one.
1322 State =
1323 MallocMemAux(C, Call, UnknownVal(), UnknownVal(), State, AF_IfNameIndex);
1324
1325 C.addTransition(State);
1326 }
1327
checkIfFreeNameIndex(const CallEvent & Call,CheckerContext & C) const1328 void MallocChecker::checkIfFreeNameIndex(const CallEvent &Call,
1329 CheckerContext &C) const {
1330 ProgramStateRef State = C.getState();
1331 bool IsKnownToBeAllocatedMemory = false;
1332 State = FreeMemAux(C, Call, State, 0, false, IsKnownToBeAllocatedMemory,
1333 AF_IfNameIndex);
1334 C.addTransition(State);
1335 }
1336
checkCXXNewOrCXXDelete(const CallEvent & Call,CheckerContext & C) const1337 void MallocChecker::checkCXXNewOrCXXDelete(const CallEvent &Call,
1338 CheckerContext &C) const {
1339 ProgramStateRef State = C.getState();
1340 bool IsKnownToBeAllocatedMemory = false;
1341 const auto *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
1342 if (!CE)
1343 return;
1344
1345 assert(isStandardNewDelete(Call));
1346
1347 // Process direct calls to operator new/new[]/delete/delete[] functions
1348 // as distinct from new/new[]/delete/delete[] expressions that are
1349 // processed by the checkPostStmt callbacks for CXXNewExpr and
1350 // CXXDeleteExpr.
1351 const FunctionDecl *FD = C.getCalleeDecl(CE);
1352 switch (FD->getOverloadedOperator()) {
1353 case OO_New:
1354 State =
1355 MallocMemAux(C, Call, CE->getArg(0), UndefinedVal(), State, AF_CXXNew);
1356 State = ProcessZeroAllocCheck(Call, 0, State);
1357 break;
1358 case OO_Array_New:
1359 State = MallocMemAux(C, Call, CE->getArg(0), UndefinedVal(), State,
1360 AF_CXXNewArray);
1361 State = ProcessZeroAllocCheck(Call, 0, State);
1362 break;
1363 case OO_Delete:
1364 State = FreeMemAux(C, Call, State, 0, false, IsKnownToBeAllocatedMemory,
1365 AF_CXXNew);
1366 break;
1367 case OO_Array_Delete:
1368 State = FreeMemAux(C, Call, State, 0, false, IsKnownToBeAllocatedMemory,
1369 AF_CXXNewArray);
1370 break;
1371 default:
1372 llvm_unreachable("not a new/delete operator");
1373 }
1374
1375 C.addTransition(State);
1376 }
1377
checkGMalloc0(const CallEvent & Call,CheckerContext & C) const1378 void MallocChecker::checkGMalloc0(const CallEvent &Call,
1379 CheckerContext &C) const {
1380 ProgramStateRef State = C.getState();
1381 SValBuilder &svalBuilder = C.getSValBuilder();
1382 SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
1383 State = MallocMemAux(C, Call, Call.getArgExpr(0), zeroVal, State, AF_Malloc);
1384 State = ProcessZeroAllocCheck(Call, 0, State);
1385 C.addTransition(State);
1386 }
1387
checkGMemdup(const CallEvent & Call,CheckerContext & C) const1388 void MallocChecker::checkGMemdup(const CallEvent &Call,
1389 CheckerContext &C) const {
1390 ProgramStateRef State = C.getState();
1391 State =
1392 MallocMemAux(C, Call, Call.getArgExpr(1), UnknownVal(), State, AF_Malloc);
1393 State = ProcessZeroAllocCheck(Call, 1, State);
1394 C.addTransition(State);
1395 }
1396
checkGMallocN(const CallEvent & Call,CheckerContext & C) const1397 void MallocChecker::checkGMallocN(const CallEvent &Call,
1398 CheckerContext &C) const {
1399 ProgramStateRef State = C.getState();
1400 SVal Init = UndefinedVal();
1401 SVal TotalSize = evalMulForBufferSize(C, Call.getArgExpr(0), Call.getArgExpr(1));
1402 State = MallocMemAux(C, Call, TotalSize, Init, State, AF_Malloc);
1403 State = ProcessZeroAllocCheck(Call, 0, State);
1404 State = ProcessZeroAllocCheck(Call, 1, State);
1405 C.addTransition(State);
1406 }
1407
checkGMallocN0(const CallEvent & Call,CheckerContext & C) const1408 void MallocChecker::checkGMallocN0(const CallEvent &Call,
1409 CheckerContext &C) const {
1410 ProgramStateRef State = C.getState();
1411 SValBuilder &SB = C.getSValBuilder();
1412 SVal Init = SB.makeZeroVal(SB.getContext().CharTy);
1413 SVal TotalSize = evalMulForBufferSize(C, Call.getArgExpr(0), Call.getArgExpr(1));
1414 State = MallocMemAux(C, Call, TotalSize, Init, State, AF_Malloc);
1415 State = ProcessZeroAllocCheck(Call, 0, State);
1416 State = ProcessZeroAllocCheck(Call, 1, State);
1417 C.addTransition(State);
1418 }
1419
checkReallocN(const CallEvent & Call,CheckerContext & C) const1420 void MallocChecker::checkReallocN(const CallEvent &Call,
1421 CheckerContext &C) const {
1422 ProgramStateRef State = C.getState();
1423 State = ReallocMemAux(C, Call, /*ShouldFreeOnFail=*/false, State, AF_Malloc,
1424 /*SuffixWithN=*/true);
1425 State = ProcessZeroAllocCheck(Call, 1, State);
1426 State = ProcessZeroAllocCheck(Call, 2, State);
1427 C.addTransition(State);
1428 }
1429
checkOwnershipAttr(const CallEvent & Call,CheckerContext & C) const1430 void MallocChecker::checkOwnershipAttr(const CallEvent &Call,
1431 CheckerContext &C) const {
1432 ProgramStateRef State = C.getState();
1433 const auto *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
1434 if (!CE)
1435 return;
1436 const FunctionDecl *FD = C.getCalleeDecl(CE);
1437 if (!FD)
1438 return;
1439 if (ShouldIncludeOwnershipAnnotatedFunctions ||
1440 ChecksEnabled[CK_MismatchedDeallocatorChecker]) {
1441 // Check all the attributes, if there are any.
1442 // There can be multiple of these attributes.
1443 if (FD->hasAttrs())
1444 for (const auto *I : FD->specific_attrs<OwnershipAttr>()) {
1445 switch (I->getOwnKind()) {
1446 case OwnershipAttr::Returns:
1447 State = MallocMemReturnsAttr(C, Call, I, State);
1448 break;
1449 case OwnershipAttr::Takes:
1450 case OwnershipAttr::Holds:
1451 State = FreeMemAttr(C, Call, I, State);
1452 break;
1453 }
1454 }
1455 }
1456 C.addTransition(State);
1457 }
1458
checkPostCall(const CallEvent & Call,CheckerContext & C) const1459 void MallocChecker::checkPostCall(const CallEvent &Call,
1460 CheckerContext &C) const {
1461 if (C.wasInlined)
1462 return;
1463 if (!Call.getOriginExpr())
1464 return;
1465
1466 ProgramStateRef State = C.getState();
1467
1468 if (const CheckFn *Callback = FreeingMemFnMap.lookup(Call)) {
1469 (*Callback)(this, Call, C);
1470 return;
1471 }
1472
1473 if (const CheckFn *Callback = AllocatingMemFnMap.lookup(Call)) {
1474 (*Callback)(this, Call, C);
1475 return;
1476 }
1477
1478 if (const CheckFn *Callback = ReallocatingMemFnMap.lookup(Call)) {
1479 (*Callback)(this, Call, C);
1480 return;
1481 }
1482
1483 if (isStandardNewDelete(Call)) {
1484 checkCXXNewOrCXXDelete(Call, C);
1485 return;
1486 }
1487
1488 checkOwnershipAttr(Call, C);
1489 }
1490
1491 // Performs a 0-sized allocations check.
ProcessZeroAllocCheck(const CallEvent & Call,const unsigned IndexOfSizeArg,ProgramStateRef State,std::optional<SVal> RetVal)1492 ProgramStateRef MallocChecker::ProcessZeroAllocCheck(
1493 const CallEvent &Call, const unsigned IndexOfSizeArg, ProgramStateRef State,
1494 std::optional<SVal> RetVal) {
1495 if (!State)
1496 return nullptr;
1497
1498 if (!RetVal)
1499 RetVal = Call.getReturnValue();
1500
1501 const Expr *Arg = nullptr;
1502
1503 if (const CallExpr *CE = dyn_cast<CallExpr>(Call.getOriginExpr())) {
1504 Arg = CE->getArg(IndexOfSizeArg);
1505 } else if (const CXXNewExpr *NE =
1506 dyn_cast<CXXNewExpr>(Call.getOriginExpr())) {
1507 if (NE->isArray()) {
1508 Arg = *NE->getArraySize();
1509 } else {
1510 return State;
1511 }
1512 } else
1513 llvm_unreachable("not a CallExpr or CXXNewExpr");
1514
1515 assert(Arg);
1516
1517 auto DefArgVal =
1518 State->getSVal(Arg, Call.getLocationContext()).getAs<DefinedSVal>();
1519
1520 if (!DefArgVal)
1521 return State;
1522
1523 // Check if the allocation size is 0.
1524 ProgramStateRef TrueState, FalseState;
1525 SValBuilder &SvalBuilder = State->getStateManager().getSValBuilder();
1526 DefinedSVal Zero =
1527 SvalBuilder.makeZeroVal(Arg->getType()).castAs<DefinedSVal>();
1528
1529 std::tie(TrueState, FalseState) =
1530 State->assume(SvalBuilder.evalEQ(State, *DefArgVal, Zero));
1531
1532 if (TrueState && !FalseState) {
1533 SymbolRef Sym = RetVal->getAsLocSymbol();
1534 if (!Sym)
1535 return State;
1536
1537 const RefState *RS = State->get<RegionState>(Sym);
1538 if (RS) {
1539 if (RS->isAllocated())
1540 return TrueState->set<RegionState>(Sym,
1541 RefState::getAllocatedOfSizeZero(RS));
1542 else
1543 return State;
1544 } else {
1545 // Case of zero-size realloc. Historically 'realloc(ptr, 0)' is treated as
1546 // 'free(ptr)' and the returned value from 'realloc(ptr, 0)' is not
1547 // tracked. Add zero-reallocated Sym to the state to catch references
1548 // to zero-allocated memory.
1549 return TrueState->add<ReallocSizeZeroSymbols>(Sym);
1550 }
1551 }
1552
1553 // Assume the value is non-zero going forward.
1554 assert(FalseState);
1555 return FalseState;
1556 }
1557
getDeepPointeeType(QualType T)1558 static QualType getDeepPointeeType(QualType T) {
1559 QualType Result = T, PointeeType = T->getPointeeType();
1560 while (!PointeeType.isNull()) {
1561 Result = PointeeType;
1562 PointeeType = PointeeType->getPointeeType();
1563 }
1564 return Result;
1565 }
1566
1567 /// \returns true if the constructor invoked by \p NE has an argument of a
1568 /// pointer/reference to a record type.
hasNonTrivialConstructorCall(const CXXNewExpr * NE)1569 static bool hasNonTrivialConstructorCall(const CXXNewExpr *NE) {
1570
1571 const CXXConstructExpr *ConstructE = NE->getConstructExpr();
1572 if (!ConstructE)
1573 return false;
1574
1575 if (!NE->getAllocatedType()->getAsCXXRecordDecl())
1576 return false;
1577
1578 const CXXConstructorDecl *CtorD = ConstructE->getConstructor();
1579
1580 // Iterate over the constructor parameters.
1581 for (const auto *CtorParam : CtorD->parameters()) {
1582
1583 QualType CtorParamPointeeT = CtorParam->getType()->getPointeeType();
1584 if (CtorParamPointeeT.isNull())
1585 continue;
1586
1587 CtorParamPointeeT = getDeepPointeeType(CtorParamPointeeT);
1588
1589 if (CtorParamPointeeT->getAsCXXRecordDecl())
1590 return true;
1591 }
1592
1593 return false;
1594 }
1595
1596 ProgramStateRef
processNewAllocation(const CXXAllocatorCall & Call,CheckerContext & C,AllocationFamily Family) const1597 MallocChecker::processNewAllocation(const CXXAllocatorCall &Call,
1598 CheckerContext &C,
1599 AllocationFamily Family) const {
1600 if (!isStandardNewDelete(Call))
1601 return nullptr;
1602
1603 const CXXNewExpr *NE = Call.getOriginExpr();
1604 const ParentMap &PM = C.getLocationContext()->getParentMap();
1605 ProgramStateRef State = C.getState();
1606
1607 // Non-trivial constructors have a chance to escape 'this', but marking all
1608 // invocations of trivial constructors as escaped would cause too great of
1609 // reduction of true positives, so let's just do that for constructors that
1610 // have an argument of a pointer-to-record type.
1611 if (!PM.isConsumedExpr(NE) && hasNonTrivialConstructorCall(NE))
1612 return State;
1613
1614 // The return value from operator new is bound to a specified initialization
1615 // value (if any) and we don't want to loose this value. So we call
1616 // MallocUpdateRefState() instead of MallocMemAux() which breaks the
1617 // existing binding.
1618 SVal Target = Call.getObjectUnderConstruction();
1619 State = MallocUpdateRefState(C, NE, State, Family, Target);
1620 State = ProcessZeroAllocCheck(Call, 0, State, Target);
1621 return State;
1622 }
1623
checkNewAllocator(const CXXAllocatorCall & Call,CheckerContext & C) const1624 void MallocChecker::checkNewAllocator(const CXXAllocatorCall &Call,
1625 CheckerContext &C) const {
1626 if (!C.wasInlined) {
1627 ProgramStateRef State = processNewAllocation(
1628 Call, C,
1629 (Call.getOriginExpr()->isArray() ? AF_CXXNewArray : AF_CXXNew));
1630 C.addTransition(State);
1631 }
1632 }
1633
isKnownDeallocObjCMethodName(const ObjCMethodCall & Call)1634 static bool isKnownDeallocObjCMethodName(const ObjCMethodCall &Call) {
1635 // If the first selector piece is one of the names below, assume that the
1636 // object takes ownership of the memory, promising to eventually deallocate it
1637 // with free().
1638 // Ex: [NSData dataWithBytesNoCopy:bytes length:10];
1639 // (...unless a 'freeWhenDone' parameter is false, but that's checked later.)
1640 StringRef FirstSlot = Call.getSelector().getNameForSlot(0);
1641 return FirstSlot == "dataWithBytesNoCopy" ||
1642 FirstSlot == "initWithBytesNoCopy" ||
1643 FirstSlot == "initWithCharactersNoCopy";
1644 }
1645
getFreeWhenDoneArg(const ObjCMethodCall & Call)1646 static std::optional<bool> getFreeWhenDoneArg(const ObjCMethodCall &Call) {
1647 Selector S = Call.getSelector();
1648
1649 // FIXME: We should not rely on fully-constrained symbols being folded.
1650 for (unsigned i = 1; i < S.getNumArgs(); ++i)
1651 if (S.getNameForSlot(i).equals("freeWhenDone"))
1652 return !Call.getArgSVal(i).isZeroConstant();
1653
1654 return std::nullopt;
1655 }
1656
checkPostObjCMessage(const ObjCMethodCall & Call,CheckerContext & C) const1657 void MallocChecker::checkPostObjCMessage(const ObjCMethodCall &Call,
1658 CheckerContext &C) const {
1659 if (C.wasInlined)
1660 return;
1661
1662 if (!isKnownDeallocObjCMethodName(Call))
1663 return;
1664
1665 if (std::optional<bool> FreeWhenDone = getFreeWhenDoneArg(Call))
1666 if (!*FreeWhenDone)
1667 return;
1668
1669 if (Call.hasNonZeroCallbackArg())
1670 return;
1671
1672 bool IsKnownToBeAllocatedMemory;
1673 ProgramStateRef State =
1674 FreeMemAux(C, Call.getArgExpr(0), Call, C.getState(),
1675 /*Hold=*/true, IsKnownToBeAllocatedMemory, AF_Malloc,
1676 /*ReturnsNullOnFailure=*/true);
1677
1678 C.addTransition(State);
1679 }
1680
1681 ProgramStateRef
MallocMemReturnsAttr(CheckerContext & C,const CallEvent & Call,const OwnershipAttr * Att,ProgramStateRef State) const1682 MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallEvent &Call,
1683 const OwnershipAttr *Att,
1684 ProgramStateRef State) const {
1685 if (!State)
1686 return nullptr;
1687
1688 if (Att->getModule()->getName() != "malloc")
1689 return nullptr;
1690
1691 OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
1692 if (I != E) {
1693 return MallocMemAux(C, Call, Call.getArgExpr(I->getASTIndex()),
1694 UndefinedVal(), State, AF_Malloc);
1695 }
1696 return MallocMemAux(C, Call, UnknownVal(), UndefinedVal(), State, AF_Malloc);
1697 }
1698
MallocMemAux(CheckerContext & C,const CallEvent & Call,const Expr * SizeEx,SVal Init,ProgramStateRef State,AllocationFamily Family)1699 ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
1700 const CallEvent &Call,
1701 const Expr *SizeEx, SVal Init,
1702 ProgramStateRef State,
1703 AllocationFamily Family) {
1704 if (!State)
1705 return nullptr;
1706
1707 assert(SizeEx);
1708 return MallocMemAux(C, Call, C.getSVal(SizeEx), Init, State, Family);
1709 }
1710
MallocMemAux(CheckerContext & C,const CallEvent & Call,SVal Size,SVal Init,ProgramStateRef State,AllocationFamily Family)1711 ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
1712 const CallEvent &Call, SVal Size,
1713 SVal Init, ProgramStateRef State,
1714 AllocationFamily Family) {
1715 if (!State)
1716 return nullptr;
1717
1718 const Expr *CE = Call.getOriginExpr();
1719
1720 // We expect the malloc functions to return a pointer.
1721 if (!Loc::isLocType(CE->getType()))
1722 return nullptr;
1723
1724 // Bind the return value to the symbolic value from the heap region.
1725 // TODO: We could rewrite post visit to eval call; 'malloc' does not have
1726 // side effects other than what we model here.
1727 unsigned Count = C.blockCount();
1728 SValBuilder &svalBuilder = C.getSValBuilder();
1729 const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
1730 DefinedSVal RetVal = svalBuilder.getConjuredHeapSymbolVal(CE, LCtx, Count)
1731 .castAs<DefinedSVal>();
1732 State = State->BindExpr(CE, C.getLocationContext(), RetVal);
1733
1734 // Fill the region with the initialization value.
1735 State = State->bindDefaultInitial(RetVal, Init, LCtx);
1736
1737 // If Size is somehow undefined at this point, this line prevents a crash.
1738 if (Size.isUndef())
1739 Size = UnknownVal();
1740
1741 // Set the region's extent.
1742 State = setDynamicExtent(State, RetVal.getAsRegion(),
1743 Size.castAs<DefinedOrUnknownSVal>(), svalBuilder);
1744
1745 return MallocUpdateRefState(C, CE, State, Family);
1746 }
1747
MallocUpdateRefState(CheckerContext & C,const Expr * E,ProgramStateRef State,AllocationFamily Family,std::optional<SVal> RetVal)1748 static ProgramStateRef MallocUpdateRefState(CheckerContext &C, const Expr *E,
1749 ProgramStateRef State,
1750 AllocationFamily Family,
1751 std::optional<SVal> RetVal) {
1752 if (!State)
1753 return nullptr;
1754
1755 // Get the return value.
1756 if (!RetVal)
1757 RetVal = C.getSVal(E);
1758
1759 // We expect the malloc functions to return a pointer.
1760 if (!RetVal->getAs<Loc>())
1761 return nullptr;
1762
1763 SymbolRef Sym = RetVal->getAsLocSymbol();
1764 // This is a return value of a function that was not inlined, such as malloc()
1765 // or new(). We've checked that in the caller. Therefore, it must be a symbol.
1766 assert(Sym);
1767
1768 // Set the symbol's state to Allocated.
1769 return State->set<RegionState>(Sym, RefState::getAllocated(Family, E));
1770 }
1771
FreeMemAttr(CheckerContext & C,const CallEvent & Call,const OwnershipAttr * Att,ProgramStateRef State) const1772 ProgramStateRef MallocChecker::FreeMemAttr(CheckerContext &C,
1773 const CallEvent &Call,
1774 const OwnershipAttr *Att,
1775 ProgramStateRef State) const {
1776 if (!State)
1777 return nullptr;
1778
1779 if (Att->getModule()->getName() != "malloc")
1780 return nullptr;
1781
1782 bool IsKnownToBeAllocated = false;
1783
1784 for (const auto &Arg : Att->args()) {
1785 ProgramStateRef StateI =
1786 FreeMemAux(C, Call, State, Arg.getASTIndex(),
1787 Att->getOwnKind() == OwnershipAttr::Holds,
1788 IsKnownToBeAllocated, AF_Malloc);
1789 if (StateI)
1790 State = StateI;
1791 }
1792 return State;
1793 }
1794
FreeMemAux(CheckerContext & C,const CallEvent & Call,ProgramStateRef State,unsigned Num,bool Hold,bool & IsKnownToBeAllocated,AllocationFamily Family,bool ReturnsNullOnFailure) const1795 ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
1796 const CallEvent &Call,
1797 ProgramStateRef State, unsigned Num,
1798 bool Hold, bool &IsKnownToBeAllocated,
1799 AllocationFamily Family,
1800 bool ReturnsNullOnFailure) const {
1801 if (!State)
1802 return nullptr;
1803
1804 if (Call.getNumArgs() < (Num + 1))
1805 return nullptr;
1806
1807 return FreeMemAux(C, Call.getArgExpr(Num), Call, State, Hold,
1808 IsKnownToBeAllocated, Family, ReturnsNullOnFailure);
1809 }
1810
1811 /// Checks if the previous call to free on the given symbol failed - if free
1812 /// failed, returns true. Also, returns the corresponding return value symbol.
didPreviousFreeFail(ProgramStateRef State,SymbolRef Sym,SymbolRef & RetStatusSymbol)1813 static bool didPreviousFreeFail(ProgramStateRef State,
1814 SymbolRef Sym, SymbolRef &RetStatusSymbol) {
1815 const SymbolRef *Ret = State->get<FreeReturnValue>(Sym);
1816 if (Ret) {
1817 assert(*Ret && "We should not store the null return symbol");
1818 ConstraintManager &CMgr = State->getConstraintManager();
1819 ConditionTruthVal FreeFailed = CMgr.isNull(State, *Ret);
1820 RetStatusSymbol = *Ret;
1821 return FreeFailed.isConstrainedTrue();
1822 }
1823 return false;
1824 }
1825
printMemFnName(raw_ostream & os,CheckerContext & C,const Expr * E)1826 static bool printMemFnName(raw_ostream &os, CheckerContext &C, const Expr *E) {
1827 if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
1828 // FIXME: This doesn't handle indirect calls.
1829 const FunctionDecl *FD = CE->getDirectCallee();
1830 if (!FD)
1831 return false;
1832
1833 os << *FD;
1834 if (!FD->isOverloadedOperator())
1835 os << "()";
1836 return true;
1837 }
1838
1839 if (const ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E)) {
1840 if (Msg->isInstanceMessage())
1841 os << "-";
1842 else
1843 os << "+";
1844 Msg->getSelector().print(os);
1845 return true;
1846 }
1847
1848 if (const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(E)) {
1849 os << "'"
1850 << getOperatorSpelling(NE->getOperatorNew()->getOverloadedOperator())
1851 << "'";
1852 return true;
1853 }
1854
1855 if (const CXXDeleteExpr *DE = dyn_cast<CXXDeleteExpr>(E)) {
1856 os << "'"
1857 << getOperatorSpelling(DE->getOperatorDelete()->getOverloadedOperator())
1858 << "'";
1859 return true;
1860 }
1861
1862 return false;
1863 }
1864
printExpectedAllocName(raw_ostream & os,AllocationFamily Family)1865 static void printExpectedAllocName(raw_ostream &os, AllocationFamily Family) {
1866
1867 switch(Family) {
1868 case AF_Malloc: os << "malloc()"; return;
1869 case AF_CXXNew: os << "'new'"; return;
1870 case AF_CXXNewArray: os << "'new[]'"; return;
1871 case AF_IfNameIndex: os << "'if_nameindex()'"; return;
1872 case AF_InnerBuffer: os << "container-specific allocator"; return;
1873 case AF_Alloca:
1874 case AF_None: llvm_unreachable("not a deallocation expression");
1875 }
1876 }
1877
printExpectedDeallocName(raw_ostream & os,AllocationFamily Family)1878 static void printExpectedDeallocName(raw_ostream &os, AllocationFamily Family) {
1879 switch(Family) {
1880 case AF_Malloc: os << "free()"; return;
1881 case AF_CXXNew: os << "'delete'"; return;
1882 case AF_CXXNewArray: os << "'delete[]'"; return;
1883 case AF_IfNameIndex: os << "'if_freenameindex()'"; return;
1884 case AF_InnerBuffer: os << "container-specific deallocator"; return;
1885 case AF_Alloca:
1886 case AF_None: llvm_unreachable("suspicious argument");
1887 }
1888 }
1889
FreeMemAux(CheckerContext & C,const Expr * ArgExpr,const CallEvent & Call,ProgramStateRef State,bool Hold,bool & IsKnownToBeAllocated,AllocationFamily Family,bool ReturnsNullOnFailure) const1890 ProgramStateRef MallocChecker::FreeMemAux(
1891 CheckerContext &C, const Expr *ArgExpr, const CallEvent &Call,
1892 ProgramStateRef State, bool Hold, bool &IsKnownToBeAllocated,
1893 AllocationFamily Family, bool ReturnsNullOnFailure) const {
1894
1895 if (!State)
1896 return nullptr;
1897
1898 SVal ArgVal = C.getSVal(ArgExpr);
1899 if (!isa<DefinedOrUnknownSVal>(ArgVal))
1900 return nullptr;
1901 DefinedOrUnknownSVal location = ArgVal.castAs<DefinedOrUnknownSVal>();
1902
1903 // Check for null dereferences.
1904 if (!isa<Loc>(location))
1905 return nullptr;
1906
1907 // The explicit NULL case, no operation is performed.
1908 ProgramStateRef notNullState, nullState;
1909 std::tie(notNullState, nullState) = State->assume(location);
1910 if (nullState && !notNullState)
1911 return nullptr;
1912
1913 // Unknown values could easily be okay
1914 // Undefined values are handled elsewhere
1915 if (ArgVal.isUnknownOrUndef())
1916 return nullptr;
1917
1918 const MemRegion *R = ArgVal.getAsRegion();
1919 const Expr *ParentExpr = Call.getOriginExpr();
1920
1921 // NOTE: We detected a bug, but the checker under whose name we would emit the
1922 // error could be disabled. Generally speaking, the MallocChecker family is an
1923 // integral part of the Static Analyzer, and disabling any part of it should
1924 // only be done under exceptional circumstances, such as frequent false
1925 // positives. If this is the case, we can reasonably believe that there are
1926 // serious faults in our understanding of the source code, and even if we
1927 // don't emit an warning, we should terminate further analysis with a sink
1928 // node.
1929
1930 // Nonlocs can't be freed, of course.
1931 // Non-region locations (labels and fixed addresses) also shouldn't be freed.
1932 if (!R) {
1933 // Exception:
1934 // If the macro ZERO_SIZE_PTR is defined, this could be a kernel source
1935 // code. In that case, the ZERO_SIZE_PTR defines a special value used for a
1936 // zero-sized memory block which is allowed to be freed, despite not being a
1937 // null pointer.
1938 if (Family != AF_Malloc || !isArgZERO_SIZE_PTR(State, C, ArgVal))
1939 HandleNonHeapDealloc(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr,
1940 Family);
1941 return nullptr;
1942 }
1943
1944 R = R->StripCasts();
1945
1946 // Blocks might show up as heap data, but should not be free()d
1947 if (isa<BlockDataRegion>(R)) {
1948 HandleNonHeapDealloc(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr,
1949 Family);
1950 return nullptr;
1951 }
1952
1953 const MemSpaceRegion *MS = R->getMemorySpace();
1954
1955 // Parameters, locals, statics, globals, and memory returned by
1956 // __builtin_alloca() shouldn't be freed.
1957 if (!isa<UnknownSpaceRegion, HeapSpaceRegion>(MS)) {
1958 // FIXME: at the time this code was written, malloc() regions were
1959 // represented by conjured symbols, which are all in UnknownSpaceRegion.
1960 // This means that there isn't actually anything from HeapSpaceRegion
1961 // that should be freed, even though we allow it here.
1962 // Of course, free() can work on memory allocated outside the current
1963 // function, so UnknownSpaceRegion is always a possibility.
1964 // False negatives are better than false positives.
1965
1966 if (isa<AllocaRegion>(R))
1967 HandleFreeAlloca(C, ArgVal, ArgExpr->getSourceRange());
1968 else
1969 HandleNonHeapDealloc(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr,
1970 Family);
1971
1972 return nullptr;
1973 }
1974
1975 const SymbolicRegion *SrBase = dyn_cast<SymbolicRegion>(R->getBaseRegion());
1976 // Various cases could lead to non-symbol values here.
1977 // For now, ignore them.
1978 if (!SrBase)
1979 return nullptr;
1980
1981 SymbolRef SymBase = SrBase->getSymbol();
1982 const RefState *RsBase = State->get<RegionState>(SymBase);
1983 SymbolRef PreviousRetStatusSymbol = nullptr;
1984
1985 IsKnownToBeAllocated =
1986 RsBase && (RsBase->isAllocated() || RsBase->isAllocatedOfSizeZero());
1987
1988 if (RsBase) {
1989
1990 // Memory returned by alloca() shouldn't be freed.
1991 if (RsBase->getAllocationFamily() == AF_Alloca) {
1992 HandleFreeAlloca(C, ArgVal, ArgExpr->getSourceRange());
1993 return nullptr;
1994 }
1995
1996 // Check for double free first.
1997 if ((RsBase->isReleased() || RsBase->isRelinquished()) &&
1998 !didPreviousFreeFail(State, SymBase, PreviousRetStatusSymbol)) {
1999 HandleDoubleFree(C, ParentExpr->getSourceRange(), RsBase->isReleased(),
2000 SymBase, PreviousRetStatusSymbol);
2001 return nullptr;
2002
2003 // If the pointer is allocated or escaped, but we are now trying to free it,
2004 // check that the call to free is proper.
2005 } else if (RsBase->isAllocated() || RsBase->isAllocatedOfSizeZero() ||
2006 RsBase->isEscaped()) {
2007
2008 // Check if an expected deallocation function matches the real one.
2009 bool DeallocMatchesAlloc = RsBase->getAllocationFamily() == Family;
2010 if (!DeallocMatchesAlloc) {
2011 HandleMismatchedDealloc(C, ArgExpr->getSourceRange(), ParentExpr,
2012 RsBase, SymBase, Hold);
2013 return nullptr;
2014 }
2015
2016 // Check if the memory location being freed is the actual location
2017 // allocated, or an offset.
2018 RegionOffset Offset = R->getAsOffset();
2019 if (Offset.isValid() &&
2020 !Offset.hasSymbolicOffset() &&
2021 Offset.getOffset() != 0) {
2022 const Expr *AllocExpr = cast<Expr>(RsBase->getStmt());
2023 HandleOffsetFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr,
2024 Family, AllocExpr);
2025 return nullptr;
2026 }
2027 }
2028 }
2029
2030 if (SymBase->getType()->isFunctionPointerType()) {
2031 HandleFunctionPtrFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr,
2032 Family);
2033 return nullptr;
2034 }
2035
2036 // Clean out the info on previous call to free return info.
2037 State = State->remove<FreeReturnValue>(SymBase);
2038
2039 // Keep track of the return value. If it is NULL, we will know that free
2040 // failed.
2041 if (ReturnsNullOnFailure) {
2042 SVal RetVal = C.getSVal(ParentExpr);
2043 SymbolRef RetStatusSymbol = RetVal.getAsSymbol();
2044 if (RetStatusSymbol) {
2045 C.getSymbolManager().addSymbolDependency(SymBase, RetStatusSymbol);
2046 State = State->set<FreeReturnValue>(SymBase, RetStatusSymbol);
2047 }
2048 }
2049
2050 // If we don't know anything about this symbol, a free on it may be totally
2051 // valid. If this is the case, lets assume that the allocation family of the
2052 // freeing function is the same as the symbols allocation family, and go with
2053 // that.
2054 assert(!RsBase || (RsBase && RsBase->getAllocationFamily() == Family));
2055
2056 // Normal free.
2057 if (Hold)
2058 return State->set<RegionState>(SymBase,
2059 RefState::getRelinquished(Family,
2060 ParentExpr));
2061
2062 return State->set<RegionState>(SymBase,
2063 RefState::getReleased(Family, ParentExpr));
2064 }
2065
2066 std::optional<MallocChecker::CheckKind>
getCheckIfTracked(AllocationFamily Family,bool IsALeakCheck) const2067 MallocChecker::getCheckIfTracked(AllocationFamily Family,
2068 bool IsALeakCheck) const {
2069 switch (Family) {
2070 case AF_Malloc:
2071 case AF_Alloca:
2072 case AF_IfNameIndex: {
2073 if (ChecksEnabled[CK_MallocChecker])
2074 return CK_MallocChecker;
2075 return std::nullopt;
2076 }
2077 case AF_CXXNew:
2078 case AF_CXXNewArray: {
2079 if (IsALeakCheck) {
2080 if (ChecksEnabled[CK_NewDeleteLeaksChecker])
2081 return CK_NewDeleteLeaksChecker;
2082 }
2083 else {
2084 if (ChecksEnabled[CK_NewDeleteChecker])
2085 return CK_NewDeleteChecker;
2086 }
2087 return std::nullopt;
2088 }
2089 case AF_InnerBuffer: {
2090 if (ChecksEnabled[CK_InnerPointerChecker])
2091 return CK_InnerPointerChecker;
2092 return std::nullopt;
2093 }
2094 case AF_None: {
2095 llvm_unreachable("no family");
2096 }
2097 }
2098 llvm_unreachable("unhandled family");
2099 }
2100
2101 std::optional<MallocChecker::CheckKind>
getCheckIfTracked(CheckerContext & C,SymbolRef Sym,bool IsALeakCheck) const2102 MallocChecker::getCheckIfTracked(CheckerContext &C, SymbolRef Sym,
2103 bool IsALeakCheck) const {
2104 if (C.getState()->contains<ReallocSizeZeroSymbols>(Sym))
2105 return CK_MallocChecker;
2106
2107 const RefState *RS = C.getState()->get<RegionState>(Sym);
2108 assert(RS);
2109 return getCheckIfTracked(RS->getAllocationFamily(), IsALeakCheck);
2110 }
2111
SummarizeValue(raw_ostream & os,SVal V)2112 bool MallocChecker::SummarizeValue(raw_ostream &os, SVal V) {
2113 if (std::optional<nonloc::ConcreteInt> IntVal =
2114 V.getAs<nonloc::ConcreteInt>())
2115 os << "an integer (" << IntVal->getValue() << ")";
2116 else if (std::optional<loc::ConcreteInt> ConstAddr =
2117 V.getAs<loc::ConcreteInt>())
2118 os << "a constant address (" << ConstAddr->getValue() << ")";
2119 else if (std::optional<loc::GotoLabel> Label = V.getAs<loc::GotoLabel>())
2120 os << "the address of the label '" << Label->getLabel()->getName() << "'";
2121 else
2122 return false;
2123
2124 return true;
2125 }
2126
SummarizeRegion(raw_ostream & os,const MemRegion * MR)2127 bool MallocChecker::SummarizeRegion(raw_ostream &os,
2128 const MemRegion *MR) {
2129 switch (MR->getKind()) {
2130 case MemRegion::FunctionCodeRegionKind: {
2131 const NamedDecl *FD = cast<FunctionCodeRegion>(MR)->getDecl();
2132 if (FD)
2133 os << "the address of the function '" << *FD << '\'';
2134 else
2135 os << "the address of a function";
2136 return true;
2137 }
2138 case MemRegion::BlockCodeRegionKind:
2139 os << "block text";
2140 return true;
2141 case MemRegion::BlockDataRegionKind:
2142 // FIXME: where the block came from?
2143 os << "a block";
2144 return true;
2145 default: {
2146 const MemSpaceRegion *MS = MR->getMemorySpace();
2147
2148 if (isa<StackLocalsSpaceRegion>(MS)) {
2149 const VarRegion *VR = dyn_cast<VarRegion>(MR);
2150 const VarDecl *VD;
2151 if (VR)
2152 VD = VR->getDecl();
2153 else
2154 VD = nullptr;
2155
2156 if (VD)
2157 os << "the address of the local variable '" << VD->getName() << "'";
2158 else
2159 os << "the address of a local stack variable";
2160 return true;
2161 }
2162
2163 if (isa<StackArgumentsSpaceRegion>(MS)) {
2164 const VarRegion *VR = dyn_cast<VarRegion>(MR);
2165 const VarDecl *VD;
2166 if (VR)
2167 VD = VR->getDecl();
2168 else
2169 VD = nullptr;
2170
2171 if (VD)
2172 os << "the address of the parameter '" << VD->getName() << "'";
2173 else
2174 os << "the address of a parameter";
2175 return true;
2176 }
2177
2178 if (isa<GlobalsSpaceRegion>(MS)) {
2179 const VarRegion *VR = dyn_cast<VarRegion>(MR);
2180 const VarDecl *VD;
2181 if (VR)
2182 VD = VR->getDecl();
2183 else
2184 VD = nullptr;
2185
2186 if (VD) {
2187 if (VD->isStaticLocal())
2188 os << "the address of the static variable '" << VD->getName() << "'";
2189 else
2190 os << "the address of the global variable '" << VD->getName() << "'";
2191 } else
2192 os << "the address of a global variable";
2193 return true;
2194 }
2195
2196 return false;
2197 }
2198 }
2199 }
2200
HandleNonHeapDealloc(CheckerContext & C,SVal ArgVal,SourceRange Range,const Expr * DeallocExpr,AllocationFamily Family) const2201 void MallocChecker::HandleNonHeapDealloc(CheckerContext &C, SVal ArgVal,
2202 SourceRange Range,
2203 const Expr *DeallocExpr,
2204 AllocationFamily Family) const {
2205
2206 if (!ChecksEnabled[CK_MallocChecker] && !ChecksEnabled[CK_NewDeleteChecker]) {
2207 C.addSink();
2208 return;
2209 }
2210
2211 std::optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(Family);
2212 if (!CheckKind)
2213 return;
2214
2215 if (ExplodedNode *N = C.generateErrorNode()) {
2216 if (!BT_BadFree[*CheckKind])
2217 BT_BadFree[*CheckKind].reset(new BugType(
2218 CheckNames[*CheckKind], "Bad free", categories::MemoryError));
2219
2220 SmallString<100> buf;
2221 llvm::raw_svector_ostream os(buf);
2222
2223 const MemRegion *MR = ArgVal.getAsRegion();
2224 while (const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(MR))
2225 MR = ER->getSuperRegion();
2226
2227 os << "Argument to ";
2228 if (!printMemFnName(os, C, DeallocExpr))
2229 os << "deallocator";
2230
2231 os << " is ";
2232 bool Summarized = MR ? SummarizeRegion(os, MR)
2233 : SummarizeValue(os, ArgVal);
2234 if (Summarized)
2235 os << ", which is not memory allocated by ";
2236 else
2237 os << "not memory allocated by ";
2238
2239 printExpectedAllocName(os, Family);
2240
2241 auto R = std::make_unique<PathSensitiveBugReport>(*BT_BadFree[*CheckKind],
2242 os.str(), N);
2243 R->markInteresting(MR);
2244 R->addRange(Range);
2245 C.emitReport(std::move(R));
2246 }
2247 }
2248
HandleFreeAlloca(CheckerContext & C,SVal ArgVal,SourceRange Range) const2249 void MallocChecker::HandleFreeAlloca(CheckerContext &C, SVal ArgVal,
2250 SourceRange Range) const {
2251
2252 std::optional<MallocChecker::CheckKind> CheckKind;
2253
2254 if (ChecksEnabled[CK_MallocChecker])
2255 CheckKind = CK_MallocChecker;
2256 else if (ChecksEnabled[CK_MismatchedDeallocatorChecker])
2257 CheckKind = CK_MismatchedDeallocatorChecker;
2258 else {
2259 C.addSink();
2260 return;
2261 }
2262
2263 if (ExplodedNode *N = C.generateErrorNode()) {
2264 if (!BT_FreeAlloca[*CheckKind])
2265 BT_FreeAlloca[*CheckKind].reset(new BugType(
2266 CheckNames[*CheckKind], "Free alloca()", categories::MemoryError));
2267
2268 auto R = std::make_unique<PathSensitiveBugReport>(
2269 *BT_FreeAlloca[*CheckKind],
2270 "Memory allocated by alloca() should not be deallocated", N);
2271 R->markInteresting(ArgVal.getAsRegion());
2272 R->addRange(Range);
2273 C.emitReport(std::move(R));
2274 }
2275 }
2276
HandleMismatchedDealloc(CheckerContext & C,SourceRange Range,const Expr * DeallocExpr,const RefState * RS,SymbolRef Sym,bool OwnershipTransferred) const2277 void MallocChecker::HandleMismatchedDealloc(CheckerContext &C,
2278 SourceRange Range,
2279 const Expr *DeallocExpr,
2280 const RefState *RS, SymbolRef Sym,
2281 bool OwnershipTransferred) const {
2282
2283 if (!ChecksEnabled[CK_MismatchedDeallocatorChecker]) {
2284 C.addSink();
2285 return;
2286 }
2287
2288 if (ExplodedNode *N = C.generateErrorNode()) {
2289 if (!BT_MismatchedDealloc)
2290 BT_MismatchedDealloc.reset(
2291 new BugType(CheckNames[CK_MismatchedDeallocatorChecker],
2292 "Bad deallocator", categories::MemoryError));
2293
2294 SmallString<100> buf;
2295 llvm::raw_svector_ostream os(buf);
2296
2297 const Expr *AllocExpr = cast<Expr>(RS->getStmt());
2298 SmallString<20> AllocBuf;
2299 llvm::raw_svector_ostream AllocOs(AllocBuf);
2300 SmallString<20> DeallocBuf;
2301 llvm::raw_svector_ostream DeallocOs(DeallocBuf);
2302
2303 if (OwnershipTransferred) {
2304 if (printMemFnName(DeallocOs, C, DeallocExpr))
2305 os << DeallocOs.str() << " cannot";
2306 else
2307 os << "Cannot";
2308
2309 os << " take ownership of memory";
2310
2311 if (printMemFnName(AllocOs, C, AllocExpr))
2312 os << " allocated by " << AllocOs.str();
2313 } else {
2314 os << "Memory";
2315 if (printMemFnName(AllocOs, C, AllocExpr))
2316 os << " allocated by " << AllocOs.str();
2317
2318 os << " should be deallocated by ";
2319 printExpectedDeallocName(os, RS->getAllocationFamily());
2320
2321 if (printMemFnName(DeallocOs, C, DeallocExpr))
2322 os << ", not " << DeallocOs.str();
2323 }
2324
2325 auto R = std::make_unique<PathSensitiveBugReport>(*BT_MismatchedDealloc,
2326 os.str(), N);
2327 R->markInteresting(Sym);
2328 R->addRange(Range);
2329 R->addVisitor<MallocBugVisitor>(Sym);
2330 C.emitReport(std::move(R));
2331 }
2332 }
2333
HandleOffsetFree(CheckerContext & C,SVal ArgVal,SourceRange Range,const Expr * DeallocExpr,AllocationFamily Family,const Expr * AllocExpr) const2334 void MallocChecker::HandleOffsetFree(CheckerContext &C, SVal ArgVal,
2335 SourceRange Range, const Expr *DeallocExpr,
2336 AllocationFamily Family,
2337 const Expr *AllocExpr) const {
2338
2339 if (!ChecksEnabled[CK_MallocChecker] && !ChecksEnabled[CK_NewDeleteChecker]) {
2340 C.addSink();
2341 return;
2342 }
2343
2344 std::optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(Family);
2345 if (!CheckKind)
2346 return;
2347
2348 ExplodedNode *N = C.generateErrorNode();
2349 if (!N)
2350 return;
2351
2352 if (!BT_OffsetFree[*CheckKind])
2353 BT_OffsetFree[*CheckKind].reset(new BugType(
2354 CheckNames[*CheckKind], "Offset free", categories::MemoryError));
2355
2356 SmallString<100> buf;
2357 llvm::raw_svector_ostream os(buf);
2358 SmallString<20> AllocNameBuf;
2359 llvm::raw_svector_ostream AllocNameOs(AllocNameBuf);
2360
2361 const MemRegion *MR = ArgVal.getAsRegion();
2362 assert(MR && "Only MemRegion based symbols can have offset free errors");
2363
2364 RegionOffset Offset = MR->getAsOffset();
2365 assert((Offset.isValid() &&
2366 !Offset.hasSymbolicOffset() &&
2367 Offset.getOffset() != 0) &&
2368 "Only symbols with a valid offset can have offset free errors");
2369
2370 int offsetBytes = Offset.getOffset() / C.getASTContext().getCharWidth();
2371
2372 os << "Argument to ";
2373 if (!printMemFnName(os, C, DeallocExpr))
2374 os << "deallocator";
2375 os << " is offset by "
2376 << offsetBytes
2377 << " "
2378 << ((abs(offsetBytes) > 1) ? "bytes" : "byte")
2379 << " from the start of ";
2380 if (AllocExpr && printMemFnName(AllocNameOs, C, AllocExpr))
2381 os << "memory allocated by " << AllocNameOs.str();
2382 else
2383 os << "allocated memory";
2384
2385 auto R = std::make_unique<PathSensitiveBugReport>(*BT_OffsetFree[*CheckKind],
2386 os.str(), N);
2387 R->markInteresting(MR->getBaseRegion());
2388 R->addRange(Range);
2389 C.emitReport(std::move(R));
2390 }
2391
HandleUseAfterFree(CheckerContext & C,SourceRange Range,SymbolRef Sym) const2392 void MallocChecker::HandleUseAfterFree(CheckerContext &C, SourceRange Range,
2393 SymbolRef Sym) const {
2394
2395 if (!ChecksEnabled[CK_MallocChecker] && !ChecksEnabled[CK_NewDeleteChecker] &&
2396 !ChecksEnabled[CK_InnerPointerChecker]) {
2397 C.addSink();
2398 return;
2399 }
2400
2401 std::optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(C, Sym);
2402 if (!CheckKind)
2403 return;
2404
2405 if (ExplodedNode *N = C.generateErrorNode()) {
2406 if (!BT_UseFree[*CheckKind])
2407 BT_UseFree[*CheckKind].reset(new BugType(
2408 CheckNames[*CheckKind], "Use-after-free", categories::MemoryError));
2409
2410 AllocationFamily AF =
2411 C.getState()->get<RegionState>(Sym)->getAllocationFamily();
2412
2413 auto R = std::make_unique<PathSensitiveBugReport>(
2414 *BT_UseFree[*CheckKind],
2415 AF == AF_InnerBuffer
2416 ? "Inner pointer of container used after re/deallocation"
2417 : "Use of memory after it is freed",
2418 N);
2419
2420 R->markInteresting(Sym);
2421 R->addRange(Range);
2422 R->addVisitor<MallocBugVisitor>(Sym);
2423
2424 if (AF == AF_InnerBuffer)
2425 R->addVisitor(allocation_state::getInnerPointerBRVisitor(Sym));
2426
2427 C.emitReport(std::move(R));
2428 }
2429 }
2430
HandleDoubleFree(CheckerContext & C,SourceRange Range,bool Released,SymbolRef Sym,SymbolRef PrevSym) const2431 void MallocChecker::HandleDoubleFree(CheckerContext &C, SourceRange Range,
2432 bool Released, SymbolRef Sym,
2433 SymbolRef PrevSym) const {
2434
2435 if (!ChecksEnabled[CK_MallocChecker] && !ChecksEnabled[CK_NewDeleteChecker]) {
2436 C.addSink();
2437 return;
2438 }
2439
2440 std::optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(C, Sym);
2441 if (!CheckKind)
2442 return;
2443
2444 if (ExplodedNode *N = C.generateErrorNode()) {
2445 if (!BT_DoubleFree[*CheckKind])
2446 BT_DoubleFree[*CheckKind].reset(new BugType(
2447 CheckNames[*CheckKind], "Double free", categories::MemoryError));
2448
2449 auto R = std::make_unique<PathSensitiveBugReport>(
2450 *BT_DoubleFree[*CheckKind],
2451 (Released ? "Attempt to free released memory"
2452 : "Attempt to free non-owned memory"),
2453 N);
2454 R->addRange(Range);
2455 R->markInteresting(Sym);
2456 if (PrevSym)
2457 R->markInteresting(PrevSym);
2458 R->addVisitor<MallocBugVisitor>(Sym);
2459 C.emitReport(std::move(R));
2460 }
2461 }
2462
HandleDoubleDelete(CheckerContext & C,SymbolRef Sym) const2463 void MallocChecker::HandleDoubleDelete(CheckerContext &C, SymbolRef Sym) const {
2464
2465 if (!ChecksEnabled[CK_NewDeleteChecker]) {
2466 C.addSink();
2467 return;
2468 }
2469
2470 std::optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(C, Sym);
2471 if (!CheckKind)
2472 return;
2473
2474 if (ExplodedNode *N = C.generateErrorNode()) {
2475 if (!BT_DoubleDelete)
2476 BT_DoubleDelete.reset(new BugType(CheckNames[CK_NewDeleteChecker],
2477 "Double delete",
2478 categories::MemoryError));
2479
2480 auto R = std::make_unique<PathSensitiveBugReport>(
2481 *BT_DoubleDelete, "Attempt to delete released memory", N);
2482
2483 R->markInteresting(Sym);
2484 R->addVisitor<MallocBugVisitor>(Sym);
2485 C.emitReport(std::move(R));
2486 }
2487 }
2488
HandleUseZeroAlloc(CheckerContext & C,SourceRange Range,SymbolRef Sym) const2489 void MallocChecker::HandleUseZeroAlloc(CheckerContext &C, SourceRange Range,
2490 SymbolRef Sym) const {
2491
2492 if (!ChecksEnabled[CK_MallocChecker] && !ChecksEnabled[CK_NewDeleteChecker]) {
2493 C.addSink();
2494 return;
2495 }
2496
2497 std::optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(C, Sym);
2498
2499 if (!CheckKind)
2500 return;
2501
2502 if (ExplodedNode *N = C.generateErrorNode()) {
2503 if (!BT_UseZerroAllocated[*CheckKind])
2504 BT_UseZerroAllocated[*CheckKind].reset(
2505 new BugType(CheckNames[*CheckKind], "Use of zero allocated",
2506 categories::MemoryError));
2507
2508 auto R = std::make_unique<PathSensitiveBugReport>(
2509 *BT_UseZerroAllocated[*CheckKind],
2510 "Use of memory allocated with size zero", N);
2511
2512 R->addRange(Range);
2513 if (Sym) {
2514 R->markInteresting(Sym);
2515 R->addVisitor<MallocBugVisitor>(Sym);
2516 }
2517 C.emitReport(std::move(R));
2518 }
2519 }
2520
HandleFunctionPtrFree(CheckerContext & C,SVal ArgVal,SourceRange Range,const Expr * FreeExpr,AllocationFamily Family) const2521 void MallocChecker::HandleFunctionPtrFree(CheckerContext &C, SVal ArgVal,
2522 SourceRange Range,
2523 const Expr *FreeExpr,
2524 AllocationFamily Family) const {
2525 if (!ChecksEnabled[CK_MallocChecker]) {
2526 C.addSink();
2527 return;
2528 }
2529
2530 std::optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(Family);
2531 if (!CheckKind)
2532 return;
2533
2534 if (ExplodedNode *N = C.generateErrorNode()) {
2535 if (!BT_BadFree[*CheckKind])
2536 BT_BadFree[*CheckKind].reset(new BugType(
2537 CheckNames[*CheckKind], "Bad free", categories::MemoryError));
2538
2539 SmallString<100> Buf;
2540 llvm::raw_svector_ostream Os(Buf);
2541
2542 const MemRegion *MR = ArgVal.getAsRegion();
2543 while (const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(MR))
2544 MR = ER->getSuperRegion();
2545
2546 Os << "Argument to ";
2547 if (!printMemFnName(Os, C, FreeExpr))
2548 Os << "deallocator";
2549
2550 Os << " is a function pointer";
2551
2552 auto R = std::make_unique<PathSensitiveBugReport>(*BT_BadFree[*CheckKind],
2553 Os.str(), N);
2554 R->markInteresting(MR);
2555 R->addRange(Range);
2556 C.emitReport(std::move(R));
2557 }
2558 }
2559
2560 ProgramStateRef
ReallocMemAux(CheckerContext & C,const CallEvent & Call,bool ShouldFreeOnFail,ProgramStateRef State,AllocationFamily Family,bool SuffixWithN) const2561 MallocChecker::ReallocMemAux(CheckerContext &C, const CallEvent &Call,
2562 bool ShouldFreeOnFail, ProgramStateRef State,
2563 AllocationFamily Family, bool SuffixWithN) const {
2564 if (!State)
2565 return nullptr;
2566
2567 const CallExpr *CE = cast<CallExpr>(Call.getOriginExpr());
2568
2569 if (SuffixWithN && CE->getNumArgs() < 3)
2570 return nullptr;
2571 else if (CE->getNumArgs() < 2)
2572 return nullptr;
2573
2574 const Expr *arg0Expr = CE->getArg(0);
2575 SVal Arg0Val = C.getSVal(arg0Expr);
2576 if (!isa<DefinedOrUnknownSVal>(Arg0Val))
2577 return nullptr;
2578 DefinedOrUnknownSVal arg0Val = Arg0Val.castAs<DefinedOrUnknownSVal>();
2579
2580 SValBuilder &svalBuilder = C.getSValBuilder();
2581
2582 DefinedOrUnknownSVal PtrEQ = svalBuilder.evalEQ(
2583 State, arg0Val, svalBuilder.makeNullWithType(arg0Expr->getType()));
2584
2585 // Get the size argument.
2586 const Expr *Arg1 = CE->getArg(1);
2587
2588 // Get the value of the size argument.
2589 SVal TotalSize = C.getSVal(Arg1);
2590 if (SuffixWithN)
2591 TotalSize = evalMulForBufferSize(C, Arg1, CE->getArg(2));
2592 if (!isa<DefinedOrUnknownSVal>(TotalSize))
2593 return nullptr;
2594
2595 // Compare the size argument to 0.
2596 DefinedOrUnknownSVal SizeZero =
2597 svalBuilder.evalEQ(State, TotalSize.castAs<DefinedOrUnknownSVal>(),
2598 svalBuilder.makeIntValWithWidth(
2599 svalBuilder.getContext().getSizeType(), 0));
2600
2601 ProgramStateRef StatePtrIsNull, StatePtrNotNull;
2602 std::tie(StatePtrIsNull, StatePtrNotNull) = State->assume(PtrEQ);
2603 ProgramStateRef StateSizeIsZero, StateSizeNotZero;
2604 std::tie(StateSizeIsZero, StateSizeNotZero) = State->assume(SizeZero);
2605 // We only assume exceptional states if they are definitely true; if the
2606 // state is under-constrained, assume regular realloc behavior.
2607 bool PrtIsNull = StatePtrIsNull && !StatePtrNotNull;
2608 bool SizeIsZero = StateSizeIsZero && !StateSizeNotZero;
2609
2610 // If the ptr is NULL and the size is not 0, the call is equivalent to
2611 // malloc(size).
2612 if (PrtIsNull && !SizeIsZero) {
2613 ProgramStateRef stateMalloc = MallocMemAux(
2614 C, Call, TotalSize, UndefinedVal(), StatePtrIsNull, Family);
2615 return stateMalloc;
2616 }
2617
2618 if (PrtIsNull && SizeIsZero)
2619 return State;
2620
2621 assert(!PrtIsNull);
2622
2623 bool IsKnownToBeAllocated = false;
2624
2625 // If the size is 0, free the memory.
2626 if (SizeIsZero)
2627 // The semantics of the return value are:
2628 // If size was equal to 0, either NULL or a pointer suitable to be passed
2629 // to free() is returned. We just free the input pointer and do not add
2630 // any constrains on the output pointer.
2631 if (ProgramStateRef stateFree = FreeMemAux(
2632 C, Call, StateSizeIsZero, 0, false, IsKnownToBeAllocated, Family))
2633 return stateFree;
2634
2635 // Default behavior.
2636 if (ProgramStateRef stateFree =
2637 FreeMemAux(C, Call, State, 0, false, IsKnownToBeAllocated, Family)) {
2638
2639 ProgramStateRef stateRealloc =
2640 MallocMemAux(C, Call, TotalSize, UnknownVal(), stateFree, Family);
2641 if (!stateRealloc)
2642 return nullptr;
2643
2644 OwnershipAfterReallocKind Kind = OAR_ToBeFreedAfterFailure;
2645 if (ShouldFreeOnFail)
2646 Kind = OAR_FreeOnFailure;
2647 else if (!IsKnownToBeAllocated)
2648 Kind = OAR_DoNotTrackAfterFailure;
2649
2650 // Get the from and to pointer symbols as in toPtr = realloc(fromPtr, size).
2651 SymbolRef FromPtr = arg0Val.getLocSymbolInBase();
2652 SVal RetVal = C.getSVal(CE);
2653 SymbolRef ToPtr = RetVal.getAsSymbol();
2654 assert(FromPtr && ToPtr &&
2655 "By this point, FreeMemAux and MallocMemAux should have checked "
2656 "whether the argument or the return value is symbolic!");
2657
2658 // Record the info about the reallocated symbol so that we could properly
2659 // process failed reallocation.
2660 stateRealloc = stateRealloc->set<ReallocPairs>(ToPtr,
2661 ReallocPair(FromPtr, Kind));
2662 // The reallocated symbol should stay alive for as long as the new symbol.
2663 C.getSymbolManager().addSymbolDependency(ToPtr, FromPtr);
2664 return stateRealloc;
2665 }
2666 return nullptr;
2667 }
2668
CallocMem(CheckerContext & C,const CallEvent & Call,ProgramStateRef State)2669 ProgramStateRef MallocChecker::CallocMem(CheckerContext &C,
2670 const CallEvent &Call,
2671 ProgramStateRef State) {
2672 if (!State)
2673 return nullptr;
2674
2675 if (Call.getNumArgs() < 2)
2676 return nullptr;
2677
2678 SValBuilder &svalBuilder = C.getSValBuilder();
2679 SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
2680 SVal TotalSize =
2681 evalMulForBufferSize(C, Call.getArgExpr(0), Call.getArgExpr(1));
2682
2683 return MallocMemAux(C, Call, TotalSize, zeroVal, State, AF_Malloc);
2684 }
2685
getAllocationSite(const ExplodedNode * N,SymbolRef Sym,CheckerContext & C)2686 MallocChecker::LeakInfo MallocChecker::getAllocationSite(const ExplodedNode *N,
2687 SymbolRef Sym,
2688 CheckerContext &C) {
2689 const LocationContext *LeakContext = N->getLocationContext();
2690 // Walk the ExplodedGraph backwards and find the first node that referred to
2691 // the tracked symbol.
2692 const ExplodedNode *AllocNode = N;
2693 const MemRegion *ReferenceRegion = nullptr;
2694
2695 while (N) {
2696 ProgramStateRef State = N->getState();
2697 if (!State->get<RegionState>(Sym))
2698 break;
2699
2700 // Find the most recent expression bound to the symbol in the current
2701 // context.
2702 if (!ReferenceRegion) {
2703 if (const MemRegion *MR = C.getLocationRegionIfPostStore(N)) {
2704 SVal Val = State->getSVal(MR);
2705 if (Val.getAsLocSymbol() == Sym) {
2706 const VarRegion *VR = MR->getBaseRegion()->getAs<VarRegion>();
2707 // Do not show local variables belonging to a function other than
2708 // where the error is reported.
2709 if (!VR || (VR->getStackFrame() == LeakContext->getStackFrame()))
2710 ReferenceRegion = MR;
2711 }
2712 }
2713 }
2714
2715 // Allocation node, is the last node in the current or parent context in
2716 // which the symbol was tracked.
2717 const LocationContext *NContext = N->getLocationContext();
2718 if (NContext == LeakContext ||
2719 NContext->isParentOf(LeakContext))
2720 AllocNode = N;
2721 N = N->pred_empty() ? nullptr : *(N->pred_begin());
2722 }
2723
2724 return LeakInfo(AllocNode, ReferenceRegion);
2725 }
2726
HandleLeak(SymbolRef Sym,ExplodedNode * N,CheckerContext & C) const2727 void MallocChecker::HandleLeak(SymbolRef Sym, ExplodedNode *N,
2728 CheckerContext &C) const {
2729
2730 if (!ChecksEnabled[CK_MallocChecker] &&
2731 !ChecksEnabled[CK_NewDeleteLeaksChecker])
2732 return;
2733
2734 const RefState *RS = C.getState()->get<RegionState>(Sym);
2735 assert(RS && "cannot leak an untracked symbol");
2736 AllocationFamily Family = RS->getAllocationFamily();
2737
2738 if (Family == AF_Alloca)
2739 return;
2740
2741 std::optional<MallocChecker::CheckKind> CheckKind =
2742 getCheckIfTracked(Family, true);
2743
2744 if (!CheckKind)
2745 return;
2746
2747 assert(N);
2748 if (!BT_Leak[*CheckKind]) {
2749 // Leaks should not be reported if they are post-dominated by a sink:
2750 // (1) Sinks are higher importance bugs.
2751 // (2) NoReturnFunctionChecker uses sink nodes to represent paths ending
2752 // with __noreturn functions such as assert() or exit(). We choose not
2753 // to report leaks on such paths.
2754 BT_Leak[*CheckKind].reset(new BugType(CheckNames[*CheckKind], "Memory leak",
2755 categories::MemoryError,
2756 /*SuppressOnSink=*/true));
2757 }
2758
2759 // Most bug reports are cached at the location where they occurred.
2760 // With leaks, we want to unique them by the location where they were
2761 // allocated, and only report a single path.
2762 PathDiagnosticLocation LocUsedForUniqueing;
2763 const ExplodedNode *AllocNode = nullptr;
2764 const MemRegion *Region = nullptr;
2765 std::tie(AllocNode, Region) = getAllocationSite(N, Sym, C);
2766
2767 const Stmt *AllocationStmt = AllocNode->getStmtForDiagnostics();
2768 if (AllocationStmt)
2769 LocUsedForUniqueing = PathDiagnosticLocation::createBegin(AllocationStmt,
2770 C.getSourceManager(),
2771 AllocNode->getLocationContext());
2772
2773 SmallString<200> buf;
2774 llvm::raw_svector_ostream os(buf);
2775 if (Region && Region->canPrintPretty()) {
2776 os << "Potential leak of memory pointed to by ";
2777 Region->printPretty(os);
2778 } else {
2779 os << "Potential memory leak";
2780 }
2781
2782 auto R = std::make_unique<PathSensitiveBugReport>(
2783 *BT_Leak[*CheckKind], os.str(), N, LocUsedForUniqueing,
2784 AllocNode->getLocationContext()->getDecl());
2785 R->markInteresting(Sym);
2786 R->addVisitor<MallocBugVisitor>(Sym, true);
2787 if (ShouldRegisterNoOwnershipChangeVisitor)
2788 R->addVisitor<NoOwnershipChangeVisitor>(Sym, this);
2789 C.emitReport(std::move(R));
2790 }
2791
checkDeadSymbols(SymbolReaper & SymReaper,CheckerContext & C) const2792 void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper,
2793 CheckerContext &C) const
2794 {
2795 ProgramStateRef state = C.getState();
2796 RegionStateTy OldRS = state->get<RegionState>();
2797 RegionStateTy::Factory &F = state->get_context<RegionState>();
2798
2799 RegionStateTy RS = OldRS;
2800 SmallVector<SymbolRef, 2> Errors;
2801 for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
2802 if (SymReaper.isDead(I->first)) {
2803 if (I->second.isAllocated() || I->second.isAllocatedOfSizeZero())
2804 Errors.push_back(I->first);
2805 // Remove the dead symbol from the map.
2806 RS = F.remove(RS, I->first);
2807 }
2808 }
2809
2810 if (RS == OldRS) {
2811 // We shouldn't have touched other maps yet.
2812 assert(state->get<ReallocPairs>() ==
2813 C.getState()->get<ReallocPairs>());
2814 assert(state->get<FreeReturnValue>() ==
2815 C.getState()->get<FreeReturnValue>());
2816 return;
2817 }
2818
2819 // Cleanup the Realloc Pairs Map.
2820 ReallocPairsTy RP = state->get<ReallocPairs>();
2821 for (ReallocPairsTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) {
2822 if (SymReaper.isDead(I->first) ||
2823 SymReaper.isDead(I->second.ReallocatedSym)) {
2824 state = state->remove<ReallocPairs>(I->first);
2825 }
2826 }
2827
2828 // Cleanup the FreeReturnValue Map.
2829 FreeReturnValueTy FR = state->get<FreeReturnValue>();
2830 for (FreeReturnValueTy::iterator I = FR.begin(), E = FR.end(); I != E; ++I) {
2831 if (SymReaper.isDead(I->first) ||
2832 SymReaper.isDead(I->second)) {
2833 state = state->remove<FreeReturnValue>(I->first);
2834 }
2835 }
2836
2837 // Generate leak node.
2838 ExplodedNode *N = C.getPredecessor();
2839 if (!Errors.empty()) {
2840 static CheckerProgramPointTag Tag("MallocChecker", "DeadSymbolsLeak");
2841 N = C.generateNonFatalErrorNode(C.getState(), &Tag);
2842 if (N) {
2843 for (SmallVectorImpl<SymbolRef>::iterator
2844 I = Errors.begin(), E = Errors.end(); I != E; ++I) {
2845 HandleLeak(*I, N, C);
2846 }
2847 }
2848 }
2849
2850 C.addTransition(state->set<RegionState>(RS), N);
2851 }
2852
checkPreCall(const CallEvent & Call,CheckerContext & C) const2853 void MallocChecker::checkPreCall(const CallEvent &Call,
2854 CheckerContext &C) const {
2855
2856 if (const auto *DC = dyn_cast<CXXDeallocatorCall>(&Call)) {
2857 const CXXDeleteExpr *DE = DC->getOriginExpr();
2858
2859 if (!ChecksEnabled[CK_NewDeleteChecker])
2860 if (SymbolRef Sym = C.getSVal(DE->getArgument()).getAsSymbol())
2861 checkUseAfterFree(Sym, C, DE->getArgument());
2862
2863 if (!isStandardNewDelete(DC->getDecl()))
2864 return;
2865
2866 ProgramStateRef State = C.getState();
2867 bool IsKnownToBeAllocated;
2868 State = FreeMemAux(C, DE->getArgument(), Call, State,
2869 /*Hold*/ false, IsKnownToBeAllocated,
2870 (DE->isArrayForm() ? AF_CXXNewArray : AF_CXXNew));
2871
2872 C.addTransition(State);
2873 return;
2874 }
2875
2876 if (const auto *DC = dyn_cast<CXXDestructorCall>(&Call)) {
2877 SymbolRef Sym = DC->getCXXThisVal().getAsSymbol();
2878 if (!Sym || checkDoubleDelete(Sym, C))
2879 return;
2880 }
2881
2882 // We will check for double free in the post visit.
2883 if (const AnyFunctionCall *FC = dyn_cast<AnyFunctionCall>(&Call)) {
2884 const FunctionDecl *FD = FC->getDecl();
2885 if (!FD)
2886 return;
2887
2888 if (ChecksEnabled[CK_MallocChecker] && isFreeingCall(Call))
2889 return;
2890 }
2891
2892 // Check if the callee of a method is deleted.
2893 if (const CXXInstanceCall *CC = dyn_cast<CXXInstanceCall>(&Call)) {
2894 SymbolRef Sym = CC->getCXXThisVal().getAsSymbol();
2895 if (!Sym || checkUseAfterFree(Sym, C, CC->getCXXThisExpr()))
2896 return;
2897 }
2898
2899 // Check arguments for being used after free.
2900 for (unsigned I = 0, E = Call.getNumArgs(); I != E; ++I) {
2901 SVal ArgSVal = Call.getArgSVal(I);
2902 if (isa<Loc>(ArgSVal)) {
2903 SymbolRef Sym = ArgSVal.getAsSymbol();
2904 if (!Sym)
2905 continue;
2906 if (checkUseAfterFree(Sym, C, Call.getArgExpr(I)))
2907 return;
2908 }
2909 }
2910 }
2911
checkPreStmt(const ReturnStmt * S,CheckerContext & C) const2912 void MallocChecker::checkPreStmt(const ReturnStmt *S,
2913 CheckerContext &C) const {
2914 checkEscapeOnReturn(S, C);
2915 }
2916
2917 // In the CFG, automatic destructors come after the return statement.
2918 // This callback checks for returning memory that is freed by automatic
2919 // destructors, as those cannot be reached in checkPreStmt().
checkEndFunction(const ReturnStmt * S,CheckerContext & C) const2920 void MallocChecker::checkEndFunction(const ReturnStmt *S,
2921 CheckerContext &C) const {
2922 checkEscapeOnReturn(S, C);
2923 }
2924
checkEscapeOnReturn(const ReturnStmt * S,CheckerContext & C) const2925 void MallocChecker::checkEscapeOnReturn(const ReturnStmt *S,
2926 CheckerContext &C) const {
2927 if (!S)
2928 return;
2929
2930 const Expr *E = S->getRetValue();
2931 if (!E)
2932 return;
2933
2934 // Check if we are returning a symbol.
2935 ProgramStateRef State = C.getState();
2936 SVal RetVal = C.getSVal(E);
2937 SymbolRef Sym = RetVal.getAsSymbol();
2938 if (!Sym)
2939 // If we are returning a field of the allocated struct or an array element,
2940 // the callee could still free the memory.
2941 // TODO: This logic should be a part of generic symbol escape callback.
2942 if (const MemRegion *MR = RetVal.getAsRegion())
2943 if (isa<FieldRegion, ElementRegion>(MR))
2944 if (const SymbolicRegion *BMR =
2945 dyn_cast<SymbolicRegion>(MR->getBaseRegion()))
2946 Sym = BMR->getSymbol();
2947
2948 // Check if we are returning freed memory.
2949 if (Sym)
2950 checkUseAfterFree(Sym, C, E);
2951 }
2952
2953 // TODO: Blocks should be either inlined or should call invalidate regions
2954 // upon invocation. After that's in place, special casing here will not be
2955 // needed.
checkPostStmt(const BlockExpr * BE,CheckerContext & C) const2956 void MallocChecker::checkPostStmt(const BlockExpr *BE,
2957 CheckerContext &C) const {
2958
2959 // Scan the BlockDecRefExprs for any object the retain count checker
2960 // may be tracking.
2961 if (!BE->getBlockDecl()->hasCaptures())
2962 return;
2963
2964 ProgramStateRef state = C.getState();
2965 const BlockDataRegion *R =
2966 cast<BlockDataRegion>(C.getSVal(BE).getAsRegion());
2967
2968 BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
2969 E = R->referenced_vars_end();
2970
2971 if (I == E)
2972 return;
2973
2974 SmallVector<const MemRegion*, 10> Regions;
2975 const LocationContext *LC = C.getLocationContext();
2976 MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();
2977
2978 for ( ; I != E; ++I) {
2979 const VarRegion *VR = I.getCapturedRegion();
2980 if (VR->getSuperRegion() == R) {
2981 VR = MemMgr.getVarRegion(VR->getDecl(), LC);
2982 }
2983 Regions.push_back(VR);
2984 }
2985
2986 state =
2987 state->scanReachableSymbols<StopTrackingCallback>(Regions).getState();
2988 C.addTransition(state);
2989 }
2990
isReleased(SymbolRef Sym,CheckerContext & C)2991 static bool isReleased(SymbolRef Sym, CheckerContext &C) {
2992 assert(Sym);
2993 const RefState *RS = C.getState()->get<RegionState>(Sym);
2994 return (RS && RS->isReleased());
2995 }
2996
suppressDeallocationsInSuspiciousContexts(const CallEvent & Call,CheckerContext & C) const2997 bool MallocChecker::suppressDeallocationsInSuspiciousContexts(
2998 const CallEvent &Call, CheckerContext &C) const {
2999 if (Call.getNumArgs() == 0)
3000 return false;
3001
3002 StringRef FunctionStr = "";
3003 if (const auto *FD = dyn_cast<FunctionDecl>(C.getStackFrame()->getDecl()))
3004 if (const Stmt *Body = FD->getBody())
3005 if (Body->getBeginLoc().isValid())
3006 FunctionStr =
3007 Lexer::getSourceText(CharSourceRange::getTokenRange(
3008 {FD->getBeginLoc(), Body->getBeginLoc()}),
3009 C.getSourceManager(), C.getLangOpts());
3010
3011 // We do not model the Integer Set Library's retain-count based allocation.
3012 if (!FunctionStr.contains("__isl_"))
3013 return false;
3014
3015 ProgramStateRef State = C.getState();
3016
3017 for (const Expr *Arg : cast<CallExpr>(Call.getOriginExpr())->arguments())
3018 if (SymbolRef Sym = C.getSVal(Arg).getAsSymbol())
3019 if (const RefState *RS = State->get<RegionState>(Sym))
3020 State = State->set<RegionState>(Sym, RefState::getEscaped(RS));
3021
3022 C.addTransition(State);
3023 return true;
3024 }
3025
checkUseAfterFree(SymbolRef Sym,CheckerContext & C,const Stmt * S) const3026 bool MallocChecker::checkUseAfterFree(SymbolRef Sym, CheckerContext &C,
3027 const Stmt *S) const {
3028
3029 if (isReleased(Sym, C)) {
3030 HandleUseAfterFree(C, S->getSourceRange(), Sym);
3031 return true;
3032 }
3033
3034 return false;
3035 }
3036
checkUseZeroAllocated(SymbolRef Sym,CheckerContext & C,const Stmt * S) const3037 void MallocChecker::checkUseZeroAllocated(SymbolRef Sym, CheckerContext &C,
3038 const Stmt *S) const {
3039 assert(Sym);
3040
3041 if (const RefState *RS = C.getState()->get<RegionState>(Sym)) {
3042 if (RS->isAllocatedOfSizeZero())
3043 HandleUseZeroAlloc(C, RS->getStmt()->getSourceRange(), Sym);
3044 }
3045 else if (C.getState()->contains<ReallocSizeZeroSymbols>(Sym)) {
3046 HandleUseZeroAlloc(C, S->getSourceRange(), Sym);
3047 }
3048 }
3049
checkDoubleDelete(SymbolRef Sym,CheckerContext & C) const3050 bool MallocChecker::checkDoubleDelete(SymbolRef Sym, CheckerContext &C) const {
3051
3052 if (isReleased(Sym, C)) {
3053 HandleDoubleDelete(C, Sym);
3054 return true;
3055 }
3056 return false;
3057 }
3058
3059 // Check if the location is a freed symbolic region.
checkLocation(SVal l,bool isLoad,const Stmt * S,CheckerContext & C) const3060 void MallocChecker::checkLocation(SVal l, bool isLoad, const Stmt *S,
3061 CheckerContext &C) const {
3062 SymbolRef Sym = l.getLocSymbolInBase();
3063 if (Sym) {
3064 checkUseAfterFree(Sym, C, S);
3065 checkUseZeroAllocated(Sym, C, S);
3066 }
3067 }
3068
3069 // If a symbolic region is assumed to NULL (or another constant), stop tracking
3070 // it - assuming that allocation failed on this path.
evalAssume(ProgramStateRef state,SVal Cond,bool Assumption) const3071 ProgramStateRef MallocChecker::evalAssume(ProgramStateRef state,
3072 SVal Cond,
3073 bool Assumption) const {
3074 RegionStateTy RS = state->get<RegionState>();
3075 for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
3076 // If the symbol is assumed to be NULL, remove it from consideration.
3077 ConstraintManager &CMgr = state->getConstraintManager();
3078 ConditionTruthVal AllocFailed = CMgr.isNull(state, I.getKey());
3079 if (AllocFailed.isConstrainedTrue())
3080 state = state->remove<RegionState>(I.getKey());
3081 }
3082
3083 // Realloc returns 0 when reallocation fails, which means that we should
3084 // restore the state of the pointer being reallocated.
3085 ReallocPairsTy RP = state->get<ReallocPairs>();
3086 for (ReallocPairsTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) {
3087 // If the symbol is assumed to be NULL, remove it from consideration.
3088 ConstraintManager &CMgr = state->getConstraintManager();
3089 ConditionTruthVal AllocFailed = CMgr.isNull(state, I.getKey());
3090 if (!AllocFailed.isConstrainedTrue())
3091 continue;
3092
3093 SymbolRef ReallocSym = I.getData().ReallocatedSym;
3094 if (const RefState *RS = state->get<RegionState>(ReallocSym)) {
3095 if (RS->isReleased()) {
3096 switch (I.getData().Kind) {
3097 case OAR_ToBeFreedAfterFailure:
3098 state = state->set<RegionState>(ReallocSym,
3099 RefState::getAllocated(RS->getAllocationFamily(), RS->getStmt()));
3100 break;
3101 case OAR_DoNotTrackAfterFailure:
3102 state = state->remove<RegionState>(ReallocSym);
3103 break;
3104 default:
3105 assert(I.getData().Kind == OAR_FreeOnFailure);
3106 }
3107 }
3108 }
3109 state = state->remove<ReallocPairs>(I.getKey());
3110 }
3111
3112 return state;
3113 }
3114
mayFreeAnyEscapedMemoryOrIsModeledExplicitly(const CallEvent * Call,ProgramStateRef State,SymbolRef & EscapingSymbol) const3115 bool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
3116 const CallEvent *Call,
3117 ProgramStateRef State,
3118 SymbolRef &EscapingSymbol) const {
3119 assert(Call);
3120 EscapingSymbol = nullptr;
3121
3122 // For now, assume that any C++ or block call can free memory.
3123 // TODO: If we want to be more optimistic here, we'll need to make sure that
3124 // regions escape to C++ containers. They seem to do that even now, but for
3125 // mysterious reasons.
3126 if (!isa<SimpleFunctionCall, ObjCMethodCall>(Call))
3127 return true;
3128
3129 // Check Objective-C messages by selector name.
3130 if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(Call)) {
3131 // If it's not a framework call, or if it takes a callback, assume it
3132 // can free memory.
3133 if (!Call->isInSystemHeader() || Call->argumentsMayEscape())
3134 return true;
3135
3136 // If it's a method we know about, handle it explicitly post-call.
3137 // This should happen before the "freeWhenDone" check below.
3138 if (isKnownDeallocObjCMethodName(*Msg))
3139 return false;
3140
3141 // If there's a "freeWhenDone" parameter, but the method isn't one we know
3142 // about, we can't be sure that the object will use free() to deallocate the
3143 // memory, so we can't model it explicitly. The best we can do is use it to
3144 // decide whether the pointer escapes.
3145 if (std::optional<bool> FreeWhenDone = getFreeWhenDoneArg(*Msg))
3146 return *FreeWhenDone;
3147
3148 // If the first selector piece ends with "NoCopy", and there is no
3149 // "freeWhenDone" parameter set to zero, we know ownership is being
3150 // transferred. Again, though, we can't be sure that the object will use
3151 // free() to deallocate the memory, so we can't model it explicitly.
3152 StringRef FirstSlot = Msg->getSelector().getNameForSlot(0);
3153 if (FirstSlot.endswith("NoCopy"))
3154 return true;
3155
3156 // If the first selector starts with addPointer, insertPointer,
3157 // or replacePointer, assume we are dealing with NSPointerArray or similar.
3158 // This is similar to C++ containers (vector); we still might want to check
3159 // that the pointers get freed by following the container itself.
3160 if (FirstSlot.startswith("addPointer") ||
3161 FirstSlot.startswith("insertPointer") ||
3162 FirstSlot.startswith("replacePointer") ||
3163 FirstSlot.equals("valueWithPointer")) {
3164 return true;
3165 }
3166
3167 // We should escape receiver on call to 'init'. This is especially relevant
3168 // to the receiver, as the corresponding symbol is usually not referenced
3169 // after the call.
3170 if (Msg->getMethodFamily() == OMF_init) {
3171 EscapingSymbol = Msg->getReceiverSVal().getAsSymbol();
3172 return true;
3173 }
3174
3175 // Otherwise, assume that the method does not free memory.
3176 // Most framework methods do not free memory.
3177 return false;
3178 }
3179
3180 // At this point the only thing left to handle is straight function calls.
3181 const FunctionDecl *FD = cast<SimpleFunctionCall>(Call)->getDecl();
3182 if (!FD)
3183 return true;
3184
3185 // If it's one of the allocation functions we can reason about, we model
3186 // its behavior explicitly.
3187 if (isMemCall(*Call))
3188 return false;
3189
3190 // If it's not a system call, assume it frees memory.
3191 if (!Call->isInSystemHeader())
3192 return true;
3193
3194 // White list the system functions whose arguments escape.
3195 const IdentifierInfo *II = FD->getIdentifier();
3196 if (!II)
3197 return true;
3198 StringRef FName = II->getName();
3199
3200 // White list the 'XXXNoCopy' CoreFoundation functions.
3201 // We specifically check these before
3202 if (FName.endswith("NoCopy")) {
3203 // Look for the deallocator argument. We know that the memory ownership
3204 // is not transferred only if the deallocator argument is
3205 // 'kCFAllocatorNull'.
3206 for (unsigned i = 1; i < Call->getNumArgs(); ++i) {
3207 const Expr *ArgE = Call->getArgExpr(i)->IgnoreParenCasts();
3208 if (const DeclRefExpr *DE = dyn_cast<DeclRefExpr>(ArgE)) {
3209 StringRef DeallocatorName = DE->getFoundDecl()->getName();
3210 if (DeallocatorName == "kCFAllocatorNull")
3211 return false;
3212 }
3213 }
3214 return true;
3215 }
3216
3217 // Associating streams with malloced buffers. The pointer can escape if
3218 // 'closefn' is specified (and if that function does free memory),
3219 // but it will not if closefn is not specified.
3220 // Currently, we do not inspect the 'closefn' function (PR12101).
3221 if (FName == "funopen")
3222 if (Call->getNumArgs() >= 4 && Call->getArgSVal(4).isConstant(0))
3223 return false;
3224
3225 // Do not warn on pointers passed to 'setbuf' when used with std streams,
3226 // these leaks might be intentional when setting the buffer for stdio.
3227 // http://stackoverflow.com/questions/2671151/who-frees-setvbuf-buffer
3228 if (FName == "setbuf" || FName =="setbuffer" ||
3229 FName == "setlinebuf" || FName == "setvbuf") {
3230 if (Call->getNumArgs() >= 1) {
3231 const Expr *ArgE = Call->getArgExpr(0)->IgnoreParenCasts();
3232 if (const DeclRefExpr *ArgDRE = dyn_cast<DeclRefExpr>(ArgE))
3233 if (const VarDecl *D = dyn_cast<VarDecl>(ArgDRE->getDecl()))
3234 if (D->getCanonicalDecl()->getName().contains("std"))
3235 return true;
3236 }
3237 }
3238
3239 // A bunch of other functions which either take ownership of a pointer or
3240 // wrap the result up in a struct or object, meaning it can be freed later.
3241 // (See RetainCountChecker.) Not all the parameters here are invalidated,
3242 // but the Malloc checker cannot differentiate between them. The right way
3243 // of doing this would be to implement a pointer escapes callback.
3244 if (FName == "CGBitmapContextCreate" ||
3245 FName == "CGBitmapContextCreateWithData" ||
3246 FName == "CVPixelBufferCreateWithBytes" ||
3247 FName == "CVPixelBufferCreateWithPlanarBytes" ||
3248 FName == "OSAtomicEnqueue") {
3249 return true;
3250 }
3251
3252 if (FName == "postEvent" &&
3253 FD->getQualifiedNameAsString() == "QCoreApplication::postEvent") {
3254 return true;
3255 }
3256
3257 if (FName == "connectImpl" &&
3258 FD->getQualifiedNameAsString() == "QObject::connectImpl") {
3259 return true;
3260 }
3261
3262 // Handle cases where we know a buffer's /address/ can escape.
3263 // Note that the above checks handle some special cases where we know that
3264 // even though the address escapes, it's still our responsibility to free the
3265 // buffer.
3266 if (Call->argumentsMayEscape())
3267 return true;
3268
3269 // Otherwise, assume that the function does not free memory.
3270 // Most system calls do not free the memory.
3271 return false;
3272 }
3273
checkPointerEscape(ProgramStateRef State,const InvalidatedSymbols & Escaped,const CallEvent * Call,PointerEscapeKind Kind) const3274 ProgramStateRef MallocChecker::checkPointerEscape(ProgramStateRef State,
3275 const InvalidatedSymbols &Escaped,
3276 const CallEvent *Call,
3277 PointerEscapeKind Kind) const {
3278 return checkPointerEscapeAux(State, Escaped, Call, Kind,
3279 /*IsConstPointerEscape*/ false);
3280 }
3281
checkConstPointerEscape(ProgramStateRef State,const InvalidatedSymbols & Escaped,const CallEvent * Call,PointerEscapeKind Kind) const3282 ProgramStateRef MallocChecker::checkConstPointerEscape(ProgramStateRef State,
3283 const InvalidatedSymbols &Escaped,
3284 const CallEvent *Call,
3285 PointerEscapeKind Kind) const {
3286 // If a const pointer escapes, it may not be freed(), but it could be deleted.
3287 return checkPointerEscapeAux(State, Escaped, Call, Kind,
3288 /*IsConstPointerEscape*/ true);
3289 }
3290
checkIfNewOrNewArrayFamily(const RefState * RS)3291 static bool checkIfNewOrNewArrayFamily(const RefState *RS) {
3292 return (RS->getAllocationFamily() == AF_CXXNewArray ||
3293 RS->getAllocationFamily() == AF_CXXNew);
3294 }
3295
checkPointerEscapeAux(ProgramStateRef State,const InvalidatedSymbols & Escaped,const CallEvent * Call,PointerEscapeKind Kind,bool IsConstPointerEscape) const3296 ProgramStateRef MallocChecker::checkPointerEscapeAux(
3297 ProgramStateRef State, const InvalidatedSymbols &Escaped,
3298 const CallEvent *Call, PointerEscapeKind Kind,
3299 bool IsConstPointerEscape) const {
3300 // If we know that the call does not free memory, or we want to process the
3301 // call later, keep tracking the top level arguments.
3302 SymbolRef EscapingSymbol = nullptr;
3303 if (Kind == PSK_DirectEscapeOnCall &&
3304 !mayFreeAnyEscapedMemoryOrIsModeledExplicitly(Call, State,
3305 EscapingSymbol) &&
3306 !EscapingSymbol) {
3307 return State;
3308 }
3309
3310 for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
3311 E = Escaped.end();
3312 I != E; ++I) {
3313 SymbolRef sym = *I;
3314
3315 if (EscapingSymbol && EscapingSymbol != sym)
3316 continue;
3317
3318 if (const RefState *RS = State->get<RegionState>(sym))
3319 if (RS->isAllocated() || RS->isAllocatedOfSizeZero())
3320 if (!IsConstPointerEscape || checkIfNewOrNewArrayFamily(RS))
3321 State = State->set<RegionState>(sym, RefState::getEscaped(RS));
3322 }
3323 return State;
3324 }
3325
isArgZERO_SIZE_PTR(ProgramStateRef State,CheckerContext & C,SVal ArgVal) const3326 bool MallocChecker::isArgZERO_SIZE_PTR(ProgramStateRef State, CheckerContext &C,
3327 SVal ArgVal) const {
3328 if (!KernelZeroSizePtrValue)
3329 KernelZeroSizePtrValue =
3330 tryExpandAsInteger("ZERO_SIZE_PTR", C.getPreprocessor());
3331
3332 const llvm::APSInt *ArgValKnown =
3333 C.getSValBuilder().getKnownValue(State, ArgVal);
3334 return ArgValKnown && *KernelZeroSizePtrValue &&
3335 ArgValKnown->getSExtValue() == **KernelZeroSizePtrValue;
3336 }
3337
findFailedReallocSymbol(ProgramStateRef currState,ProgramStateRef prevState)3338 static SymbolRef findFailedReallocSymbol(ProgramStateRef currState,
3339 ProgramStateRef prevState) {
3340 ReallocPairsTy currMap = currState->get<ReallocPairs>();
3341 ReallocPairsTy prevMap = prevState->get<ReallocPairs>();
3342
3343 for (const ReallocPairsTy::value_type &Pair : prevMap) {
3344 SymbolRef sym = Pair.first;
3345 if (!currMap.lookup(sym))
3346 return sym;
3347 }
3348
3349 return nullptr;
3350 }
3351
isReferenceCountingPointerDestructor(const CXXDestructorDecl * DD)3352 static bool isReferenceCountingPointerDestructor(const CXXDestructorDecl *DD) {
3353 if (const IdentifierInfo *II = DD->getParent()->getIdentifier()) {
3354 StringRef N = II->getName();
3355 if (N.contains_insensitive("ptr") || N.contains_insensitive("pointer")) {
3356 if (N.contains_insensitive("ref") || N.contains_insensitive("cnt") ||
3357 N.contains_insensitive("intrusive") ||
3358 N.contains_insensitive("shared")) {
3359 return true;
3360 }
3361 }
3362 }
3363 return false;
3364 }
3365
VisitNode(const ExplodedNode * N,BugReporterContext & BRC,PathSensitiveBugReport & BR)3366 PathDiagnosticPieceRef MallocBugVisitor::VisitNode(const ExplodedNode *N,
3367 BugReporterContext &BRC,
3368 PathSensitiveBugReport &BR) {
3369 ProgramStateRef state = N->getState();
3370 ProgramStateRef statePrev = N->getFirstPred()->getState();
3371
3372 const RefState *RSCurr = state->get<RegionState>(Sym);
3373 const RefState *RSPrev = statePrev->get<RegionState>(Sym);
3374
3375 const Stmt *S = N->getStmtForDiagnostics();
3376 // When dealing with containers, we sometimes want to give a note
3377 // even if the statement is missing.
3378 if (!S && (!RSCurr || RSCurr->getAllocationFamily() != AF_InnerBuffer))
3379 return nullptr;
3380
3381 const LocationContext *CurrentLC = N->getLocationContext();
3382
3383 // If we find an atomic fetch_add or fetch_sub within the destructor in which
3384 // the pointer was released (before the release), this is likely a destructor
3385 // of a shared pointer.
3386 // Because we don't model atomics, and also because we don't know that the
3387 // original reference count is positive, we should not report use-after-frees
3388 // on objects deleted in such destructors. This can probably be improved
3389 // through better shared pointer modeling.
3390 if (ReleaseDestructorLC) {
3391 if (const auto *AE = dyn_cast<AtomicExpr>(S)) {
3392 AtomicExpr::AtomicOp Op = AE->getOp();
3393 if (Op == AtomicExpr::AO__c11_atomic_fetch_add ||
3394 Op == AtomicExpr::AO__c11_atomic_fetch_sub) {
3395 if (ReleaseDestructorLC == CurrentLC ||
3396 ReleaseDestructorLC->isParentOf(CurrentLC)) {
3397 BR.markInvalid(getTag(), S);
3398 }
3399 }
3400 }
3401 }
3402
3403 // FIXME: We will eventually need to handle non-statement-based events
3404 // (__attribute__((cleanup))).
3405
3406 // Find out if this is an interesting point and what is the kind.
3407 StringRef Msg;
3408 std::unique_ptr<StackHintGeneratorForSymbol> StackHint = nullptr;
3409 SmallString<256> Buf;
3410 llvm::raw_svector_ostream OS(Buf);
3411
3412 if (Mode == Normal) {
3413 if (isAllocated(RSCurr, RSPrev, S)) {
3414 Msg = "Memory is allocated";
3415 StackHint = std::make_unique<StackHintGeneratorForSymbol>(
3416 Sym, "Returned allocated memory");
3417 } else if (isReleased(RSCurr, RSPrev, S)) {
3418 const auto Family = RSCurr->getAllocationFamily();
3419 switch (Family) {
3420 case AF_Alloca:
3421 case AF_Malloc:
3422 case AF_CXXNew:
3423 case AF_CXXNewArray:
3424 case AF_IfNameIndex:
3425 Msg = "Memory is released";
3426 StackHint = std::make_unique<StackHintGeneratorForSymbol>(
3427 Sym, "Returning; memory was released");
3428 break;
3429 case AF_InnerBuffer: {
3430 const MemRegion *ObjRegion =
3431 allocation_state::getContainerObjRegion(statePrev, Sym);
3432 const auto *TypedRegion = cast<TypedValueRegion>(ObjRegion);
3433 QualType ObjTy = TypedRegion->getValueType();
3434 OS << "Inner buffer of '" << ObjTy << "' ";
3435
3436 if (N->getLocation().getKind() == ProgramPoint::PostImplicitCallKind) {
3437 OS << "deallocated by call to destructor";
3438 StackHint = std::make_unique<StackHintGeneratorForSymbol>(
3439 Sym, "Returning; inner buffer was deallocated");
3440 } else {
3441 OS << "reallocated by call to '";
3442 const Stmt *S = RSCurr->getStmt();
3443 if (const auto *MemCallE = dyn_cast<CXXMemberCallExpr>(S)) {
3444 OS << MemCallE->getMethodDecl()->getDeclName();
3445 } else if (const auto *OpCallE = dyn_cast<CXXOperatorCallExpr>(S)) {
3446 OS << OpCallE->getDirectCallee()->getDeclName();
3447 } else if (const auto *CallE = dyn_cast<CallExpr>(S)) {
3448 auto &CEMgr = BRC.getStateManager().getCallEventManager();
3449 CallEventRef<> Call = CEMgr.getSimpleCall(CallE, state, CurrentLC);
3450 if (const auto *D = dyn_cast_or_null<NamedDecl>(Call->getDecl()))
3451 OS << D->getDeclName();
3452 else
3453 OS << "unknown";
3454 }
3455 OS << "'";
3456 StackHint = std::make_unique<StackHintGeneratorForSymbol>(
3457 Sym, "Returning; inner buffer was reallocated");
3458 }
3459 Msg = OS.str();
3460 break;
3461 }
3462 case AF_None:
3463 llvm_unreachable("Unhandled allocation family!");
3464 }
3465
3466 // See if we're releasing memory while inlining a destructor
3467 // (or one of its callees). This turns on various common
3468 // false positive suppressions.
3469 bool FoundAnyDestructor = false;
3470 for (const LocationContext *LC = CurrentLC; LC; LC = LC->getParent()) {
3471 if (const auto *DD = dyn_cast<CXXDestructorDecl>(LC->getDecl())) {
3472 if (isReferenceCountingPointerDestructor(DD)) {
3473 // This immediately looks like a reference-counting destructor.
3474 // We're bad at guessing the original reference count of the object,
3475 // so suppress the report for now.
3476 BR.markInvalid(getTag(), DD);
3477 } else if (!FoundAnyDestructor) {
3478 assert(!ReleaseDestructorLC &&
3479 "There can be only one release point!");
3480 // Suspect that it's a reference counting pointer destructor.
3481 // On one of the next nodes might find out that it has atomic
3482 // reference counting operations within it (see the code above),
3483 // and if so, we'd conclude that it likely is a reference counting
3484 // pointer destructor.
3485 ReleaseDestructorLC = LC->getStackFrame();
3486 // It is unlikely that releasing memory is delegated to a destructor
3487 // inside a destructor of a shared pointer, because it's fairly hard
3488 // to pass the information that the pointer indeed needs to be
3489 // released into it. So we're only interested in the innermost
3490 // destructor.
3491 FoundAnyDestructor = true;
3492 }
3493 }
3494 }
3495 } else if (isRelinquished(RSCurr, RSPrev, S)) {
3496 Msg = "Memory ownership is transferred";
3497 StackHint = std::make_unique<StackHintGeneratorForSymbol>(Sym, "");
3498 } else if (hasReallocFailed(RSCurr, RSPrev, S)) {
3499 Mode = ReallocationFailed;
3500 Msg = "Reallocation failed";
3501 StackHint = std::make_unique<StackHintGeneratorForReallocationFailed>(
3502 Sym, "Reallocation failed");
3503
3504 if (SymbolRef sym = findFailedReallocSymbol(state, statePrev)) {
3505 // Is it possible to fail two reallocs WITHOUT testing in between?
3506 assert((!FailedReallocSymbol || FailedReallocSymbol == sym) &&
3507 "We only support one failed realloc at a time.");
3508 BR.markInteresting(sym);
3509 FailedReallocSymbol = sym;
3510 }
3511 }
3512
3513 // We are in a special mode if a reallocation failed later in the path.
3514 } else if (Mode == ReallocationFailed) {
3515 assert(FailedReallocSymbol && "No symbol to look for.");
3516
3517 // Is this is the first appearance of the reallocated symbol?
3518 if (!statePrev->get<RegionState>(FailedReallocSymbol)) {
3519 // We're at the reallocation point.
3520 Msg = "Attempt to reallocate memory";
3521 StackHint = std::make_unique<StackHintGeneratorForSymbol>(
3522 Sym, "Returned reallocated memory");
3523 FailedReallocSymbol = nullptr;
3524 Mode = Normal;
3525 }
3526 }
3527
3528 if (Msg.empty()) {
3529 assert(!StackHint);
3530 return nullptr;
3531 }
3532
3533 assert(StackHint);
3534
3535 // Generate the extra diagnostic.
3536 PathDiagnosticLocation Pos;
3537 if (!S) {
3538 assert(RSCurr->getAllocationFamily() == AF_InnerBuffer);
3539 auto PostImplCall = N->getLocation().getAs<PostImplicitCall>();
3540 if (!PostImplCall)
3541 return nullptr;
3542 Pos = PathDiagnosticLocation(PostImplCall->getLocation(),
3543 BRC.getSourceManager());
3544 } else {
3545 Pos = PathDiagnosticLocation(S, BRC.getSourceManager(),
3546 N->getLocationContext());
3547 }
3548
3549 auto P = std::make_shared<PathDiagnosticEventPiece>(Pos, Msg, true);
3550 BR.addCallStackHint(P, std::move(StackHint));
3551 return P;
3552 }
3553
printState(raw_ostream & Out,ProgramStateRef State,const char * NL,const char * Sep) const3554 void MallocChecker::printState(raw_ostream &Out, ProgramStateRef State,
3555 const char *NL, const char *Sep) const {
3556
3557 RegionStateTy RS = State->get<RegionState>();
3558
3559 if (!RS.isEmpty()) {
3560 Out << Sep << "MallocChecker :" << NL;
3561 for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
3562 const RefState *RefS = State->get<RegionState>(I.getKey());
3563 AllocationFamily Family = RefS->getAllocationFamily();
3564 std::optional<MallocChecker::CheckKind> CheckKind =
3565 getCheckIfTracked(Family);
3566 if (!CheckKind)
3567 CheckKind = getCheckIfTracked(Family, true);
3568
3569 I.getKey()->dumpToStream(Out);
3570 Out << " : ";
3571 I.getData().dump(Out);
3572 if (CheckKind)
3573 Out << " (" << CheckNames[*CheckKind].getName() << ")";
3574 Out << NL;
3575 }
3576 }
3577 }
3578
3579 namespace clang {
3580 namespace ento {
3581 namespace allocation_state {
3582
3583 ProgramStateRef
markReleased(ProgramStateRef State,SymbolRef Sym,const Expr * Origin)3584 markReleased(ProgramStateRef State, SymbolRef Sym, const Expr *Origin) {
3585 AllocationFamily Family = AF_InnerBuffer;
3586 return State->set<RegionState>(Sym, RefState::getReleased(Family, Origin));
3587 }
3588
3589 } // end namespace allocation_state
3590 } // end namespace ento
3591 } // end namespace clang
3592
3593 // Intended to be used in InnerPointerChecker to register the part of
3594 // MallocChecker connected to it.
registerInnerPointerCheckerAux(CheckerManager & mgr)3595 void ento::registerInnerPointerCheckerAux(CheckerManager &mgr) {
3596 MallocChecker *checker = mgr.getChecker<MallocChecker>();
3597 checker->ChecksEnabled[MallocChecker::CK_InnerPointerChecker] = true;
3598 checker->CheckNames[MallocChecker::CK_InnerPointerChecker] =
3599 mgr.getCurrentCheckerName();
3600 }
3601
registerDynamicMemoryModeling(CheckerManager & mgr)3602 void ento::registerDynamicMemoryModeling(CheckerManager &mgr) {
3603 auto *checker = mgr.registerChecker<MallocChecker>();
3604 checker->ShouldIncludeOwnershipAnnotatedFunctions =
3605 mgr.getAnalyzerOptions().getCheckerBooleanOption(checker, "Optimistic");
3606 checker->ShouldRegisterNoOwnershipChangeVisitor =
3607 mgr.getAnalyzerOptions().getCheckerBooleanOption(
3608 checker, "AddNoOwnershipChangeNotes");
3609 }
3610
shouldRegisterDynamicMemoryModeling(const CheckerManager & mgr)3611 bool ento::shouldRegisterDynamicMemoryModeling(const CheckerManager &mgr) {
3612 return true;
3613 }
3614
3615 #define REGISTER_CHECKER(name) \
3616 void ento::register##name(CheckerManager &mgr) { \
3617 MallocChecker *checker = mgr.getChecker<MallocChecker>(); \
3618 checker->ChecksEnabled[MallocChecker::CK_##name] = true; \
3619 checker->CheckNames[MallocChecker::CK_##name] = \
3620 mgr.getCurrentCheckerName(); \
3621 } \
3622 \
3623 bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; }
3624
3625 REGISTER_CHECKER(MallocChecker)
3626 REGISTER_CHECKER(NewDeleteChecker)
3627 REGISTER_CHECKER(NewDeleteLeaksChecker)
3628 REGISTER_CHECKER(MismatchedDeallocatorChecker)
3629