Description
After #69498 I started to get the following asserts in the protobuf compiler protoc
linked with libc++ built with -fno-exceptions and -fsanitize=cfi-icall:
../../third_party/libc++/src/src/new.cpp:62: assertion !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new)) failed: libc++ was configured with exceptions disabled and operator new(size_t) has been overridden, but operator new(size_t, nothrow_t) has not been overridden. This is problematic because operator new(size_t, nothrow_t) must call operator new(size_t), which will terminate in case it fails to allocate, making it impossible for operator new(size_t, nothrow_t) to fulfill its contract (since it should return nullptr upon failure). Please make sure you override operator new(size_t, nothrow_t) as well.
There are no explicit overrides of operator new(unsigned long)
or operator new(unsigned long, std::nothrow_t const&)
in the code. So this case should not be among the impacted use cases described in #69498.
It appears -fsanitize=cfi-icall would redirect operator new(unsigned long)
but not operator new(unsigned long, std::nothrow_t const&)
, which is considered by libc++ as a form of incorrect override?
There doesn't seem to be any control of -fsanitize=cfi-icall to explicitly generate the override for operator new(unsigned long, std::nothrow_t const&)
to make libc++ happy. Is it possible or how to use -fsanitize=cfi-icall together with -fno-exceptions?
Without -fsanitize=cfi-icall:
00000000000b0110 w F .text 000000000000003f operator new(unsigned long, std::nothrow_t const&)
00000000000b0150 w F .text 000000000000003f operator new[](unsigned long, std::nothrow_t const&)
00000000000b01a0 w F .text 0000000000000066 operator new(unsigned long, std::align_val_t, std::nothrow_t const&)
00000000000b0210 w F .text 0000000000000066 operator new[](unsigned long, std::align_val_t, std::nothrow_t const&)
00000000002d4cf0 w F __lcxx_override 000000000000001d operator new(unsigned long)
00000000002d4d10 w F __lcxx_override 000000000000000a operator new[](unsigned long)
00000000002d4d20 w F __lcxx_override 0000000000000044 operator new(unsigned long, std::align_val_t)
00000000002d4d70 w F __lcxx_override 000000000000000a operator new[](unsigned long, std::align_val_t)
With -fsanitize=cfi-icall:
000000000007a9c0 w F .text 0000000000000010 operator new(unsigned long)
000000000007a9c8 w F .text 0000000000000010 operator new[](unsigned long)
0000000000093730 w F .text 0000000000000073 operator new(unsigned long, std::nothrow_t const&)
00000000000937b0 w F .text 0000000000000073 operator new[](unsigned long, std::nothrow_t const&)
0000000000093840 w F .text 00000000000000a0 operator new(unsigned long, std::align_val_t, std::nothrow_t const&)
00000000000938e0 w F .text 00000000000000a0 operator new[](unsigned long, std::align_val_t, std::nothrow_t const&)
00000000002e0190 l F __lcxx_override 0000000000000048 .hidden operator new(unsigned long) [clone .cfi]
00000000002e01e0 l F __lcxx_override 000000000000000a .hidden operator new[](unsigned long) [clone .cfi]
00000000002e01f0 w F __lcxx_override 0000000000000075 operator new(unsigned long, std::align_val_t)
00000000002e0270 w F __lcxx_override 000000000000000a operator new[](unsigned long, std::align_val_t)