| // RUN: %clang_analyze_cc1 -fblocks -verify %s \ | |
| // RUN: -analyzer-checker=core \ | |
| // RUN: -analyzer-checker=unix.Malloc | |
| // | |
| // RUN: %clang_analyze_cc1 -fblocks -verify %s \ | |
| // RUN: -analyzer-checker=core \ | |
| // RUN: -analyzer-checker=unix.Malloc \ | |
| // RUN: -analyzer-config unix.DynamicMemoryModeling:Optimistic=true | |
| namespace std { | |
| using size_t = decltype(sizeof(int)); | |
| void free(void *); | |
| } | |
| extern "C" void free(void *); | |
| extern "C" void *alloca(std::size_t); | |
| void t1a () { | |
| 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 t1b () { | |
| int a[] = { 1 }; | |
| std::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 std::free on non-heap object 'a'}} | |
| } | |
| void t2a () { | |
| 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 t2b () { | |
| int a = 1; | |
| std::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 std::free on non-heap object 'a'}} | |
| } | |
| void t3a () { | |
| 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 t3b () { | |
| static int a[] = { 1 }; | |
| std::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 std::free on non-heap object 'a'}} | |
| } | |
| void t4a (char *x) { | |
| free(x); // no-warning | |
| } | |
| void t4b (char *x) { | |
| std::free(x); // no-warning | |
| } | |
| void t5a () { | |
| extern char *ptr(); | |
| free(ptr()); // no-warning | |
| } | |
| void t5b () { | |
| extern char *ptr(); | |
| std::free(ptr()); // no-warning | |
| } | |
| void t6a () { | |
| 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 t6b () { | |
| std::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 std::free on non-heap object '(void *)1000'}} | |
| } | |
| void t7a (char **x) { | |
| free(*x); // no-warning | |
| } | |
| void t7b (char **x) { | |
| std::free(*x); // no-warning | |
| } | |
| void t8a (char **x) { | |
| // ugh | |
| free((*x)+8); // no-warning | |
| } | |
| void t8b (char **x) { | |
| // ugh | |
| std::free((*x)+8); // no-warning | |
| } | |
| void t9a () { | |
| 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 t9b () { | |
| label: | |
| std::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 std::free on non-heap object 'label'}} | |
| } | |
| void t10a () { | |
| free((void*)&t10a); | |
| // expected-warning@-1{{Argument to 'free()' is the address of the function 't10a', which is not memory allocated by 'malloc()'}} | |
| // expected-warning@-2{{attempt to call free on non-heap object 't10a'}} | |
| } | |
| void t10b () { | |
| std::free((void*)&t10b); | |
| // expected-warning@-1{{Argument to 'free()' is the address of the function 't10b', which is not memory allocated by 'malloc()'}} | |
| // expected-warning@-2{{attempt to call std::free on non-heap object 't10b'}} | |
| } | |
| void t11a () { | |
| char *p = (char*)alloca(2); | |
| free(p); // expected-warning {{Memory allocated by 'alloca()' should not be deallocated}} | |
| } | |
| void t11b () { | |
| char *p = (char*)alloca(2); | |
| std::free(p); // expected-warning {{Memory allocated by 'alloca()' should not be deallocated}} | |
| } | |
| void t12a () { | |
| char *p = (char*)__builtin_alloca(2); | |
| free(p); // expected-warning {{Memory allocated by 'alloca()' should not be deallocated}} | |
| } | |
| void t12b () { | |
| char *p = (char*)__builtin_alloca(2); | |
| std::free(p); // expected-warning {{Memory allocated by 'alloca()' should not be deallocated}} | |
| } | |
| void t13a () { | |
| 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 t13b () { | |
| std::free(^{return;}); | |
| // expected-warning@-1{{Argument to 'free()' is a block, which is not memory allocated by 'malloc()'}} | |
| // expected-warning@-2{{attempt to call std::free on non-heap object: block expression}} | |
| } | |
| void t14a () { | |
| free((void *)+[]{ return; }); | |
| // expected-warning@-1{{Argument to 'free()' is the address of the function '__invoke', which is not memory allocated by 'malloc()'}} | |
| // expected-warning@-2{{attempt to call free on non-heap object: lambda-to-function-pointer conversion}} | |
| } | |
| void t14b () { | |
| std::free((void *)+[]{ return; }); | |
| // expected-warning@-1{{Argument to 'free()' is the address of the function '__invoke', which is not memory allocated by 'malloc()'}} | |
| // expected-warning@-2{{attempt to call std::free on non-heap object: lambda-to-function-pointer conversion}} | |
| } | |
| void t15a (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'}} | |
| } | |
| void t15b (char a) { | |
| std::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 std::free on non-heap object 'a'}} | |
| } | |
| static int someGlobal[2]; | |
| void t16a () { | |
| 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 t16b () { | |
| std::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 std::free on non-heap object 'someGlobal'}} | |
| } | |
| void t17a (char **x, int offset) { | |
| // Unknown value | |
| free(x[offset]); // no-warning | |
| } | |
| void t17b (char **x, int offset) { | |
| // Unknown value | |
| std::free(x[offset]); // no-warning | |
| } | |
| struct S { | |
| const char* p; | |
| }; | |
| void t18_C_style_C_style_free (S s) { | |
| free((void*)(unsigned long long)s.p); // no warning | |
| } | |
| void t18_C_style_C_style_std_free (S s) { | |
| std::free((void*)(unsigned long long)s.p); // no warning | |
| } | |
| void t18_C_style_reinterpret_free (S s) { | |
| free((void*)reinterpret_cast<unsigned long long>(s.p)); // no warning | |
| } | |
| void t18_C_style_reinterpret_std_free (S s) { | |
| std::free((void*)reinterpret_cast<unsigned long long>(s.p)); // no warning | |
| } | |
| void t18_reinterpret_C_style_free (S s) { | |
| free(reinterpret_cast<void*>((unsigned long long)(s.p))); // no warning | |
| } | |
| void t18_reinterpret_C_style_std_free (S s) { | |
| std::free(reinterpret_cast<void*>((unsigned long long)(s.p))); // no warning | |
| } | |
| void t18_reinterpret_reinterpret_free (S s) { | |
| free(reinterpret_cast<void*>(reinterpret_cast<unsigned long long>(s.p))); // no warning | |
| } | |
| void t18_reinterpret_reinterpret_std_free (S s) { | |
| std::free(reinterpret_cast<void*>(reinterpret_cast<unsigned long long>(s.p))); // no warning | |
| } |