[analyzer] MallocChecker should not do post-call checks on inlined functions.

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>

llvm-svn: 164276
This commit is contained in:
Jordan Rose 2012-09-20 01:55:32 +00:00
parent ae134c6449
commit d6e5fd52f0
2 changed files with 39 additions and 2 deletions

View 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;

View 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}}
}