]> granicus.if.org Git - clang/commitdiff
[analyzer] MallocChecker should not do post-call checks on inlined functions.
authorJordan Rose <jordan_rose@apple.com>
Thu, 20 Sep 2012 01:55:32 +0000 (01:55 +0000)
committerJordan Rose <jordan_rose@apple.com>
Thu, 20 Sep 2012 01:55:32 +0000 (01:55 +0000)
If someone provides their own function called 'strdup', or 'reallocf', or
even 'malloc', and we inlined it, the inlining should have given us all the
malloc-related information we need. If we then try to attach new information
to the return value, we could end up with spurious warnings.

<rdar://problem/12317671>

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

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

index c036d739dd4dd7baa05cc734d2bff7179873c9d7..3a27d552218712306bb51e7c929c6f52636e4d38 100644 (file)
@@ -442,6 +442,9 @@ bool MallocChecker::isFreeFunction(const FunctionDecl *FD, ASTContext &C) const
 }
 
 void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {
+  if (C.wasInlined)
+    return;
+  
   const FunctionDecl *FD = C.getCalleeDecl(CE);
   if (!FD)
     return;
index 0ab3a715585837b0a63344f2dcf51fd629a83a75..4aa6b7545c7230fef393e39b4b31f67bedc4b549 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=unix.Malloc -analyzer-inline-max-stack-depth=5 -analyzer-inline-max-function-size=6 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=unix.Malloc -analyzer-inline-max-stack-depth=5 -verify %s
 
 #include "Inputs/system-header-simulator.h"
 
@@ -9,7 +9,10 @@ void free(void *);
 void *realloc(void *ptr, size_t size);
 void *reallocf(void *ptr, size_t size);
 void *calloc(size_t nmemb, size_t size);
-extern void exit(int) __attribute__ ((__noreturn__));
+
+void exit(int) __attribute__ ((__noreturn__));
+void *memcpy(void * restrict s1, const void * restrict s2, size_t n);
+size_t strlen(const char *);
 
 static void my_malloc1(void **d, size_t size) {
   *d = malloc(size);
@@ -96,3 +99,34 @@ int uafAndCallsFooWithEmptyReturn() {
   fooWithEmptyReturn(12);
   return *x; // expected-warning {{Use of memory after it is freed}}
 }
+
+
+// If we inline any of the malloc-family functions, the checker shouldn't also
+// try to do additional modeling. <rdar://problem/12317671>
+char *strndup(const char *str, size_t n) {
+  if (!str)
+    return 0;
+  
+  // DO NOT FIX. This is to test that we are actually using the inlined
+  // behavior!
+  if (n < 5)
+    return 0;
+  
+  size_t length = strlen(str);
+  if (length < n)
+    n = length;
+  
+  char *result = malloc(n + 1);
+  memcpy(result, str, n);
+  result[n] = '\0';
+  return result;
+}
+
+void useStrndup(size_t n) {
+  if (n == 0)
+    (void)strndup(0, 20); // no-warning
+  else if (n < 5)
+    (void)strndup("hi there", n); // no-warning
+  else
+    (void)strndup("hi there", n); // expected-warning{{leak}}
+}