devnexen created this revision.
devnexen added reviewers: NoQ, jdenny.
Herald added a subscriber: cfe-commits.

- reallocarray/recallocarray
- freezero


Repository:
  rC Clang

https://reviews.llvm.org/D45149

Files:
  lib/StaticAnalyzer/Checkers/MallocChecker.cpp
  test/Analysis/bsd-malloc.c

Index: test/Analysis/bsd-malloc.c
===================================================================
--- /dev/null
+++ test/Analysis/bsd-malloc.c
@@ -0,0 +1,28 @@
+// RUN: %clang_analyze_cc1 -triple x86_64-unknown-openbsd -analyzer-checker=unix.Malloc -verify %s
+
+#define NULL  ((void *) 0)
+
+typedef __typeof(sizeof(int)) size_t;
+
+void *reallocarray(void *ptr, size_t nmemb, size_t size);
+void *recallocarray(void *ptr, size_t onmemb, size_t nmemb, size_t size);
+void freezero(void *ptr, size_t size);
+
+void f1() {
+  int *parr = NULL;
+  parr = reallocarray(NULL, 10, sizeof(*parr));
+  return; // expected-warning{{Potential leak of memory pointed to by 'parr'}}
+}
+
+void f2() {
+  int *parr = NULL;
+  parr = recallocarray(NULL, 10, 20, sizeof(*parr));
+  return; // expected-warning{{Potential leak of memory pointed to by 'parr'}}
+}
+
+void f3() {
+  int *parr = NULL;
+  parr = reallocarray(NULL, 10, sizeof(*parr));
+  freezero(parr, 10 * sizeof(*parr)); // expected-no-warning
+  freezero(parr, 10 * sizeof(*parr)); // expected-warning{{Attempt to free released memory}}
+}
Index: lib/StaticAnalyzer/Checkers/MallocChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -182,7 +182,8 @@
         II_g_free(nullptr), II_g_memdup(nullptr), II_g_malloc_n(nullptr), 
         II_g_malloc0_n(nullptr), II_g_realloc_n(nullptr), 
         II_g_try_malloc_n(nullptr), II_g_try_malloc0_n(nullptr), 
-        II_g_try_realloc_n(nullptr) {}
+        II_g_try_realloc_n(nullptr), II_reallocarray(nullptr),
+        II_recallocarray(nullptr), II_freezero(nullptr) {}
 
   /// In pessimistic mode, the checker assumes that it does not know which
   /// functions might free the memory.
@@ -251,7 +252,8 @@
                          *II_g_try_realloc, *II_g_free, *II_g_memdup, 
                          *II_g_malloc_n, *II_g_malloc0_n, *II_g_realloc_n, 
                          *II_g_try_malloc_n, *II_g_try_malloc0_n, 
-                         *II_g_try_realloc_n;
+                         *II_g_try_realloc_n, *II_reallocarray,
+                         *II_recallocarray, *II_freezero;
   mutable Optional<uint64_t> KernelZeroFlagVal;
 
   void initIdentifierInfo(ASTContext &C) const;
@@ -349,7 +351,8 @@
   static SVal evalMulForBufferSize(CheckerContext &C, const Expr *Blocks,
                                    const Expr *BlockBytes);
   static ProgramStateRef CallocMem(CheckerContext &C, const CallExpr *CE,
-                                   ProgramStateRef State);
+                                   ProgramStateRef State,
+                                   bool SuffixWithArray = false);
 
   ///\brief Check if the memory associated with this symbol was released.
   bool isReleased(SymbolRef Sym, CheckerContext &C) const;
@@ -611,6 +614,11 @@
   II_g_try_malloc_n = &Ctx.Idents.get("g_try_malloc_n");
   II_g_try_malloc0_n = &Ctx.Idents.get("g_try_malloc0_n");
   II_g_try_realloc_n = &Ctx.Idents.get("g_try_realloc_n");
+
+  // BSD
+  II_reallocarray = &Ctx.Idents.get("reallocarray");
+  II_recallocarray = &Ctx.Idents.get("recallocarray");
+  II_freezero = &Ctx.Idents.get("freezero");
 }
 
 bool MallocChecker::isMemFunction(const FunctionDecl *FD, ASTContext &C) const {
@@ -647,7 +655,7 @@
 
     if (Family == AF_Malloc && CheckFree) {
       if (FunI == II_free || FunI == II_realloc || FunI == II_reallocf || 
-          FunI == II_g_free)
+          FunI == II_g_free || FunI == II_freezero)
         return true;
     }
 
@@ -662,7 +670,8 @@
           FunI == II_g_memdup || FunI == II_g_malloc_n || 
           FunI == II_g_malloc0_n || FunI == II_g_realloc_n || 
           FunI == II_g_try_malloc_n || FunI == II_g_try_malloc0_n || 
-          FunI == II_g_try_realloc_n)
+          FunI == II_g_try_realloc_n || FunI == II_reallocarray ||
+          FunI == II_recallocarray)
         return true;
     }
 
@@ -878,7 +887,11 @@
       State = CallocMem(C, CE, State);
       State = ProcessZeroAllocation(C, CE, 0, State);
       State = ProcessZeroAllocation(C, CE, 1, State);
-    } else if (FunI == II_free || FunI == II_g_free) {
+    } else if (FunI == II_recallocarray) {
+      State = CallocMem(C, CE, State, true);
+      State = ProcessZeroAllocation(C, CE, 0, State);
+      State = ProcessZeroAllocation(C, CE, 1, State);
+    } else if (FunI == II_free || FunI == II_g_free || FunI == II_freezero) {
       State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);
     } else if (FunI == II_strdup || FunI == II_win_strdup ||
                FunI == II_wcsdup || FunI == II_win_wcsdup) {
@@ -943,7 +956,8 @@
       State = MallocMemAux(C, CE, TotalSize, Init, State);
       State = ProcessZeroAllocation(C, CE, 0, State);
       State = ProcessZeroAllocation(C, CE, 1, State);
-    } else if (FunI == II_g_realloc_n || FunI == II_g_try_realloc_n) {
+    } else if (FunI == II_g_realloc_n || FunI == II_g_try_realloc_n ||
+               FunI == II_reallocarray) {
       if (CE->getNumArgs() < 3)
         return;
       State = ReallocMemAux(C, CE, false, State, true);
@@ -2215,16 +2229,22 @@
 }
 
 ProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE,
-                                         ProgramStateRef State) {
+                                         ProgramStateRef State,
+                                         bool SuffixWithArray) {
   if (!State)
     return nullptr;
 
   if (CE->getNumArgs() < 2)
     return nullptr;
 
   SValBuilder &svalBuilder = C.getSValBuilder();
   SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
-  SVal TotalSize = evalMulForBufferSize(C, CE->getArg(0), CE->getArg(1));
+  SVal TotalSize;
+  if (!SuffixWithArray) {
+    TotalSize = evalMulForBufferSize(C, CE->getArg(0), CE->getArg(1));
+  } else {
+    TotalSize = evalMulForBufferSize(C, CE->getArg(2), CE->getArg(3));
+  }
 
   return MallocMemAux(C, CE, TotalSize, zeroVal, State);
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to