From db49ba97b539046f30b855257be0e2f246d4b33c Mon Sep 17 00:00:00 2001 From: Ethan Barr Date: Tue, 6 Oct 2026 13:50:39 -0700 Subject: [PATCH 1/2] fix(libc): return posix_memalign allocation errors --- core/libs/prx/libc/src/ApplicationHeap.cpp | 3 ++- core/libs/prx/libc/src/FileAndHeap.cpp | 11 +++++++++- core/libs/tests/ApplicationHeap.cpp | 24 ++++++++++++++++++++-- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/core/libs/prx/libc/src/ApplicationHeap.cpp b/core/libs/prx/libc/src/ApplicationHeap.cpp index 3cd055106..6c7d93c92 100644 --- a/core/libs/prx/libc/src/ApplicationHeap.cpp +++ b/core/libs/prx/libc/src/ApplicationHeap.cpp @@ -221,7 +221,8 @@ int ApplicationHeapPosixAlign_nid_no_patch(void** pointer, std::size_t alignment const auto align = callback(6); CallbackScope scope; void* result = nullptr; - if (align(&result, alignment, bytes) != 0) throw std::runtime_error("application heap: posix_memalign failed"); + const int error = align(&result, alignment, bytes); + if (error != 0) return error; requireAllocation(result); if (reinterpret_cast(result) % alignment != 0) throw std::runtime_error("application heap: allocator returned a misaligned pointer"); *pointer = result; diff --git a/core/libs/prx/libc/src/FileAndHeap.cpp b/core/libs/prx/libc/src/FileAndHeap.cpp index 80f1716a1..dc3a4208d 100644 --- a/core/libs/prx/libc/src/FileAndHeap.cpp +++ b/core/libs/prx/libc/src/FileAndHeap.cpp @@ -211,7 +211,16 @@ void* APS5_VABI calloc_nid_postfix(size_t count, size_t size) { } int APS5_VABI posix_memalign_nid_postfix(void** pointer, size_t alignment, size_t size) { - return ApplicationHeapPosixAlign_nid_no_patch(pointer, alignment, size); + if (!pointer || alignment < sizeof(void*) || (alignment & (alignment - 1)) != 0) return 22; + const int savedError = errno; + try { + const int result = ApplicationHeapPosixAlign_nid_no_patch(pointer, alignment, size); + errno = savedError; + return result; + } catch (const std::bad_alloc&) { + errno = savedError; + return 12; + } } void* APS5_VABI bsearch_nid_postfix(const void* key, const void* base, size_t count, diff --git a/core/libs/tests/ApplicationHeap.cpp b/core/libs/tests/ApplicationHeap.cpp index 0f08924bb..da9f30958 100644 --- a/core/libs/tests/ApplicationHeap.cpp +++ b/core/libs/tests/ApplicationHeap.cpp @@ -4,10 +4,12 @@ #include #include #include +#include #include #include extern "C" { +int APS5_VABI posix_memalign_nid_postfix(void**, std::size_t, std::size_t); void* APS5_VABI _Znwm_nid_postfix(std::size_t); void* APS5_VABI _ZnamRKSt9nothrow_t_nid_postfix(std::size_t, const void*); void APS5_VABI _ZdlPv_nid_postfix(void*); @@ -24,6 +26,7 @@ namespace { alignas(64) std::array storage{}; std::size_t lastSize = 0; std::size_t lastAlignment = 0; +unsigned posixCalls = 0; unsigned initializes = 0; unsigned frees = 0; bool fail = false; @@ -75,7 +78,8 @@ void* APS5_VABI realign(void* pointer, std::size_t bytes, std::size_t alignment) } int APS5_VABI posixAlign(void** pointer, std::size_t alignment, std::size_t bytes) { - if (fail) return 12; + ++posixCalls; + if (fail) { *__error_nid_postfix() = 12; *pointer = nullptr; return 12; } *pointer = align(alignment, bytes); return 0; } @@ -188,9 +192,25 @@ int main(int argc, char** argv) { reject([] { ApplicationHeapAlign_nid_no_patch(4, 64); }); reject([] { ApplicationHeapAllocate_nid_no_patch(64); }); void* unchanged = storage.data(); - reject([&] { ApplicationHeapPosixAlign_nid_no_patch(&unchanged, 64, 64); }); + *__error_nid_postfix() = 77; + try { + const int error = posix_memalign_nid_postfix(&unchanged, 64, 64); + if (error != 12) { std::fprintf(stderr, "posix_memalign callback: expected ENOMEM 12, received %d\n", error); return 1; } + } catch (const std::exception&) { + std::fputs("posix_memalign callback: expected ENOMEM 12, received exception\n", stderr); + return 1; + } + require(*__error_nid_postfix() == 77); require(unchanged == storage.data()); fail = false; + const auto beforeInvalid = posixCalls; + for (const std::size_t alignment : {std::size_t{0}, std::size_t{1}, std::size_t{4}, std::size_t{24}}) { + require(posix_memalign_nid_postfix(&unchanged, alignment, 32) == 22); + require(unchanged == storage.data() && *__error_nid_postfix() == 77); + } + require(posix_memalign_nid_postfix(nullptr, 64, 32) == 22 && posixCalls == beforeInvalid); + require(posix_memalign_nid_postfix(&unchanged, 64, 31) == 0 && unchanged == storage.data()); + require(lastSize == 31 && lastAlignment == 64 && *__error_nid_postfix() == 77); recurse = true; reject([] { ApplicationHeapAllocate_nid_no_patch(64); }); recurse = false; From c6dde16023464136ee84a9a703671bc51e274bf8 Mon Sep 17 00:00:00 2001 From: Ethan Barr Date: Tue, 6 Oct 2026 16:44:58 -0700 Subject: [PATCH 2/2] fix(libc): preserve invalid allocator result diagnostics --- core/libs/prx/libc/src/FileAndHeap.cpp | 11 +++-------- core/libs/tests/ApplicationHeap.cpp | 12 ++++++++++++ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/core/libs/prx/libc/src/FileAndHeap.cpp b/core/libs/prx/libc/src/FileAndHeap.cpp index dc3a4208d..60ed9ef87 100644 --- a/core/libs/prx/libc/src/FileAndHeap.cpp +++ b/core/libs/prx/libc/src/FileAndHeap.cpp @@ -213,14 +213,9 @@ void* APS5_VABI calloc_nid_postfix(size_t count, size_t size) { int APS5_VABI posix_memalign_nid_postfix(void** pointer, size_t alignment, size_t size) { if (!pointer || alignment < sizeof(void*) || (alignment & (alignment - 1)) != 0) return 22; const int savedError = errno; - try { - const int result = ApplicationHeapPosixAlign_nid_no_patch(pointer, alignment, size); - errno = savedError; - return result; - } catch (const std::bad_alloc&) { - errno = savedError; - return 12; - } + const int result = ApplicationHeapPosixAlign_nid_no_patch(pointer, alignment, size); + errno = savedError; + return result; } void* APS5_VABI bsearch_nid_postfix(const void* key, const void* base, size_t count, diff --git a/core/libs/tests/ApplicationHeap.cpp b/core/libs/tests/ApplicationHeap.cpp index da9f30958..664104d4f 100644 --- a/core/libs/tests/ApplicationHeap.cpp +++ b/core/libs/tests/ApplicationHeap.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include extern "C" { @@ -31,6 +32,7 @@ unsigned initializes = 0; unsigned frees = 0; bool fail = false; bool recurse = false; +bool nullPosixResult = false; void require(bool condition) { if (!condition) throw std::runtime_error("application heap test failed"); @@ -80,6 +82,7 @@ void* APS5_VABI realign(void* pointer, std::size_t bytes, std::size_t alignment) int APS5_VABI posixAlign(void** pointer, std::size_t alignment, std::size_t bytes) { ++posixCalls; if (fail) { *__error_nid_postfix() = 12; *pointer = nullptr; return 12; } + if (nullPosixResult) { *pointer = nullptr; return 0; } *pointer = align(alignment, bytes); return 0; } @@ -203,6 +206,15 @@ int main(int argc, char** argv) { require(*__error_nid_postfix() == 77); require(unchanged == storage.data()); fail = false; + nullPosixResult = true; + bool rejectedNull = false; + try { + const int error = posix_memalign_nid_postfix(&unchanged, 64, 64); + std::fprintf(stderr, "posix_memalign callback: success with null pointer must throw, received %d\n", error); + return 1; + } catch (const std::bad_alloc&) { rejectedNull = true; } + require(rejectedNull && unchanged == storage.data()); + nullPosixResult = false; const auto beforeInvalid = posixCalls; for (const std::size_t alignment : {std::size_t{0}, std::size_t{1}, std::size_t{4}, std::size_t{24}}) { require(posix_memalign_nid_postfix(&unchanged, alignment, 32) == 22);