Two defects on the same write path, both reachable today from Download
database and from a local patch import.
1. The file was opened with fs::rewrite (write + create + trunc), streamed
into, and the write result discarded -- save_patches returned true
unconditionally. A write that fails part way (out of space, process
killed) therefore leaves a truncated patch.yml behind, and load() rejects
the whole file on a parse error, so the failure costs the user every patch
they had. There is no way to rebuild it from inside the app either:
import_patches refuses to write when load() fails, so both import paths
return -1 from then on.
save_config, 70 lines up in the same file, already writes through
fs::pending_file and checks the result. save_patches now does the same.
2. The address element was always emitted as fmt::format("0x%.8x", offset).
For move_file and hide_file that element is a VFS path, not a number:
load() keeps the text in original_offset and skips the u32 validation for
those two types. So a round trip turned a path into 0x00000000, and the
loader accepted it back -- the patch still lists and still toggles, it just
silently stops matching anything. Re-downloading does not repair it,
because append_patches discards an incoming patch whose Patch Version is
not strictly greater than the stored one.
The emit is now gated on patch_type_uses_hex_offset, the predicate that
already existed for this and was used only on the load side.
The numeric branch deliberately keeps using offset rather than
original_offset: an address modifier is folded into offset at load time,
and the flat form emitted here has nowhere to put it.
Both predate the Android patch work and apply to upstream RPCS3 unchanged;
they are in this branch because the bundled-patch import adds another caller
of save_patches.
Verified on device (arm64, Android 15). A patch.yml seeded with move_file and
hide_file entries was put through an import that merges a new patch, which is
what forces the rewrite. After it:
- [move_file, /dev_bdvd/PS3_GAME/USRDIR/probe.bik, /dev_bdvd/PS3_GAME/USRDIR/probe.bik.bak]
- [hide_file, /dev_bdvd/PS3_GAME/USRDIR/hidden.bik, ""]
Both paths survived; before this change they would read 0x00000000. All three
top-level hashes in the file (the two seeded, plus the merged one) were still
present and parseable afterwards.
Not verified: the failure path in (1). Forcing a short write mid-rewrite
(ENOSPC or a kill inside save_patches) was not exercised, so the atomicity is
argued from fs::pending_file's contract and from parity with save_config, not
from a reproduced failure.
sceNpTrophy fixes
- sceNpTrophyGetTrophyUnlockState: signed 1 was potentially shifted by 31(UB)
- sceNpTrophyUnlockTrophy: used a reader_lock and was missing check for read only context
cellGame fixes
- cellHddGameCheck: missing log parameters
- cellGameDataCheckCreate2: missing log parameter
- cellGameThemeInstall: condition inverted checking for extension + added tolower just in case
- cellGameThemeInstallFromBuffer: OOB access, buf is always filled from the start and then used as a parameter to the CB
sceNp fixes
- sceNpManagerGetTicket: Made accurate from RE
- sceNpDrmGetTimelimit: Fix msec calculation
sceNp2 fixes
-sceNpMatching2ContextStartAsync: avoid capturing ctx
-sceNpMatching2ContextStop: Minor error value swap
rpcn_client fixes
-add_friend: missing log parameter
-handle_friend_notification: misc validation issue
np_handler fixes
-ticket: Missing move in move constructor
-ticket::parse: Misc validation fix
-get_player_history_entry: potential UB fix
np_requests fixes
-Wrong CB event_type set for get_room_member_data_external_list!
-reply_tus_get_data was not copying status data!
-Order of error check in reply_get_room_member_data_external_list was wrong
-Improved logging
np_requests_gui:
-Added missing guards for gui_notifications
upnp_handler fixes
-Highest density of bugs per line of code in the west, let's pretend I never wrote this
signaling_handler fixes
-Swapped to multimap to avoid collisions on timestamps
Misc fixes