From 91c0535cd7c0f8e515fcd8479bcc58fdce7acdeb Mon Sep 17 00:00:00 2001 From: boykopovar Date: Wed, 21 Oct 2026 10:17:39 +0300 Subject: [PATCH] fix(systemgesture): validate native pad report input --- core/libs/prx/libSceSystemGesture/Export.cpp | 12 ++++++------ core/libs/tests/GuestSystemGesture.cpp | 13 ++++++++----- docs/dev/debt/libSceSystemGesture.md | 2 +- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/core/libs/prx/libSceSystemGesture/Export.cpp b/core/libs/prx/libSceSystemGesture/Export.cpp index 346cd57893..5e1fb249e6 100644 --- a/core/libs/prx/libSceSystemGesture/Export.cpp +++ b/core/libs/prx/libSceSystemGesture/Export.cpp @@ -331,14 +331,14 @@ int APS5_VABI sceSystemGestureUpdateAllTouchRecognizer(int32_t gestureHandle) { return 0; } -int APS5_VABI sceSystemGestureUpdatePrimitiveTouchRecognizer(int32_t gestureHandle, const void* param) { +int APS5_VABI sceSystemGestureUpdatePrimitiveTouchRecognizer(int32_t gestureHandle, const SystemGestureTouchPadData* input) { std::lock_guard lock(primitiveTouchMutex); if (!gestureInitialized) return static_cast(0x80890003); - if (!findGestureContext(gestureHandle)) return SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE; - if (!param) return 0; - const auto* input = static_cast(param); - if (!input->pad_data_buffer || input->report_number <= 0) return 0; - for (std::int32_t i = 0; i < input->report_number; ++i) sampleReport(findGestureContext(gestureHandle)->touches, input->pad_data_buffer[i]); + if (!input || !input->pad_data_buffer) return SCE_SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT; + auto* context = findGestureContext(gestureHandle); + if (!context) return SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE; + if (input->report_number < 0 || input->report_number > 1) return SCE_SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT; + if (input->report_number == 1) sampleReport(context->touches, *input->pad_data_buffer); return 0; } diff --git a/core/libs/tests/GuestSystemGesture.cpp b/core/libs/tests/GuestSystemGesture.cpp index db06160408..656f943aca 100644 --- a/core/libs/tests/GuestSystemGesture.cpp +++ b/core/libs/tests/GuestSystemGesture.cpp @@ -27,7 +27,7 @@ int APS5_VABI sceSystemGestureUpdateTouchRecognizer(std::int32_t, void*); int APS5_VABI sceSystemGestureUpdateTouchRecognizerRectangle(std::int32_t, void*, const void*); int APS5_VABI sceSystemGestureResetPrimitiveTouchRecognizer(std::int32_t); int APS5_VABI sceSystemGestureUpdateAllTouchRecognizer(std::int32_t); -int APS5_VABI sceSystemGestureUpdatePrimitiveTouchRecognizer(std::int32_t, const void*); +int APS5_VABI sceSystemGestureUpdatePrimitiveTouchRecognizer(std::int32_t, const SystemGestureTouchPadData*); int APS5_VABI sceSystemGestureInitializePrimitiveTouchRecognizer(); int APS5_VABI sceSystemGestureFinalizePrimitiveTouchRecognizer(void); int APS5_VABI sceSystemGestureGetPrimitiveTouchEventByPrimitiveID(std::int32_t, std::uint16_t, void*); @@ -191,11 +191,14 @@ static void TestPrimitiveTouchEvents(std::int32_t handle, int invalidArgument, i Require(sceSystemGestureGetPrimitiveTouchEventByIndex(handle, 2, &event) == indexOutOfArray); Require(UpdateWithReports(handle + 1, &pair, 1) == invalidHandle); - Require(sceSystemGestureUpdatePrimitiveTouchRecognizer(handle, nullptr) == 0); + Require(sceSystemGestureUpdatePrimitiveTouchRecognizer(handle, nullptr) == invalidArgument); Require(sceSystemGestureGetPrimitiveTouchEventsCount(handle) == 2); const std::array sequence{TouchReport(7000, {{3, 110, 200}}), TouchReport(8000, {{3, 130, 210}})}; - Require(UpdateWithReports(handle, sequence.data(), 2) == 0); + Require(UpdateWithReports(handle, sequence.data(), 2) == invalidArgument); + Require(UpdateWithReports(handle, sequence.data(), -1) == invalidArgument); + Require(UpdateWithReports(handle, sequence.data(), 1) == 0); + Require(UpdateWithReports(handle, sequence.data() + 1, 1) == 0); Require(sceSystemGestureGetPrimitiveTouchEventsCount(handle) == 1); event = SingleEvent(handle); Require(event.primitive_id == 3); @@ -261,7 +264,7 @@ int main() { Require(sceSystemGestureUpdateTouchRecognizerRectangle(handle, &recognizer, &rectangle) == 0); Require(sceSystemGestureResetPrimitiveTouchRecognizer(handle) == 0); Require(sceSystemGestureUpdateAllTouchRecognizer(handle) == 0); - Require(sceSystemGestureUpdatePrimitiveTouchRecognizer(handle, nullptr) == 0); + Require(sceSystemGestureUpdatePrimitiveTouchRecognizer(handle, nullptr) == invalidArgument); Require(sceSystemGestureAppendTouchRecognizer(handle, nullptr) == invalidArgument); Require(sceSystemGestureUpdateTouchRecognizerRectangle(handle, &recognizer, nullptr) == invalidArgument); Require(sceSystemGestureAppendTouchRecognizer(handle + 1, &recognizer) == invalidHandle); @@ -275,7 +278,7 @@ int main() { Require(sceSystemGestureUpdateTouchRecognizerRectangle(handle + 1, &recognizer, &rectangle) == invalidHandle); Require(sceSystemGestureResetPrimitiveTouchRecognizer(handle + 1) == invalidHandle); Require(sceSystemGestureUpdateAllTouchRecognizer(handle + 1) == invalidHandle); - Require(sceSystemGestureUpdatePrimitiveTouchRecognizer(handle + 1, nullptr) == invalidHandle); + Require(sceSystemGestureUpdatePrimitiveTouchRecognizer(handle + 1, nullptr) == invalidArgument); TestTouchRecognizerInformation(handle, invalidArgument, invalidHandle); TestPrimitiveTouchEvents(handle, invalidArgument, invalidHandle, indexOutOfArray); diff --git a/docs/dev/debt/libSceSystemGesture.md b/docs/dev/debt/libSceSystemGesture.md index eff9ccbe7c..5d9acec690 100644 --- a/docs/dev/debt/libSceSystemGesture.md +++ b/docs/dev/debt/libSceSystemGesture.md @@ -6,5 +6,5 @@ ### Unknown function info -- [Primitive touch events](../../../core/libs/prx/libSceSystemGesture/Export.cpp) (libSceSystemGesture) - `sceSystemGestureUpdatePrimitiveTouchRecognizer` reads the pad reports the title passes in, `{int32 padHandle, int32 reportNumber, const ScePadData* padDataBuffer, 8 reserved bytes}`, as [fpPS4](https://github.com/red-prig/fpPS4/blob/585d06fa7c04698c41272b95a696a14c4180e13e/src/ps4_libscesystemgesture.pas) records `SceSystemGestureTouchPadData`; `padHandle` is not checked and a report of a pad other than the one the title opened is not told apart. The touch states 0 inactive, 1 begin, 2 active and 3 end are the Vita ones in [RPCS3](https://github.com/RPCS3/rpcs3/blob/38c444cfa1dbe152daa63b1703c12172078cd056/rpcs3/Emu/PSP2/Modules/sceSystemGesture.h), whose recognizer, rectangle and primitive event layouts are the ones main already uses, and no public source states the PS5 values. A primitive keeps the touch id the pad reports, its positions are the pad's touchpad coordinates unscaled, `delta_time` and `elapsed_time` come from the reports' own `timestamp`, and `is_updated` is 1 for a primitive whose state or position changed in the update; the console's units, scaling and `is_updated` rule are unverified. An ended touch stays readable as one `end` event until the next report sampled drops it. A null `pInputData`, a null `padDataBuffer` or a `reportNumber` of 0 or less leaves the events unchanged and returns success, an event buffer shorter than the event count reports as many events as it holds, while native update null-pointer and report-count checks are not yet matched +- [Primitive touch events](../../../core/libs/prx/libSceSystemGesture/Export.cpp): pad handles are not validated against native controller information. Begin, active and end states are confirmed, but cancellation state 4, motion thresholds and SDK-dependent duplicate-report handling remain unimplemented. Timing, coordinate conversion and update flags still use the host approximation. Recognizer allocation and native descriptor layouts remain incomplete. - [sceSystemGestureDebugGetVersion](../../../core/libs/prx/libSceSystemGesture/Export.cpp) (libSceSystemGesture) - its name and NID are in the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceSystemGesture.c), but no credible prototype was found. It is declared without parameters solely to resolve known imports; this is not an ABI claim