mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-07 13:39:55 +00:00
test(libSceVrHand): add page-boundary coverage and qualify partial copyout in debt doc
This commit is contained in:
1 parent
aef43daa60
commit
ebd650ca69
2 files changed
+59
-1
No files matched your search
@@ -3,6 +3,13 @@
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -11,6 +18,39 @@ void Require(bool value) { if (!value) std::abort(); }
|
||||
constexpr int kErrInvalidArg = static_cast<int>(0x8a870006);
|
||||
constexpr std::uint8_t kFill = 0xaa;
|
||||
|
||||
struct GuardedRegion {
|
||||
std::size_t pageSize{0};
|
||||
unsigned char* memory{nullptr};
|
||||
|
||||
GuardedRegion() {
|
||||
#ifdef _WIN32
|
||||
SYSTEM_INFO info{};
|
||||
GetSystemInfo(&info);
|
||||
pageSize = static_cast<std::size_t>(info.dwPageSize);
|
||||
memory = static_cast<unsigned char*>(VirtualAlloc(nullptr, pageSize * 2, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE));
|
||||
Require(memory != nullptr);
|
||||
DWORD previous;
|
||||
Require(VirtualProtect(memory + pageSize, pageSize, PAGE_NOACCESS, &previous) != 0);
|
||||
#else
|
||||
const long nativePageSize = sysconf(_SC_PAGESIZE);
|
||||
Require(nativePageSize > 0);
|
||||
pageSize = static_cast<std::size_t>(nativePageSize);
|
||||
void* allocation = mmap(nullptr, pageSize * 2, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
Require(allocation != MAP_FAILED);
|
||||
memory = static_cast<unsigned char*>(allocation);
|
||||
Require(mprotect(memory + pageSize, pageSize, PROT_NONE) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
~GuardedRegion() {
|
||||
#ifdef _WIN32
|
||||
VirtualFree(memory, 0, MEM_RELEASE);
|
||||
#else
|
||||
munmap(memory, pageSize * 2);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
std::array<std::uint8_t, 0x40> ValidParam() {
|
||||
std::array<std::uint8_t, 0x40> param{};
|
||||
param[0] = 0x20;
|
||||
@@ -40,6 +80,24 @@ int main() {
|
||||
Require(sceVrHandQueryMemory(nullptr, out.data()) == kErrInvalidArg && Untouched(out));
|
||||
Require(sceVrHandQueryMemory(param.data(), nullptr) == kErrInvalidArg);
|
||||
|
||||
GuardedRegion region;
|
||||
auto* const boundaryParam = region.memory + region.pageSize - 0x20;
|
||||
std::memset(boundaryParam, 0, 0x20);
|
||||
boundaryParam[0] = 0x20;
|
||||
out.fill(kFill);
|
||||
Require(sceVrHandQueryMemory(boundaryParam, out.data()) == 0);
|
||||
|
||||
auto* const spanningParam = region.memory + region.pageSize - 0x10;
|
||||
out.fill(kFill);
|
||||
Require(sceVrHandQueryMemory(spanningParam, out.data()) == kErrInvalidArg && Untouched(out));
|
||||
|
||||
auto* const boundaryOut = region.memory + region.pageSize - 28;
|
||||
std::memset(boundaryOut, kFill, 28);
|
||||
Require(sceVrHandQueryMemory(param.data(), boundaryOut) == 0);
|
||||
|
||||
auto* const spanningOut = region.memory + region.pageSize - 8;
|
||||
Require(sceVrHandQueryMemory(param.data(), spanningOut) == kErrInvalidArg);
|
||||
|
||||
for (const std::uint32_t size : {0u, 0x1fu, 0x21u, 0x40u, 0x120u, 0x10020u, 0x1000020u}) {
|
||||
param = ValidParam();
|
||||
std::memcpy(param.data(), &size, sizeof(size));
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
### Unknown function info
|
||||
|
||||
- [sceVrHandFinalize, sceVrHandGetMesh, sceVrHandGetMeshSize, sceVrHandGetResult, sceVrHandInitialize, sceVrHandStart, sceVrHandStop](../../../core/libs/prx/libSceVrHand/Export.cpp) (libSceVrHand) - names and NIDs verified from pinned [ps5rs stubs](https://github.com/claimore22/ps5rs/tree/5f252a658ff470bcb2b6cd15205fd8ca64ae4477/data/stubs/by_library) (`libSceVrHand.txt`), with NID match confirmed via `tools/nid_names.py` `compute_nid`. Signatures, parameter layouts, and runtime behavior remain unverified; all paths throw through `NotImplemented_nid_no_patch`.
|
||||
- [sceVrHandQueryMemory](../../../core/libs/prx/libSceVrHand/Export.cpp) (libSceVrHand) - the meaning of the parameter and output fields is unknown. It follows firmware 13.42's libSceVrHand.sprx, read from its disassembly and run natively on x86-64 (not a console): a null pointer, unreadable or unwritable pointers, a first 32-bit parameter word other than 0x20, or any nonzero parameter byte from offset 4 to 31 returns `0x8a870006` and writes nothing; otherwise it stores the 32-bit values 0x3c00000 and 0x10000 at output offsets 0 and 4, clears output bytes 8 to 27 and returns 0. Returning `0x8a870006` for unwritable or unreadable pointers is a defensive host-protection fallback; console behavior is unmeasured.
|
||||
- [sceVrHandQueryMemory](../../../core/libs/prx/libSceVrHand/Export.cpp) (libSceVrHand) - the meaning of the parameter and output fields is unknown. It follows firmware 13.42's libSceVrHand.sprx, read from its disassembly and run natively on x86-64 (not a console): a null pointer, an unreadable parameter, a first 32-bit parameter word other than 0x20, or any nonzero parameter byte from offset 4 to 31 returns `0x8a870006` and writes nothing; an unwritable result pointer returns `0x8a870006` (with possible partial output on copy-out failure). Otherwise it stores the 32-bit values 0x3c00000 and 0x10000 at output offsets 0 and 4, clears output bytes 8 to 27 and returns 0. Returning `0x8a870006` for unwritable or unreadable pointers is a defensive host-protection fallback; console behavior is unmeasured.
|
||||
Reference in new issue
Block a user