aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/StaticAnalyzer/Checkers/MallocChecker.cpp3
-rw-r--r--test/Analysis/malloc-interprocedural.c38
2 files changed, 39 insertions, 2 deletions
diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index c036d739dd..3a27d55221 100644
--- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -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;
diff --git a/test/Analysis/malloc-interprocedural.c b/test/Analysis/malloc-interprocedural.c
index 0ab3a71558..4aa6b7545c 100644
--- a/test/Analysis/malloc-interprocedural.c
+++ b/test/Analysis/malloc-interprocedural.c
@@ -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}}
+}