cb424d7448
verify-patch-sanity.py validates every active recipe .patch has internally- consistent hunk line counts — catching the 'malformed patch at line N' failure at commit/CI/preflight time instead of hours into a cook. This cycle hit that class three times (qtwaylandscanner, sddm, xwayland), each only discovered when cookbook tried to apply the patch. Running it across the repo found 29 latent malformed patches (validated against GNU patch: e.g. relibc/P3-sysv-ipc reproduces 'malformed patch at line 22'). They were harmless only because they sit in vendored recipes (baked, not re- applied) — but would fail on any version-bump re-derivation. --fix recounts the hunk headers (body untouched) and repaired all 29. Wired into build-preflight.sh (Phase 1.0D) and redbear-ci.yml, with a unit test (test-patch-sanity.sh). Skips archived/legacy trees and unvalidatable formats (empty placeholders, bare-@@ git hunks).
247 lines
7.7 KiB
C++
247 lines
7.7 KiB
C++
// 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
|
|
}
|