Merge pull request #2324 from AchrafReyani/fix/libc-getcwd-application-heap

fix(libc): allocate getcwd's buffer from the application heap
This commit is contained in:
Dean 2026-10-10 17:46:55 +13:00 committed by GitHub
commit ee364bf05f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 25 additions and 4 deletions

View File

@ -24,7 +24,7 @@
#include <unistd.h>
#endif
#include "prx/libc/include/General.hpp"
#include "prx/libc/include/GuestHeap.hpp"
#include "prx/libc/include/ApplicationHeap.hpp"
namespace {
// Guest prefixes (without leading slashes) mapped to host directories, e.g. save-data mount points:
@ -304,7 +304,8 @@ extern "C" char* APS5_VABI getcwd_nid_postfix(char* buffer, std::size_t size) {
const auto path = relative == "." ? std::string("/") : "/" + relative.generic_string();
const auto required = path.size() + 1;
if ((buffer || size) && size < required) { errno = 34; return nullptr; }
if (!buffer) buffer = static_cast<char*>(GuestHeap::GuestHeapAllocate_nid_postfix(size ? size : required));
if (!buffer) buffer = static_cast<char*>(ApplicationHeapAllocate_nid_no_patch(size ? size : required));
if (!buffer) { errno = 12; return nullptr; }
std::memcpy(buffer, path.c_str(), required);
return buffer;
} catch (const std::bad_alloc&) { errno = 12; return nullptr; }

View File

@ -21,6 +21,7 @@ void APS5_VABI _ZdlPvmSt11align_val_t_nid_postfix(void*, std::size_t, std::size_
void* ApplicationHeapRealign_nid_no_patch(void*, std::size_t, std::size_t);
char* APS5_VABI strdup_nid_postfix(const char*);
char* APS5_VABI strndup_nid_postfix(const char*, std::size_t);
char* APS5_VABI getcwd_nid_postfix(char*, std::size_t);
int* APS5_VABI __error_nid_postfix();
int APS5_VABI atexit_nid_postfix(void (APS5_VABI*)());
}
@ -260,6 +261,12 @@ int main(int argc, char** argv) {
copy = strndup_nid_postfix(text, 5);
require(lastSize == 6 && std::strcmp(copy, "guest") == 0);
ApplicationHeapFree_nid_no_patch(copy);
char* directory = getcwd_nid_postfix(nullptr, 0);
require(directory == reinterpret_cast<char*>(storage.data()) && directory[0] == '/' && lastSize == std::strlen(directory) + 1);
ApplicationHeapFree_nid_no_patch(directory);
directory = getcwd_nid_postfix(nullptr, 200);
require(directory == reinterpret_cast<char*>(storage.data()) && lastSize == 200);
ApplicationHeapFree_nid_no_patch(directory);
fail = true;
*__error_nid_postfix() = 0;
require(strdup_nid_postfix(text) == nullptr && *__error_nid_postfix() == 12);
@ -267,5 +274,7 @@ int main(int argc, char** argv) {
require(strdup_nid_postfix("") == nullptr && *__error_nid_postfix() == 12);
*__error_nid_postfix() = 0;
require(strndup_nid_postfix(text, 5) == nullptr && *__error_nid_postfix() == 12);
*__error_nid_postfix() = 0;
require(getcwd_nid_postfix(nullptr, 0) == nullptr && *__error_nid_postfix() == 12);
fail = false;
}

View File

@ -1,5 +1,7 @@
#include "prx/libc/include/ApplicationHeap.hpp"
#include "prx/libc/include/General.hpp"
#include "prx/libc/include/GuestHeap.hpp"
#include <array>
#include <chrono>
#include <cstdlib>
#include <cstring>
@ -10,7 +12,15 @@ char* APS5_VABI getcwd_nid_postfix(char*, std::size_t);
int* APS5_VABI __error_nid_postfix();
}
static void Require(bool value) { if (!value) std::abort(); }
static int allocations = 0;
static int releases = 0;
static void* APS5_VABI Allocate(std::size_t bytes) { ++allocations; return GuestHeap::GuestHeapAllocate_nid_postfix(bytes); }
static void APS5_VABI Release(void* pointer) { ++releases; GuestHeap::GuestHeapFree_nid_postfix(pointer); }
static void* APS5_VABI Unused() { std::abort(); }
int main() {
const std::array<void*, 10> api{reinterpret_cast<void*>(&Allocate), reinterpret_cast<void*>(&Release), reinterpret_cast<void*>(&Unused),
reinterpret_cast<void*>(&Unused), reinterpret_cast<void*>(&Unused), reinterpret_cast<void*>(&Unused), reinterpret_cast<void*>(&Unused)};
ApplicationHeapRegister_nid_no_patch(api.data());
const auto host = std::filesystem::canonical(std::filesystem::current_path());
char path[1024];
Require(getcwd_nid_postfix(path, sizeof(path)) == path && std::strcmp(path, "/") == 0);
@ -28,8 +38,9 @@ int main() {
Require(std::strcmp(tiny, "xyz") == 0);
Require(getcwd_nid_postfix(path, 0) == nullptr && *__error_nid_postfix() == 22);
char* allocated = getcwd_nid_postfix(nullptr, 0);
Require(allocated && std::strcmp(allocated, path) == 0);
GuestHeap::GuestHeapFree_nid_postfix(allocated);
Require(allocated && std::strcmp(allocated, path) == 0 && allocations == 1);
ApplicationHeapFree_nid_no_patch(allocated);
Require(releases == 1);
Require(chdir_nid_postfix("sample.txt") == -1 && *__error_nid_postfix() == 20);
Require(chdir_nid_postfix("missing") == -1 && *__error_nid_postfix() == 2);
Require(chdir_nid_postfix("..") == 0);