[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:
parent
ae134c6449
commit
d6e5fd52f0
|
@ -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;
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue