https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98798
Bug ID: 98798 Summary: Custom operator new[] and delete[] is buggy for aligned class Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: marekr22 at wp dot pl Target Milestone: --- Basically when class has alignment requirement and custom operators `new[]` and `delete[]` (C++17), then address sanitizer reports buffer overflow: ## MCVE: ```cpp #include <iostream> #include <memory> class EndlineOnDone { std::ostream& out; public: EndlineOnDone(std::ostream& out) : out{out} {} ~EndlineOnDone() { out << std::endl; } std::ostream& stream() { return out; } }; #define VAR(x) " " #x "=[" << x << "]" #define LOG EndlineOnDone(std::cout).stream() << __PRETTY_FUNCTION__ std::ostream& operator<<(std::ostream& out, std::align_val_t a) { return out << static_cast<size_t>(a); } class alignas(32) Foo { public : double x, y, z; void * operator new (size_t s, std::align_val_t a) { auto p = aligned_alloc(static_cast<size_t>(a), s); LOG << VAR(p) << VAR(s) << VAR(a); return p; } void operator delete (void * p, size_t s, std::align_val_t a) { LOG << VAR(p) << VAR(s) << VAR(a); if (p) free(p); } #if 1 void * operator new[ ] (size_t s, std::align_val_t a) { auto p = aligned_alloc(static_cast<size_t>(a), s); LOG << VAR(p) << VAR(s) << VAR(a); return p; } void operator delete[ ] (void *p, size_t s, std::align_val_t a) { LOG << VAR(p) << VAR(s) << VAR(a); if (p) free(p); } #endif }; int main() { { LOG << " std::make_unique<Foo>"; auto p = std::make_unique<Foo>(); } { LOG << " std::make_unique<Foo[]>"; auto p = std::make_unique<Foo[]>(3); } } ``` https://godbolt.org/z/7xd8YM ## gcc logs (no address sanitizer): ```txt int main() std::make_unique<Foo> static void* Foo::operator new(size_t, std::align_val_t) p=[0x21d6ec0] s=[32] a=[32] static void Foo::operator delete(void*, size_t, std::align_val_t) p=[0x21d6ec0] s=[32] a=[32] int main() std::make_unique<Foo[]> static void* Foo::operator new [](size_t, std::align_val_t) p=[0x21d6f40] s=[96] a=[32] static void Foo::operator delete [](void*, size_t, std::align_val_t) p=[0x21d6f40] s=[3616] a=[32] ``` Note that `s` value for `Foo[]` doesn't match for `new[]` and `delete[]` operations. Address sanitizer reports buffer overflow. clang is fine (didn't check msvc). ## Workaround Adding explicit destructor `~Foo() {}` fixes this issue: https://godbolt.org/z/WoM91Y (use of `~Foo() = default;` doesn't fix it). https://stackoverflow.com/q/65826663/1387438