llvm/clang/test/Analysis/free.c
Christopher Di Bella 9830901b34 [clang] removes check against integral-to-pointer conversion...
... 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
2021-03-04 17:00:54 +00:00

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
}