[PATCH] libstdc++: Ensure that aligned new detects size_t overflow (CVE-2026-95619)
Jonathan Wakely
jwakely@redhat.com
Wed Sep 23 08:28:30 GMT 2026
On Wed, 23 Sept 2026 at 00:34, Jonathan Wakely <jwakely@redhat.com> wrote:
>
> Depending on the implementation used for aligned new, we might need to
> round the size argument up to a multiple of the alignment. If either the
> size or the alignment is a huge value then the rounded result could
> wraparound to a small value which would then be successfully allocated
> by the underlying libc allocation function. This means that we return
> a non-null pointer but not of the requested size. Instead we should
> throw std::bad_alloc because the allocation cannot succeed.
>
> This doesn't affect most modern targets because they use the
> posix_memalign implementation, which doesn't do that rounding. The
> affected targets are the ones without posix_memalign (where we round
> before calling C11 aligned_alloc) and without any aligned allocation
> function (where we provide our own __gnu_cxx::aligned_alloc in terms of
> malloc).
>
> libstdc++-v3/ChangeLog:
>
> * libsupc++/new_opa.cc (__gnu_cxx::aligned_alloc): Check for
> size_t overflow.
> (operator new) [_GLIBCXX_HAVE_ALIGNED_ALLOC]: Likewise.
> * testsuite/18_support/new_aligned_wrap.cc: New test.
> ---
>
> Tested x86_64-linux. This should be backported too.
>
> This fixes https://access.redhat.com/security/cve/cve-2026-95619 so
> distros should backport it to any supported releases that are affected.
> The bug was introduced in GCC 7.1 and fixed for most targets in 12.4.0,
> 13.3.0, and 14.1.0 by PR113258. For *-*-mingw* all versions after 7.1.0
> are affected.
After testing on mingw-w64 I've realized that the first hunk here
doesn't fix it for that platform, because we use the Windows
_aligned_malloc function, which appears to overflow internally.
So another fix is needed for mingw*
>
> libstdc++-v3/libsupc++/new_opa.cc | 11 +++++---
> .../testsuite/18_support/new_aligned_wrap.cc | 25 +++++++++++++++++++
> 2 files changed, 33 insertions(+), 3 deletions(-)
> create mode 100644 libstdc++-v3/testsuite/18_support/new_aligned_wrap.cc
>
> diff --git a/libstdc++-v3/libsupc++/new_opa.cc b/libstdc++-v3/libsupc++/new_opa.cc
> index 7bda847a9257..ad9cf21dfcae 100644
> --- a/libstdc++-v3/libsupc++/new_opa.cc
> +++ b/libstdc++-v3/libsupc++/new_opa.cc
> @@ -103,8 +103,10 @@ aligned_alloc (std::size_t al, std::size_t sz)
> // We need extra bytes to store the original value returned by malloc.
> if (al < sizeof(void*))
> al = sizeof(void*);
> - void* const malloc_ptr = malloc(sz + al);
> - if (!malloc_ptr)
> + if (__builtin_add_overflow(sz, al, &sz)) [[unlikely]]
> + return nullptr;
> + void* const malloc_ptr = malloc(sz);
> + if (!malloc_ptr) [[unlikely]]
> return nullptr;
> // Align to the requested value, leaving room for the original malloc value.
> void* const aligned_ptr = (void *) (((uintptr_t) malloc_ptr + al) & -al);
> @@ -141,7 +143,10 @@ operator new (std::size_t sz, std::align_val_t al)
> align = sizeof(void*);
> # endif
> /* C11: the value of size shall be an integral multiple of alignment. */
> - sz = (sz + align - 1) & ~(align - 1);
> + if (!__builtin_add_overflow(sz, align - 1, &sz))
> + sz &= ~(align - 1);
> + else
> + _GLIBCXX_THROW_OR_ABORT(bad_alloc());
> #endif
>
> void *p;
> diff --git a/libstdc++-v3/testsuite/18_support/new_aligned_wrap.cc b/libstdc++-v3/testsuite/18_support/new_aligned_wrap.cc
> new file mode 100644
> index 000000000000..d17a97a5e712
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/18_support/new_aligned_wrap.cc
> @@ -0,0 +1,25 @@
> +// { dg-do run }
> +
> +#include <new>
> +#include <testsuite_hooks.h>
> +
> +#pragma GCC diagnostic ignored "-Walloc-size-larger-than="
> +
> +int main()
> +{
> +#if __cpp_aligned_new
> + std::size_t size = -9;
> + std::align_val_t align = (std::align_val_t)32;
> + try
> + {
> + (void*) ::operator new(size, align);
> + VERIFY(false);
> + }
> + catch (const std::bad_alloc&)
> + {
> + }
> +
> + void* p = ::operator new(size, align, std::nothrow);
> + VERIFY(p == 0);
> +#endif
> +}
> --
> 2.55.0
>
More information about the Libstdc++
mailing list