xiangzhai updated this revision to Diff 83758.
xiangzhai marked 2 inline comments as done.
xiangzhai added a comment.

make II_g_*malloc*_n sense


Repository:
  rL LLVM

https://reviews.llvm.org/D28348

Files:
  lib/StaticAnalyzer/Checkers/MallocChecker.cpp
  test/Analysis/gmalloc.c

Index: test/Analysis/gmalloc.c
===================================================================
--- test/Analysis/gmalloc.c
+++ test/Analysis/gmalloc.c
@@ -0,0 +1,169 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc -analyzer-store=region -verify %s
+
+#include "Inputs/system-header-simulator.h"
+
+typedef void* gpointer;
+typedef const void* gconstpointer;
+typedef unsigned long gsize;
+typedef unsigned int guint;
+
+gpointer g_malloc(gsize n_bytes);
+gpointer g_malloc0(gsize n_bytes);
+gpointer g_realloc(gpointer mem, gsize n_bytes);
+gpointer g_try_malloc(gsize n_bytes);
+gpointer g_try_malloc0(gsize n_bytes);
+gpointer g_try_realloc(gpointer mem, gsize n_bytes);
+gpointer g_malloc_n(gsize n_blocks, gsize n_block_bytes);
+gpointer g_malloc0_n(gsize n_blocks, gsize n_block_bytes);
+gpointer g_realloc_n(gpointer mem, gsize n_blocks, gsize n_block_bytes);
+gpointer g_try_malloc_n(gsize n_blocks, gsize n_block_bytes);
+gpointer g_try_malloc0_n(gsize n_blocks, gsize n_block_bytes);
+gpointer g_try_realloc_n(gpointer mem, gsize n_blocks, gsize n_block_bytes);
+void g_free(gpointer mem);
+gpointer g_memdup(gconstpointer mem, guint byte_size);
+
+static const gsize n_bytes = 1024;
+
+void f1() {
+  gpointer g1 = g_malloc(n_bytes);
+  gpointer g2 = g_malloc0(n_bytes);
+  g1 = g_realloc(g1, n_bytes * 2);
+  gpointer g3 = g_try_malloc(n_bytes);
+  gpointer g4 = g_try_malloc0(n_bytes);
+  g3 = g_try_realloc(g3, n_bytes * 2);
+  gpointer g5 = g_malloc_n(n_bytes, sizeof(char));
+  gpointer g6 = g_malloc0_n(n_bytes, sizeof(char));
+  g5 = g_realloc_n(g5, n_bytes * 2, sizeof(char));
+  gpointer g7 = g_try_malloc_n(n_bytes, sizeof(char));
+  gpointer g8 = g_try_malloc0_n(n_bytes, sizeof(char));
+  g7 = g_try_realloc_n(g7, n_bytes * 2, sizeof(char));
+
+  g_free(g1);
+  g_free(g2);
+  g_free(g2); // expected-warning{{Attempt to free released memory}}
+}
+
+void f2() {
+  gpointer g1 = g_malloc(n_bytes);
+  gpointer g2 = g_malloc0(n_bytes);
+  g1 = g_realloc(g1, n_bytes * 2);
+  gpointer g3 = g_try_malloc(n_bytes);
+  gpointer g4 = g_try_malloc0(n_bytes);
+  g3 = g_try_realloc(g3, n_bytes * 2);
+  gpointer g5 = g_malloc_n(n_bytes, sizeof(char));
+  gpointer g6 = g_malloc0_n(n_bytes, sizeof(char));
+  g5 = g_realloc_n(g5, n_bytes * 2, sizeof(char));
+  gpointer g7 = g_try_malloc_n(n_bytes, sizeof(char));
+  gpointer g8 = g_try_malloc0_n(n_bytes, sizeof(char));
+  g7 = g_try_realloc_n(g7, n_bytes * 2, sizeof(char));
+
+  g_free(g1);
+  g_free(g2);
+  g_free(g3);
+  g3 = g_memdup(g3, n_bytes); // expected-warning{{Use of memory after it is freed}}
+}
+
+void f3() {
+  gpointer g1 = g_malloc(n_bytes);
+  gpointer g2 = g_malloc0(n_bytes);
+  g1 = g_realloc(g1, n_bytes * 2);
+  gpointer g3 = g_try_malloc(n_bytes);
+  gpointer g4 = g_try_malloc0(n_bytes);
+  g3 = g_try_realloc(g3, n_bytes * 2); // expected-warning{{Potential leak of memory pointed to by 'g4'}}
+  gpointer g5 = g_malloc_n(n_bytes, sizeof(char));
+  gpointer g6 = g_malloc0_n(n_bytes, sizeof(char));
+  g5 = g_realloc_n(g5, n_bytes * 2, sizeof(char)); // expected-warning{{Potential leak of memory pointed to by 'g6'}}
+  gpointer g7 = g_try_malloc_n(n_bytes, sizeof(char)); // expected-warning{{Potential leak of memory pointed to by 'g5'}}
+  gpointer g8 = g_try_malloc0_n(n_bytes, sizeof(char));
+  g7 = g_try_realloc_n(g7, n_bytes * 2, sizeof(char)); // expected-warning{{Potential leak of memory pointed to by 'g8'}}
+
+  g_free(g1); // expected-warning{{Potential leak of memory pointed to by 'g7'}}
+  g_free(g2);
+  g_free(g3);
+}
+
+void f4() {
+  gpointer g1 = g_malloc(n_bytes);
+  gpointer g2 = g_malloc0(n_bytes);
+  g1 = g_realloc(g1, n_bytes * 2);
+  gpointer g3 = g_try_malloc(n_bytes);
+  gpointer g4 = g_try_malloc0(n_bytes);
+  g3 = g_try_realloc(g3, n_bytes * 2);
+  gpointer g5 = g_malloc_n(n_bytes, sizeof(char));
+  gpointer g6 = g_malloc0_n(n_bytes, sizeof(char));
+  g5 = g_realloc_n(g5, n_bytes * 2, sizeof(char)); // expected-warning{{Potential leak of memory pointed to by 'g6'}}
+  gpointer g7 = g_try_malloc_n(n_bytes, sizeof(char)); // expected-warning{{Potential leak of memory pointed to by 'g5'}}
+  gpointer g8 = g_try_malloc0_n(n_bytes, sizeof(char));
+  g7 = g_try_realloc_n(g7, n_bytes * 2, sizeof(char)); // expected-warning{{Potential leak of memory pointed to by 'g8'}}
+
+  g_free(g1); // expected-warning{{Potential leak of memory pointed to by 'g7'}}
+  g_free(g2);
+  g_free(g3);
+  g_free(g4);
+}
+
+void f5() {
+  gpointer g1 = g_malloc(n_bytes);
+  gpointer g2 = g_malloc0(n_bytes);
+  g1 = g_realloc(g1, n_bytes * 2);
+  gpointer g3 = g_try_malloc(n_bytes);
+  gpointer g4 = g_try_malloc0(n_bytes);
+  g3 = g_try_realloc(g3, n_bytes * 2);
+  gpointer g5 = g_malloc_n(n_bytes, sizeof(char));
+  gpointer g6 = g_malloc0_n(n_bytes, sizeof(char));
+  g5 = g_realloc_n(g5, n_bytes * 2, sizeof(char)); // expected-warning{{Potential leak of memory pointed to by 'g6'}}
+  gpointer g7 = g_try_malloc_n(n_bytes, sizeof(char));
+  gpointer g8 = g_try_malloc0_n(n_bytes, sizeof(char));
+  g7 = g_try_realloc_n(g7, n_bytes * 2, sizeof(char)); // expected-warning{{Potential leak of memory pointed to by 'g8'}}
+
+  g_free(g1); // expected-warning{{Potential leak of memory pointed to by 'g7'}}
+  g_free(g2);
+  g_free(g3);
+  g_free(g4);
+  g_free(g5);
+}
+
+void f6() {
+  gpointer g1 = g_malloc(n_bytes);
+  gpointer g2 = g_malloc0(n_bytes);
+  g1 = g_realloc(g1, n_bytes * 2);
+  gpointer g3 = g_try_malloc(n_bytes);
+  gpointer g4 = g_try_malloc0(n_bytes);
+  g3 = g_try_realloc(g3, n_bytes * 2);
+  gpointer g5 = g_malloc_n(n_bytes, sizeof(char));
+  gpointer g6 = g_malloc0_n(n_bytes, sizeof(char));
+  g5 = g_realloc_n(g5, n_bytes * 2, sizeof(char));
+  gpointer g7 = g_try_malloc_n(n_bytes, sizeof(char));
+  gpointer g8 = g_try_malloc0_n(n_bytes, sizeof(char));
+  g7 = g_try_realloc_n(g7, n_bytes * 2, sizeof(char)); // expected-warning{{Potential leak of memory pointed to by 'g8'}}
+
+  g_free(g1); // expected-warning{{Potential leak of memory pointed to by 'g7'}}
+  g_free(g2);
+  g_free(g3);
+  g_free(g4);
+  g_free(g5);
+  g_free(g6);
+}
+
+void f7() {
+  gpointer g1 = g_malloc(n_bytes);
+  gpointer g2 = g_malloc0(n_bytes);
+  g1 = g_realloc(g1, n_bytes * 2);
+  gpointer g3 = g_try_malloc(n_bytes);
+  gpointer g4 = g_try_malloc0(n_bytes);
+  g3 = g_try_realloc(g3, n_bytes * 2);
+  gpointer g5 = g_malloc_n(n_bytes, sizeof(char));
+  gpointer g6 = g_malloc0_n(n_bytes, sizeof(char));
+  g5 = g_realloc_n(g5, n_bytes * 2, sizeof(char));
+  gpointer g7 = g_try_malloc_n(n_bytes, sizeof(char));
+  gpointer g8 = g_try_malloc0_n(n_bytes, sizeof(char));
+  g7 = g_try_realloc_n(g7, n_bytes * 2, sizeof(char)); // expected-warning{{Potential leak of memory pointed to by 'g8'}}
+
+  g_free(g1);
+  g_free(g2);
+  g_free(g3);
+  g_free(g4);
+  g_free(g5);
+  g_free(g6);
+  g_free(g7);
+}
Index: lib/StaticAnalyzer/Checkers/MallocChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -174,7 +174,13 @@
         II_valloc(nullptr), II_reallocf(nullptr), II_strndup(nullptr),
         II_strdup(nullptr), II_win_strdup(nullptr), II_kmalloc(nullptr),
         II_if_nameindex(nullptr), II_if_freenameindex(nullptr),
-        II_wcsdup(nullptr), II_win_wcsdup(nullptr) {}
+        II_wcsdup(nullptr), II_win_wcsdup(nullptr), II_g_malloc(nullptr),
+        II_g_malloc0(nullptr), II_g_realloc(nullptr), II_g_try_malloc(nullptr), 
+        II_g_try_malloc0(nullptr), II_g_try_realloc(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_free(nullptr), II_g_memdup(nullptr) {}
 
   /// In pessimistic mode, the checker assumes that it does not know which
   /// functions might free the memory.
@@ -236,7 +242,12 @@
                          *II_realloc, *II_calloc, *II_valloc, *II_reallocf,
                          *II_strndup, *II_strdup, *II_win_strdup, *II_kmalloc,
                          *II_if_nameindex, *II_if_freenameindex, *II_wcsdup,
-                         *II_win_wcsdup;
+                         *II_win_wcsdup, *II_g_malloc, *II_g_malloc0, 
+                         *II_g_realloc, *II_g_try_malloc, *II_g_try_malloc0, 
+                         *II_g_try_realloc, *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_free, *II_g_memdup;
   mutable Optional<uint64_t> KernelZeroFlagVal;
 
   void initIdentifierInfo(ASTContext &C) const;
@@ -554,6 +565,22 @@
   II_win_strdup = &Ctx.Idents.get("_strdup");
   II_win_wcsdup = &Ctx.Idents.get("_wcsdup");
   II_win_alloca = &Ctx.Idents.get("_alloca");
+
+  // Glib
+  II_g_malloc = &Ctx.Idents.get("g_malloc");
+  II_g_malloc0 = &Ctx.Idents.get("g_malloc0");
+  II_g_realloc = &Ctx.Idents.get("g_realloc");
+  II_g_try_malloc = &Ctx.Idents.get("g_try_malloc");
+  II_g_try_malloc0 = &Ctx.Idents.get("g_try_malloc0");
+  II_g_try_realloc = &Ctx.Idents.get("g_try_realloc");
+  II_g_malloc_n = &Ctx.Idents.get("g_malloc_n");
+  II_g_malloc0_n = &Ctx.Idents.get("g_malloc0_n");
+  II_g_realloc_n = &Ctx.Idents.get("g_realloc_n");
+  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");
+  II_g_free = &Ctx.Idents.get("g_free");
+  II_g_memdup = &Ctx.Idents.get("g_memdup");
 }
 
 bool MallocChecker::isMemFunction(const FunctionDecl *FD, ASTContext &C) const {
@@ -589,15 +616,23 @@
     initIdentifierInfo(C);
 
     if (Family == AF_Malloc && CheckFree) {
-      if (FunI == II_free || FunI == II_realloc || FunI == II_reallocf)
+      if (FunI == II_free || FunI == II_realloc || FunI == II_reallocf || 
+          FunI == II_g_free)
         return true;
     }
 
     if (Family == AF_Malloc && CheckAlloc) {
       if (FunI == II_malloc || FunI == II_realloc || FunI == II_reallocf ||
           FunI == II_calloc || FunI == II_valloc || FunI == II_strdup ||
           FunI == II_win_strdup || FunI == II_strndup || FunI == II_wcsdup ||
-          FunI == II_win_wcsdup || FunI == II_kmalloc)
+          FunI == II_win_wcsdup || FunI == II_kmalloc ||
+          FunI == II_g_malloc || FunI == II_g_malloc0 || 
+          FunI == II_g_realloc || FunI == II_g_try_malloc || 
+          FunI == II_g_try_malloc0 || FunI == II_g_try_realloc ||
+          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_memdup)
         return true;
     }
 
@@ -762,13 +797,17 @@
     initIdentifierInfo(C.getASTContext());
     IdentifierInfo *FunI = FD->getIdentifier();
 
-    if (FunI == II_malloc) {
+    if (FunI == II_malloc || FunI == II_g_malloc || FunI == II_g_malloc0 ||
+        FunI == II_g_try_malloc || FunI == II_g_try_malloc0 || 
+        FunI == II_g_malloc_n || FunI == II_g_malloc0_n || 
+        FunI == II_g_try_malloc_n || FunI == II_g_try_malloc0_n) {
       if (CE->getNumArgs() < 1)
         return;
       if (CE->getNumArgs() < 3) {
         State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);
-        if (CE->getNumArgs() == 1)
-          State = ProcessZeroAllocation(C, CE, 0, State);
+        State = ProcessZeroAllocation(C, CE, 0, State);
+        if (CE->getNumArgs() == 2)
+          State = ProcessZeroAllocation(C, CE, 1, State);
       } else if (CE->getNumArgs() == 3) {
         llvm::Optional<ProgramStateRef> MaybeState =
           performKernelMalloc(CE, C, State);
@@ -791,17 +830,20 @@
         return;
       State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);
       State = ProcessZeroAllocation(C, CE, 0, State);
-    } else if (FunI == II_realloc) {
+    } else if (FunI == II_realloc || FunI == II_g_realloc || 
+               FunI == II_g_try_realloc || FunI == II_g_realloc_n || 
+               FunI == II_g_try_realloc_n ||  FunI == II_g_memdup) {
       State = ReallocMem(C, CE, false, State);
       State = ProcessZeroAllocation(C, CE, 1, State);
+      if (CE->getNumArgs() > 2)
+        State = ProcessZeroAllocation(C, CE, 2, State);
     } else if (FunI == II_reallocf) {
       State = ReallocMem(C, CE, true, State);
       State = ProcessZeroAllocation(C, CE, 1, State);
     } else if (FunI == II_calloc) {
       State = CallocMem(C, CE, State);
       State = ProcessZeroAllocation(C, CE, 0, State);
-      State = ProcessZeroAllocation(C, CE, 1, State);
-    } else if (FunI == II_free) {
+    } else if (FunI == II_free || FunI == II_g_free) {
       State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);
     } else if (FunI == II_strdup || FunI == II_win_strdup ||
                FunI == II_wcsdup || FunI == II_win_wcsdup) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to