Skip to content

fix(libScePad): check scePadInit and pointers before the handle as a PS5 does - #11558

Closed
hugodearaujo wants to merge 1 commit into
boykopovar:mainfrom
hugodearaujo:fix/pad-init-pointer-order
Closed

hugodearaujo wants to merge 1 commit into
boykopovar:mainfrom
hugodearaujo:fix/pad-init-pointer-order

Conversation

@hugodearaujo

Copy link
Copy Markdown
Contributor

What

On a PS5, these ScePad calls check that scePadInit ran, then their pointer arguments, then the handle. AnyPS5 checked the handle first, had no initialization check in them and wrote nothing on a bad handle. They now follow the measured order:

  • Before scePadInit: NOT_INITIALIZED (0x80920005), even with a null pointer, except scePadReadState(h, NULL), which is INVALID_ARG (0x80920001).
  • After it: a null pointer, and for scePadRead a count outside 1 to 64, is INVALID_ARG before the handle is looked at; a bad handle is then INVALID_HANDLE (0x80920003).
  • Records written on those errors, as measured: scePadReadState writes the 120-byte rest record (buttons 0, sticks 0x80, orientation (0, 0, 0, 1), acceleration (0, 1, 0), everything else zero, padding included) both before scePadInit and on a bad handle. On a bad handle, scePadDeviceClassGetExtendedInformation writes 20 zero bytes and scePadDeviceClassParseData writes 24 bytes, a device class of -1 and zeros. The other calls write nothing.

The calls, with how many of the nine converted titles I have import each: scePadGetControllerInformation (9), scePadSetTriggerEffect (8), scePadReadState, scePadSetLightBar, scePadResetLightBar and scePadSetVibration (6 each), scePadRead (4), scePadResetOrientation (3), scePadSetTiltCorrectionState, scePadSetAngularVelocityDeadbandState and scePadIsRemoteController (2 each), scePadSetMotionSensorState, scePadDeviceClassGetExtendedInformation and scePadDeviceClassParseData (1 each).

scePadOpen, scePadOpenExt, scePadGetHandle, scePadClose, scePadGetTriggerEffectState and scePadGetExtControllerInformation follow the same rule on the console but are left out, because #10935, #5038, #10112 and #11187 change them. With the initialization check in front, scePadRead and scePadReadState no longer reach the "read before initialization" throws in PadState.cpp.

Measured

PS5 on firmware 13.60, from a payload process, calling the exports of libScePad.sprx through dlopen and dlsym. The bad handles 0, 1, -1 and 0x7fffffff gave the same results. Lines from the probe logs (phase, call, handle, result, bytes written, bytes):

R|preinit|readstate|h=1|80920005|touched=120|0000000080808080000000000000000000000000000000000000803f000000000000803f00000000...
R|inv|readstate|h=1|80920003|touched=120|0000000080808080000000000000000000000000000000000000803f000000000000803f00000000...
R|inv|read 64|h=1|80920003|touched=0|
R|inv|read 65|h=1|80920001|touched=0|
R|inv|read 128|h=1|80920001|touched=0|
R|inv|ctrlinfo NULL|h=7fffffff|80920001
R|inv|ctrlinfo buf|h=7fffffff|80920003|touched=0|
R|inv|isremote ptr|h=7fffffff|80920003|b=cc
R|inv|parse data buf|h=7fffffff|80920003|touched=24|ffffffff000000000000000000000000

Before scePadInit, each of the fourteen calls returned 0x80920005, also with null pointers and with counts of 0, -1 and 65, and none of them wrote anything except scePadReadState. scePadReadState(h, NULL) returned 0x80920001, and scePadInit twice returned 0 both times.

Tested

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

@github-actions

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 6337 core/libs/tests/GuestPad.cpp L674
PR 10880 core/libs/tests/GuestPad.cpp L590

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 5038 core/libs/prx/libScePad/Export.cpp
PR 8260 core/libs/prx/libScePad/Export.cpp
core/libs/tests/GuestPad.cpp
PR 11207 core/libs/tests/GuestPad.cpp

@oneandonlydean oneandonlydean self-assigned this Oct 26, 2026
@hugodearaujo

Copy link
Copy Markdown
Contributor Author

Closing this: I noticed the evidence for it is weak. The measurements are right, but none of the titles I have reaches the error paths it changes (they all call scePadInit first and check the results). If anyone finds a title that depends on this order, please say so here and I'll reopen it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants