Skip to content

libc++ with -fno-exceptions conflicts with -fsanitize=cfi-icall #86430

Open
@klzgrad

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)

Metadata

Assignees

No one assigned

    Labels

    libc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions