[Bug c++/98798] New: Custom operator new[] and delete[] is buggy for aligned class
marekr22 at wp dot pl
gcc-bugzilla@gcc.gnu.org
Fri Jan 22 16:42:50 GMT 2021
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
More information about the Gcc-bugs
mailing list