[Bug 288805] [libcxxrt] __cxa_demangle() implementation does not adhere to Itanium C++ ABI

From: <bugzilla-noreply_at_freebsd.org>
Date: Mon, 11 Aug 2025 20:52:54 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=288805

            Bug ID: 288805
           Summary: [libcxxrt] __cxa_demangle() implementation does not
                    adhere to Itanium C++ ABI
           Product: Base System
           Version: 14.3-RELEASE
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: bin
          Assignee: bugs@FreeBSD.org
          Reporter: freebsd-bugzilla@mhxnet.de

I've previously reported this on Github for lack of a bugzilla account:
https://github.com/libcxxrt/libcxxrt/issues/50

I've noticed this on FreeBSD, but reporting it here as I can't seem to be able
to create a bugzilla account.

The Itanium C++ ABI
[states](https://itanium-cxx-abi.github.io/cxx-abi/abi.html#demangler) that

```
namespace abi {
  extern "C" char* __cxa_demangle (const char* mangled_name,
                                   char* buf,
                                   size_t* n,
                                   int* status);
}
```

- If `buf` is a null pointer, `__cxa_demangle` allocates a new buffer with
`malloc`. It stores the size of the buffer in `*n`, if `n` is not `NULL`.
- If `buf` is not a null pointer, it must have been allocated with `malloc`. If
`buf` is not big enough to store the resulting demangled name, `__cxa_demangle`
must either a) call `free` to deallocate `buf` and then allocate a new buffer
with `malloc`, or b) call `realloc` to increase the size of the buffer. In
either case, the new buffer size will be stored in `*n`.

The [current
implementation](https://github.com/libcxxrt/libcxxrt/blob/a6f71cbc3a1e1b8b9df241e081fa0ffdcde96249/src/typeinfo.cc#L88-L105)
has two issues:

- It stores the *length of the string* in `*n`, not the buffer size as
required.
- It *overwrites* `*n` unconditionally, regardless of whether or not a
re-allocation happened.

Here's [simple test case in compiler
explorer](https://gcc.godbolt.org/z/PE9xzP8br). You can see that using
`libstdc++`, `__cxa_demangle` behaves as expected:

```
buffer contents: int
string length  : 3
buffer size    : 4
buffer contents: int
string length  : 3
buffer size    : 21
```

Building the same code on macOS (using `libc++` instead), the implementation
also suffers from the second issue:

```
buffer contents: int
string length  : 3
buffer size    : 4
buffer contents: int
string length  : 3
buffer size    : 4
```

FreeBSD currently suffers from both issues:

```
buffer contents: int
string length  : 3
buffer size    : 3
buffer contents: int
string length  : 3
buffer size    : 3
```

This bug actually triggers [an
assertion](https://github.com/facebook/folly/blob/main/folly/FBString.h#L310)
when using `folly::demangle`, as it calls an `fbstring` constructor that takes
ownership of the buffer and checks that the buffer size is large enough for the
string to hold a trailing `\0` terminator.

-- 
You are receiving this mail because:
You are the assignee for the bug.