mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-22 16:43:05 -05:00
Guest descriptors are host C runtime descriptors. Closing descriptor 0, 1 or 2 closed the host process's standard stream, and the runtime then gave that number to the next file opened anywhere in the process, including files libkernel opens itself, such as the APR reader's. The title's next close of the same number closed that file mid-read. close and sceKernelClose now fail with EBADF for descriptors 0 to 2 that were open when libkernel loaded, and leave them open. A standard descriptor that was not open at load can still be opened and closed by the guest. PPSA21703 calls sceKernelClose(0) repeatedly while loading asset bundles, which made APR reads return 0 or a part of the requested bytes and raised UCRT invalid parameter reports from close. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
39 lines
1.1 KiB
C++
39 lines
1.1 KiB
C++
#include "prx/libc/include/general/VabiMacros.hpp"
|
|
#include <cstdlib>
|
|
|
|
extern "C" {
|
|
int APS5_VABI dup_nid_postfix(int);
|
|
int APS5_VABI pipe_nid_postfix(int*);
|
|
int APS5_VABI close_nid_postfix(int);
|
|
int APS5_VABI sceKernelClose(int);
|
|
int* APS5_VABI __error_nid_postfix();
|
|
}
|
|
|
|
static void Require(bool value) { if (!value) std::abort(); }
|
|
|
|
constexpr int GuestEbadf = 9;
|
|
constexpr int SceKernelErrorEbadf = static_cast<int>(0x80020009);
|
|
|
|
static bool Open(int fd) {
|
|
const int duplicate = dup_nid_postfix(fd);
|
|
if (duplicate < 0) return false;
|
|
Require(close_nid_postfix(duplicate) == 0);
|
|
return true;
|
|
}
|
|
|
|
int main() {
|
|
bool open[3];
|
|
for (int fd = 0; fd < 3; ++fd) open[fd] = Open(fd);
|
|
for (int fd = 0; fd < 3; ++fd) {
|
|
if (!open[fd]) continue;
|
|
Require(close_nid_postfix(fd) == -1 && *__error_nid_postfix() == GuestEbadf);
|
|
Require(sceKernelClose(fd) == SceKernelErrorEbadf);
|
|
Require(Open(fd));
|
|
}
|
|
int pipe[2];
|
|
Require(pipe_nid_postfix(pipe) == 0);
|
|
for (const int fd : pipe) Require(fd >= 3 || !open[fd]);
|
|
Require(close_nid_postfix(pipe[0]) == 0 && close_nid_postfix(pipe[1]) == 0);
|
|
return 0;
|
|
}
|