9830901b34
... unless it's a literal D94640 was a bit too aggressive in its analysis, considering integers representing valid addresses as invalid. This change rolls back some of the check, so that only the most obvious case is still flagged. Before: ```cpp free((void*)1000); // literal converted to `void*`: warning good free((void*)an_int); // `int` object converted to `void*`: warning might // be a false positive ``` After ```cpp free((void*)1000); // literal converted to `void*`: warning good free((void*)an_int); // doesn't warn ``` Differential Revision: https://reviews.llvm.org/D97512
119 lines
3.6 KiB
C
119 lines
3.6 KiB
C
// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-store=region \
|
|
// RUN: -analyzer-checker=core \
|
|
// RUN: -analyzer-checker=unix.Malloc
|
|
//
|
|
// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-store=region \
|
|
// RUN: -analyzer-checker=core \
|
|
// RUN: -analyzer-checker=unix.Malloc \
|
|
// RUN: -analyzer-config unix.DynamicMemoryModeling:Optimistic=true
|
|
typedef __typeof(sizeof(int)) size_t;
|
|
void free(void *);
|
|
void *alloca(size_t);
|
|
|
|
void t1 () {
|
|
int a[] = { 1 };
|
|
free(a);
|
|
// expected-warning@-1{{Argument to free() is the address of the local variable 'a', which is not memory allocated by malloc()}}
|
|
// expected-warning@-2{{attempt to call free on non-heap object 'a'}}
|
|
}
|
|
|
|
void t2 () {
|
|
int a = 1;
|
|
free(&a);
|
|
// expected-warning@-1{{Argument to free() is the address of the local variable 'a', which is not memory allocated by malloc()}}
|
|
// expected-warning@-2{{attempt to call free on non-heap object 'a'}}
|
|
}
|
|
|
|
void t3 () {
|
|
static int a[] = { 1 };
|
|
free(a);
|
|
// expected-warning@-1{{Argument to free() is the address of the static variable 'a', which is not memory allocated by malloc()}}
|
|
// expected-warning@-2{{attempt to call free on non-heap object 'a'}}
|
|
}
|
|
|
|
void t4 (char *x) {
|
|
free(x); // no-warning
|
|
}
|
|
|
|
void t5 () {
|
|
extern char *ptr();
|
|
free(ptr()); // no-warning
|
|
}
|
|
|
|
void t6 () {
|
|
free((void*)1000);
|
|
// expected-warning@-1{{Argument to free() is a constant address (1000), which is not memory allocated by malloc()}}
|
|
// expected-warning@-2{{attempt to call free on non-heap object '(void *)1000'}}
|
|
}
|
|
|
|
void t7 (char **x) {
|
|
free(*x); // no-warning
|
|
}
|
|
|
|
void t8 (char **x) {
|
|
// ugh
|
|
free((*x)+8); // no-warning
|
|
}
|
|
|
|
void t9 () {
|
|
label:
|
|
free(&&label);
|
|
// expected-warning@-1{{Argument to free() is the address of the label 'label', which is not memory allocated by malloc()}}
|
|
// expected-warning@-2{{attempt to call free on non-heap object 'label'}}
|
|
}
|
|
|
|
void t10 () {
|
|
free((void*)&t10);
|
|
// expected-warning@-1{{Argument to free() is the address of the function 't10', which is not memory allocated by malloc()}}
|
|
// expected-warning@-2{{attempt to call free on non-heap object 't10'}}
|
|
}
|
|
|
|
void t11 () {
|
|
char *p = (char*)alloca(2);
|
|
free(p); // expected-warning {{Memory allocated by alloca() should not be deallocated}}
|
|
}
|
|
|
|
void t12 () {
|
|
char *p = (char*)__builtin_alloca(2);
|
|
free(p); // expected-warning {{Memory allocated by alloca() should not be deallocated}}
|
|
}
|
|
|
|
void t13 () {
|
|
free(^{return;});
|
|
// expected-warning@-1{{Argument to free() is a block, which is not memory allocated by malloc()}}
|
|
// expected-warning@-2{{attempt to call free on non-heap object: block expression}}
|
|
}
|
|
|
|
void t14 (char a) {
|
|
free(&a);
|
|
// expected-warning@-1{{Argument to free() is the address of the parameter 'a', which is not memory allocated by malloc()}}
|
|
// expected-warning@-2{{attempt to call free on non-heap object 'a'}}
|
|
}
|
|
|
|
static int someGlobal[2];
|
|
void t15 () {
|
|
free(someGlobal);
|
|
// expected-warning@-1{{Argument to free() is the address of the global variable 'someGlobal', which is not memory allocated by malloc()}}
|
|
// expected-warning@-2{{attempt to call free on non-heap object 'someGlobal'}}
|
|
}
|
|
|
|
void t16 (char **x, int offset) {
|
|
// Unknown value
|
|
free(x[offset]); // no-warning
|
|
}
|
|
|
|
int *iptr(void);
|
|
void t17(void) {
|
|
free(iptr); // Oops, forgot to call iptr().
|
|
// expected-warning@-1{{Argument to free() is the address of the function 'iptr', which is not memory allocated by malloc()}}
|
|
// expected-warning@-2{{attempt to call free on non-heap object 'iptr'}}
|
|
}
|
|
|
|
struct S {
|
|
const char* p;
|
|
};
|
|
|
|
void t18 (struct S s) {
|
|
free((void*)(unsigned long long)s.p); // no warning
|
|
}
|