diff --git a/core/libs/prx/libc/src/ApplicationHeap.cpp b/core/libs/prx/libc/src/ApplicationHeap.cpp index b24c4fe64..cc12f6571 100644 --- a/core/libs/prx/libc/src/ApplicationHeap.cpp +++ b/core/libs/prx/libc/src/ApplicationHeap.cpp @@ -226,7 +226,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 862107572..c6a5de95d 100644 --- a/core/libs/prx/libc/src/FileAndHeap.cpp +++ b/core/libs/prx/libc/src/FileAndHeap.cpp @@ -246,7 +246,11 @@ 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; + 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 088f79122..87d87d5a5 100644 --- a/core/libs/tests/ApplicationHeap.cpp +++ b/core/libs/tests/ApplicationHeap.cpp @@ -4,10 +4,13 @@ #include #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*); @@ -25,10 +28,12 @@ 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; bool recurse = false; +bool nullPosixResult = false; void require(bool condition) { if (!condition) throw std::runtime_error("application heap test failed"); @@ -79,7 +84,9 @@ 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; } + if (nullPosixResult) { *pointer = nullptr; return 0; } *pointer = align(alignment, bytes); return 0; } @@ -198,9 +205,34 @@ 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; + 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); + 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;