r297323 - [analyzer] Teach the MallocChecker about about Glib API
Anna Zaks via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 8 16:01:01 PST 2017
Author: zaks
Date: Wed Mar 8 18:01:01 2017
New Revision: 297323
URL: http://llvm.org/viewvc/llvm-project?rev=297323&view=rev
Log:
[analyzer] Teach the MallocChecker about about Glib API
A patch by Leslie Zhai!
Differential Revision: https://reviews.llvm.org/D28348
Added:
cfe/trunk/test/Analysis/gmalloc.c
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=297323&r1=297322&r2=297323&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Wed Mar 8 18:01:01 2017
@@ -174,7 +174,10 @@ public:
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_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 +239,9 @@ private:
*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_free, *II_g_memdup;
mutable Optional<uint64_t> KernelZeroFlagVal;
void initIdentifierInfo(ASTContext &C) const;
@@ -554,6 +559,16 @@ void MallocChecker::initIdentifierInfo(A
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_free = &Ctx.Idents.get("g_free");
+ II_g_memdup = &Ctx.Idents.get("g_memdup");
}
bool MallocChecker::isMemFunction(const FunctionDecl *FD, ASTContext &C) const {
@@ -589,7 +604,8 @@ bool MallocChecker::isCMemFunction(const
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;
}
@@ -597,7 +613,11 @@ bool MallocChecker::isCMemFunction(const
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_memdup)
return true;
}
@@ -762,7 +782,7 @@ void MallocChecker::checkPostStmt(const
initIdentifierInfo(C.getASTContext());
IdentifierInfo *FunI = FD->getIdentifier();
- if (FunI == II_malloc) {
+ if (FunI == II_malloc || FunI == II_g_malloc || FunI == II_g_try_malloc) {
if (CE->getNumArgs() < 1)
return;
if (CE->getNumArgs() < 3) {
@@ -791,7 +811,8 @@ void MallocChecker::checkPostStmt(const
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) {
State = ReallocMem(C, CE, false, State);
State = ProcessZeroAllocation(C, CE, 1, State);
} else if (FunI == II_reallocf) {
@@ -801,7 +822,7 @@ void MallocChecker::checkPostStmt(const
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) {
@@ -841,6 +862,18 @@ void MallocChecker::checkPostStmt(const
AF_IfNameIndex);
} else if (FunI == II_if_freenameindex) {
State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);
+ } else if (FunI == II_g_malloc0 || FunI == II_g_try_malloc0) {
+ if (CE->getNumArgs() < 1)
+ return;
+ SValBuilder &svalBuilder = C.getSValBuilder();
+ SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
+ State = MallocMemAux(C, CE, CE->getArg(0), zeroVal, State);
+ State = ProcessZeroAllocation(C, CE, 0, State);
+ } else if (FunI == II_g_memdup) {
+ if (CE->getNumArgs() < 2)
+ return;
+ State = MallocMemAux(C, CE, CE->getArg(1), UndefinedVal(), State);
+ State = ProcessZeroAllocation(C, CE, 1, State);
}
}
Added: cfe/trunk/test/Analysis/gmalloc.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/gmalloc.c?rev=297323&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/gmalloc.c (added)
+++ cfe/trunk/test/Analysis/gmalloc.c Wed Mar 8 18:01:01 2017
@@ -0,0 +1,59 @@
+// 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);
+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);
+
+ 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);
+
+ 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'}}
+
+ g_free(g1);
+ g_free(g2);
+ g_free(g3);
+}
More information about the cfe-commits
mailing list