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).
468 lines
13 KiB
C++
468 lines
13 KiB
C++
// RUN: %clang_analyze_cc1 -std=c++11 %s \
|
|
// RUN: -analyzer-checker=core \
|
|
// RUN: -analyzer-checker=cplusplus.NewDelete \
|
|
// RUN: -analyzer-checker=cplusplus.PlacementNew \
|
|
// RUN: -analyzer-output=text -verify \
|
|
// RUN: -triple x86_64-unknown-linux-gnu
|
|
|
|
#include "Inputs/system-header-simulator-cxx.h"
|
|
|
|
void f() {
|
|
short s; // expected-note {{'s' declared without an initial value}}
|
|
long *lp = ::new (&s) long; // expected-warning{{Storage provided to placement new is only 2 bytes, whereas the allocated type requires 8 bytes}} expected-note 3 {{}}
|
|
(void)lp;
|
|
}
|
|
|
|
namespace testArrayNew {
|
|
void f() {
|
|
short s; // expected-note {{'s' declared without an initial value}}
|
|
char *buf = ::new (&s) char[8]; // expected-warning{{Storage provided to placement new is only 2 bytes, whereas the allocated type requires 8 bytes}} expected-note 3 {{}}
|
|
(void)buf;
|
|
}
|
|
} // namespace testArrayNew
|
|
|
|
namespace testBufferInOtherFun {
|
|
void f(void *place) {
|
|
long *lp = ::new (place) long; // expected-warning{{Storage provided to placement new is only 2 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
|
|
(void)lp;
|
|
}
|
|
void g() {
|
|
short buf; // expected-note {{'buf' declared without an initial value}}
|
|
f(&buf); // expected-note 2 {{}}
|
|
}
|
|
} // namespace testBufferInOtherFun
|
|
|
|
namespace testArrayBuffer {
|
|
void f(void *place) {
|
|
long *lp = ::new (place) long; // expected-warning{{Storage provided to placement new is only 2 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
|
|
(void)lp;
|
|
}
|
|
void g() {
|
|
char buf[2]; // expected-note {{'buf' initialized here}}
|
|
f(&buf); // expected-note 2 {{}}
|
|
}
|
|
} // namespace testArrayBuffer
|
|
|
|
namespace testGlobalPtrAsPlace {
|
|
void *gptr = nullptr;
|
|
short gs;
|
|
void f() {
|
|
gptr = &gs; // expected-note {{Value assigned to 'gptr'}}
|
|
}
|
|
void g() {
|
|
f(); // expected-note 2 {{}}
|
|
long *lp = ::new (gptr) long; // expected-warning{{Storage provided to placement new is only 2 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
|
|
(void)lp;
|
|
}
|
|
} // namespace testGlobalPtrAsPlace
|
|
|
|
namespace testRvalue {
|
|
short gs;
|
|
void *f() {
|
|
return &gs;
|
|
}
|
|
void g() {
|
|
long *lp = ::new (f()) long; // expected-warning{{Storage provided to placement new is only 2 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
|
|
(void)lp;
|
|
}
|
|
} // namespace testRvalue
|
|
|
|
namespace testNoWarning {
|
|
void *f();
|
|
void g() {
|
|
long *lp = ::new (f()) long;
|
|
(void)lp;
|
|
}
|
|
} // namespace testNoWarning
|
|
|
|
namespace testPtrToArrayAsPlace {
|
|
void f() {
|
|
//char *st = new char [8];
|
|
char buf[3]; // expected-note {{'buf' initialized here}}
|
|
void *st = buf; // expected-note {{'st' initialized here}}
|
|
long *lp = ::new (st) long; // expected-warning{{Storage provided to placement new is only 3 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
|
|
(void)lp;
|
|
}
|
|
} // namespace testPtrToArrayAsPlace
|
|
|
|
namespace testPtrToArrayWithOffsetAsPlace {
|
|
void f() {
|
|
int buf[3]; // expected-note {{'buf' initialized here}}
|
|
long *lp = ::new (buf + 2) long; // expected-warning{{Storage provided to placement new is only 4 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
|
|
(void)lp;
|
|
}
|
|
} // namespace testPtrToArrayWithOffsetAsPlace
|
|
|
|
namespace testZeroSize {
|
|
void f() {
|
|
int buf[3]; // expected-note {{'buf' initialized here}}
|
|
long *lp = ::new (buf + 3) long; // expected-warning{{Storage provided to placement new is only 0 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
|
|
(void)lp;
|
|
}
|
|
} // namespace testZeroSize
|
|
|
|
namespace testNegativeSize {
|
|
void f() {
|
|
int buf[3]; // expected-note {{'buf' initialized here}}
|
|
long *lp = ::new (buf + 4) long; // expected-warning{{Storage provided to placement new is only -4 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
|
|
(void)lp;
|
|
}
|
|
} // namespace testNegativeSize
|
|
|
|
namespace testHeapAllocatedBuffer {
|
|
void g2() {
|
|
char *buf = new char[2]; // expected-note {{'buf' initialized here}}
|
|
// FIXME: The message is misleading -- we should
|
|
// state that a pointer to an uninitialized value
|
|
// is stored.
|
|
// expected-note@-4{{Storing uninitialized value}}
|
|
long *lp = ::new (buf) long; // expected-warning{{Storage provided to placement new is only 2 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
|
|
(void)lp;
|
|
}
|
|
} // namespace testHeapAllocatedBuffer
|
|
|
|
namespace testMultiDimensionalArray {
|
|
void f() {
|
|
char buf[2][3]; // expected-note {{'buf' initialized here}}
|
|
long *lp = ::new (buf) long; // expected-warning{{Storage provided to placement new is only 6 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
|
|
(void)lp;
|
|
}
|
|
} // namespace testMultiDimensionalArray
|
|
|
|
namespace testMultiDimensionalArray2 {
|
|
void f() {
|
|
char buf[2][3]; // expected-note {{'buf' initialized here}}
|
|
long *lp = ::new (buf + 1) long; // expected-warning{{Storage provided to placement new is only 3 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
|
|
(void)lp;
|
|
}
|
|
} // namespace testMultiDimensionalArray2
|
|
|
|
namespace testMultiDimensionalArray3 {
|
|
void f() {
|
|
char buf[2][3]; // expected-note {{'buf' initialized here}}
|
|
long *lp = ::new (&buf[1][1]) long; // expected-warning{{Storage provided to placement new is only 2 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
|
|
(void)lp;
|
|
}
|
|
} // namespace testMultiDimensionalArray3
|
|
|
|
namespace testHierarchy {
|
|
struct Base {
|
|
char a[2];
|
|
};
|
|
struct Derived : Base {
|
|
char x[2];
|
|
int y;
|
|
};
|
|
void f() {
|
|
Base b; // expected-note {{'b' initialized here}}
|
|
Derived *dp = ::new (&b) Derived; // expected-warning{{Storage provided to placement new is only 2 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
|
|
(void)dp;
|
|
}
|
|
} // namespace testHierarchy
|
|
|
|
namespace testArrayTypesAllocation {
|
|
void f1() {
|
|
struct S {
|
|
short a;
|
|
};
|
|
|
|
// bad (not enough space).
|
|
const unsigned N = 32;
|
|
alignas(S) unsigned char buffer1[sizeof(S) * N]; // expected-note {{'buffer1' initialized here}}
|
|
::new (buffer1) S[N]; // expected-warning{{Storage provided to placement new is only 64 bytes, whereas the allocated array type requires more space for internal needs}} expected-note 1 {{}}
|
|
}
|
|
|
|
void f2() {
|
|
struct S {
|
|
short a;
|
|
};
|
|
|
|
// maybe ok but we need to warn.
|
|
const unsigned N = 32;
|
|
alignas(S) unsigned char buffer2[sizeof(S) * N + sizeof(int)]; // expected-note {{'buffer2' initialized here}}
|
|
::new (buffer2) S[N]; // expected-warning{{68 bytes is possibly not enough for array allocation which requires 64 bytes. Current overhead requires the size of 4 bytes}} expected-note 1 {{}}
|
|
}
|
|
} // namespace testArrayTypesAllocation
|
|
|
|
namespace testStructAlign {
|
|
void f1() {
|
|
struct X {
|
|
char a[9];
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// bad (struct X is aligned to char).
|
|
::new (&Xi.a) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
|
|
}
|
|
|
|
void f2() {
|
|
struct X {
|
|
char a;
|
|
char b;
|
|
long c;
|
|
} Xi;
|
|
|
|
// ok (struct X is aligned to long).
|
|
::new (&Xi.a) long;
|
|
}
|
|
|
|
void f3() {
|
|
struct X {
|
|
char a;
|
|
char b;
|
|
long c;
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// bad (struct X is aligned to long but field 'b' is aligned to 1 because of its offset)
|
|
::new (&Xi.b) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
|
|
}
|
|
|
|
void f4() {
|
|
struct X {
|
|
char a;
|
|
struct alignas(alignof(short)) Y {
|
|
char b;
|
|
char c;
|
|
} y;
|
|
long d;
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// bad. 'b' is aligned to short
|
|
::new (&Xi.y.b) long; // expected-warning{{Storage type is aligned to 2 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
|
|
}
|
|
|
|
void f5() {
|
|
short b[10]; // expected-note {{'b' initialized here}}
|
|
|
|
::new (&b) long; // expected-warning{{Storage type is aligned to 2 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
|
|
}
|
|
|
|
void f6() {
|
|
short b[10]; // expected-note {{'b' initialized here}}
|
|
|
|
// bad (same as previous but checks ElementRegion case)
|
|
::new (&b[0]) long; // expected-warning{{Storage type is aligned to 2 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
|
|
}
|
|
|
|
void f7() {
|
|
alignas(alignof(long)) short b[10];
|
|
|
|
// ok. aligned to long(ok). offset 4*2(ok)
|
|
::new (&b[4]) long;
|
|
}
|
|
|
|
void f8() {
|
|
alignas(alignof(long)) short b[10]; // expected-note {{'b' initialized here}}
|
|
|
|
// ok. aligned to long(ok). offset 3*2(ok)
|
|
::new (&b[3]) long; // expected-warning{{Storage type is aligned to 6 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
|
|
}
|
|
|
|
void f9() {
|
|
struct X {
|
|
char a;
|
|
alignas(alignof(long)) char b[20];
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// ok. aligned to long(ok). offset 8*1(ok)
|
|
::new (&Xi.b[8]) long;
|
|
|
|
// bad. aligned to long(ok). offset 1*1(ok)
|
|
::new (&Xi.b[1]) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
|
|
}
|
|
|
|
void f10() {
|
|
struct X {
|
|
char a[8];
|
|
alignas(2) char b;
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// bad (struct X is aligned to 2).
|
|
::new (&Xi.a) long; // expected-warning{{Storage type is aligned to 2 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
|
|
}
|
|
|
|
void f11() {
|
|
struct X {
|
|
char a;
|
|
char b;
|
|
struct Y {
|
|
long c;
|
|
} d;
|
|
} Xi;
|
|
|
|
// ok (struct X is aligned to long).
|
|
::new (&Xi.a) long;
|
|
}
|
|
|
|
void f12() {
|
|
struct alignas(alignof(long)) X {
|
|
char a;
|
|
char b;
|
|
} Xi;
|
|
|
|
// ok (struct X is aligned to long).
|
|
::new (&Xi.a) long;
|
|
}
|
|
|
|
void test13() {
|
|
struct Y {
|
|
char a[10];
|
|
};
|
|
|
|
struct X {
|
|
Y b[10];
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// bad. X,A are aligned to 'char'
|
|
::new (&Xi.b[0].a) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
|
|
}
|
|
|
|
void test14() {
|
|
struct Y {
|
|
char a[10];
|
|
};
|
|
|
|
struct alignas(alignof(long)) X {
|
|
Y b[10];
|
|
} Xi;
|
|
|
|
// ok. X is aligned to 'long' and field 'a' goes with zero offset
|
|
::new (&Xi.b[0].a) long;
|
|
}
|
|
|
|
void test15() {
|
|
struct alignas(alignof(long)) Y {
|
|
char a[10];
|
|
};
|
|
|
|
struct X {
|
|
Y b[10];
|
|
} Xi;
|
|
|
|
// ok. X is aligned to 'long' because it contains struct 'Y' which is aligned to 'long'
|
|
::new (&Xi.b[0].a) long;
|
|
}
|
|
|
|
void test16() {
|
|
struct alignas(alignof(long)) Y {
|
|
char p;
|
|
char a[10];
|
|
};
|
|
|
|
struct X {
|
|
Y b[10];
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// bad. aligned to long(ok). offset 1(bad)
|
|
::new (&Xi.b[0].a) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
|
|
}
|
|
|
|
void test17() {
|
|
struct alignas(alignof(long)) Y {
|
|
char p;
|
|
char a[10];
|
|
};
|
|
|
|
struct X {
|
|
Y b[10];
|
|
} Xi;
|
|
|
|
// ok. aligned to long(ok). offset 1+7*1(ok)
|
|
::new (&Xi.b[0].a[7]) long;
|
|
}
|
|
|
|
void test18() {
|
|
struct Y {
|
|
char p;
|
|
alignas(alignof(long)) char a[10];
|
|
};
|
|
|
|
struct X {
|
|
Y b[10];
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// ok. aligned to long(ok). offset 8*1(ok)
|
|
::new (&Xi.b[0].a[8]) long;
|
|
|
|
// bad. aligned to long(ok). offset 1(bad)
|
|
::new (&Xi.b[0].a[1]) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
|
|
}
|
|
|
|
void test19() {
|
|
struct Z {
|
|
char p;
|
|
char c[10];
|
|
};
|
|
|
|
struct Y {
|
|
char p;
|
|
Z b[10];
|
|
};
|
|
|
|
struct X {
|
|
Y a[10];
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// bad. all structures X,Y,Z are aligned to char
|
|
::new (&Xi.a[1].b[1].c) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
|
|
}
|
|
|
|
void test20() {
|
|
struct Z {
|
|
char p;
|
|
alignas(alignof(long)) char c[10];
|
|
};
|
|
|
|
struct Y {
|
|
char p;
|
|
Z b[10];
|
|
};
|
|
|
|
struct X {
|
|
Y a[10];
|
|
} Xi;
|
|
|
|
// ok. field 'c' is aligned to 'long'
|
|
::new (&Xi.a[1].b[1].c) long;
|
|
}
|
|
|
|
void test21() {
|
|
struct Z {
|
|
char p;
|
|
char c[10];
|
|
};
|
|
|
|
struct Y {
|
|
char p;
|
|
Z b[10];
|
|
};
|
|
|
|
struct alignas(alignof(long)) X {
|
|
Y a[10];
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// ok. aligned to long(ok). offset 1+7*1(ok)
|
|
::new (&Xi.a[0].b[0].c[7]) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
|
|
}
|
|
|
|
void test22() {
|
|
struct alignas(alignof(long)) Y {
|
|
char p;
|
|
char a[10][10];
|
|
};
|
|
|
|
struct X {
|
|
Y b[10];
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// ok. aligned to long(ok). offset ok. 1(field 'a' offset) + 0*10(index '0' * first dimension size '10') + 7*1(index '7')
|
|
::new (&Xi.b[0].a[0][7]) long;
|
|
|
|
// ok. aligned to long(ok). offset ok. 1(field 'a' offset) + 1*10(index '1' * first dimension size '10') + 5*1(index '5')
|
|
::new (&Xi.b[0].a[1][5]) long;
|
|
|
|
// bad. aligned to long(ok). offset ok. 1(field 'a' offset) + 1*10(index '1' * first dimension size '10') + 6*1(index '5')
|
|
::new (&Xi.b[0].a[1][6]) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
|
|
}
|
|
|
|
} // namespace testStructAlign
|