Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion core/libs/prx/libc/src/ApplicationHeap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,8 @@ int ApplicationHeapPosixAlign_nid_no_patch(void** pointer, std::size_t alignment
const auto align = callback<PosixAlign>(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<std::uintptr_t>(result) % alignment != 0) throw std::runtime_error("application heap: allocator returned a misaligned pointer");
*pointer = result;
Expand Down
6 changes: 5 additions & 1 deletion core/libs/prx/libc/src/FileAndHeap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,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,
Expand Down
36 changes: 34 additions & 2 deletions core/libs/tests/ApplicationHeap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <cstdio>
#include <limits>
#include <new>
#include <stdexcept>

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*);
Expand All @@ -24,10 +27,12 @@ namespace {
alignas(64) std::array<std::byte, 256> 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");
Expand Down Expand Up @@ -75,7 +80,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;
}
Expand Down Expand Up @@ -188,9 +195,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;
Expand Down
Loading