]> granicus.if.org Git - clang/commitdiff
[analyzer] Malloc Checker: add support for valloc + minor code
authorAnna Zaks <ganna@apple.com>
Wed, 15 Feb 2012 00:11:22 +0000 (00:11 +0000)
committerAnna Zaks <ganna@apple.com>
Wed, 15 Feb 2012 00:11:22 +0000 (00:11 +0000)
hardening.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150532 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Checkers/MallocChecker.cpp
test/Analysis/malloc.c

index d57e8a9f621adb018fe0a27bddb5730bb6395fc0..1191cf8d902a9140bfa9cc0ab1d1d2faa1976bf0 100644 (file)
@@ -82,10 +82,12 @@ class MallocChecker : public Checker<check::DeadSymbols,
   mutable OwningPtr<BuiltinBug> BT_UseFree;
   mutable OwningPtr<BuiltinBug> BT_UseRelinquished;
   mutable OwningPtr<BuiltinBug> BT_BadFree;
-  mutable IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc;
+  mutable IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc,
+                         *II_valloc;
 
 public:
-  MallocChecker() : II_malloc(0), II_free(0), II_realloc(0), II_calloc(0) {}
+  MallocChecker() : II_malloc(0), II_free(0), II_realloc(0), II_calloc(0),
+                    II_valloc(0) {}
 
   /// In pessimistic mode, the checker assumes that it does not know which
   /// functions might free the memory.
@@ -241,6 +243,8 @@ void MallocChecker::initIdentifierInfo(ASTContext &Ctx) const {
     II_realloc = &Ctx.Idents.get("realloc");
   if (!II_calloc)
     II_calloc = &Ctx.Idents.get("calloc");
+  if (!II_valloc)
+    II_valloc = &Ctx.Idents.get("valloc");
 }
 
 bool MallocChecker::isMemFunction(const FunctionDecl *FD, ASTContext &C) const {
@@ -251,7 +255,7 @@ bool MallocChecker::isMemFunction(const FunctionDecl *FD, ASTContext &C) const {
 
   // TODO: Add more here : ex: reallocf!
   if (FunI == II_malloc || FunI == II_free ||
-      FunI == II_realloc || FunI == II_calloc)
+      FunI == II_realloc || FunI == II_calloc || FunI == II_valloc)
     return true;
 
   if (Filter.CMallocOptimistic && FD->hasAttrs() &&
@@ -267,23 +271,22 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {
   const FunctionDecl *FD = C.getCalleeDecl(CE);
   if (!FD)
     return;
+
   initIdentifierInfo(C.getASTContext());
+  IdentifierInfo *FunI = FD->getIdentifier();
+  if (!FunI)
+    return;
 
-  if (FD->getIdentifier() == II_malloc) {
+  if (FunI == II_malloc || FunI == II_valloc) {
     MallocMem(C, CE);
     return;
-  }
-  if (FD->getIdentifier() == II_realloc) {
+  } else if (FunI == II_realloc) {
     ReallocMem(C, CE);
     return;
-  }
-
-  if (FD->getIdentifier() == II_calloc) {
+  } else if (FunI == II_calloc) {
     CallocMem(C, CE);
     return;
-  }
-
-  if (FD->getIdentifier() == II_free) {
+  }else if (FunI == II_free) {
     FreeMem(C, CE);
     return;
   }
@@ -343,6 +346,10 @@ ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
   // Get the return value.
   SVal retVal = state->getSVal(CE, C.getLocationContext());
 
+  // We expect the malloc functions to return a pointer.
+  if (!isa<Loc>(retVal))
+    return 0;
+
   // Fill the region with the initialization value.
   state = state->bindDefault(retVal, Init);
 
index 0aa9291255998e6c34a94446d83574be49993640..dce088e50d979374c7c132caa14a76926ef3a5f0 100644 (file)
@@ -3,6 +3,7 @@
 
 typedef __typeof(sizeof(int)) size_t;
 void *malloc(size_t);
+void *valloc(size_t);
 void free(void *);
 void *realloc(void *ptr, size_t size);
 void *calloc(size_t nmemb, size_t size);
@@ -406,6 +407,18 @@ void mallocFailedOrNotLeak() {
     return; // expected-warning {{Allocated memory never released. Potential memory leak.}}
 }
 
+int vallocTest() {
+  char *mem = valloc(12);
+  return 0; // expected-warning {{Allocated memory never released. Potential memory leak.}}
+}
+
+void vallocEscapeFreeUse() {
+  int *p = valloc(12);
+  myfoo(p);
+  free(p);
+  myfoo(p); // expected-warning{{Use of dynamically allocated memory after it is freed.}}
+}
+
 int *Gl;
 struct GlStTy {
   int *x;