Repository navigation
fix(libSceNpCommon): keep the JSON text helpers inside their buffers and surrogate pairs - #12265
Conversation
…lJsonEscape sceNpUtilJsonEscape appends to the destination with strcat, but the room check started its running length at 0 and ignored the text the buffer already held, so escaping into a partly filled buffer wrote past its end: sceNpUtilJsonEscape(buf, 16, "\n\n\n", 3) on a buffer holding ten characters placed 16 characters and the terminator in 16 bytes. The running length now starts at the length of the existing text, and a destination that is already full returns NP_UTIL_ERROR_BUFFER_TOO_SMALL.
…NpUtilJsonGetOneChar After a high surrogate, sceNpUtilJsonGetOneChar parsed four hex digits at offset 8 without checking that offsets 6 and 7 hold a backslash and a 'u'. The string "\ud83dXXde00" decoded to U+1F600 and consumed 12 bytes, swallowing the two unrelated characters. sceNpUtilJsonUnescape already makes that check. A high surrogate not followed by \u now takes the same failure path as an invalid low surrogate.
…ll destination The final room check ran even when dst was null, so a size query such as (nullptr, 0, src, n, &length) returned NP_UTIL_ERROR_BUFFER_TOO_SMALL and never wrote the required length, although the per-character checks in the same function already skip the comparison for a null destination. The check now applies only when there is a destination.
…ation query, split a surrogate pair sceNpUtilJsonEscape has to stay inside a partly filled 16 byte buffer and refuse one without a terminator, sceNpUtilJsonUnescape has to report the length of a query with a null destination and size 0, and sceNpUtilJsonGetOneChar has to reject a high surrogate that is not followed by a second unicode escape.
|
A Windows run, since the description lists none. Head
AI-assisted: yes (Claude Code). |
|
Windows result in the project's real build, with the control the description lists as not run ("I did not run the new assertions against the unfixed code"). Setup: Windows 11 Pro 26300, AMD Ryzen 7 7800X3D, WinLibs GCC 15.2.0 r7, Ninja Release, Test:
Not tested: Linux in a real build. My WSL tree (GCC 11.4) stops on an unrelated main issue in that target's dependencies: AI-assisted (Claude Code). |
|
Windows result for head Host: Windows 11 26300, Intel i7-12700K, WinLibs GCC 15.2.0 (x86_64-ucrt-posix-seh, r6), Release, The tree also carried the open PRs #12290, #12288, #12285, #12269, #12232, #12206, #12201, #12199, #12197, #12165, #12146, all merged cleanly, so the run is a joint one; the tests of this PR are AI-assisted: yes (Claude Code), the runs and the numbers above are from this machine. |
What
Three defects in the JSON text helpers of
libSceNpCommon/Strings.cpp. One commit each, then one test commit:sceNpUtilJsonEscapeappends withstrcat, but its room check started the running length at 0 and ignored the text the buffer already holds, so escaping into a partly filled buffer wrote past its end:sceNpUtilJsonEscape(buf, 16, "\n\n\n", 3)on a buffer holding ten characters placed 16 characters and the terminator in 16 bytes. The running length now starts at the existing text length, and an already full destination returnsNP_UTIL_ERROR_BUFFER_TOO_SMALL.sceNpUtilJsonGetOneCharparsed the low half of a surrogate pair at offset 8 without checking that offsets 6 and 7 hold\u, so"\ud83dXXde00"decoded to U+1F600 and swallowed the two unrelated characters.sceNpUtilJsonUnescapealready makes that check; a high surrogate not followed by\unow fails the same way an invalid low surrogate does.sceNpUtilJsonUnescapeapplied its finalcount > dstSizecheck even for a null destination, so the size query(nullptr, 0, src, n, &length)returnedBUFFER_TOO_SMALLand never wrote the length, although the per-character checks in the same function skip the comparison for a null destination. The check now applies only when there is a destination. The console's behaviour for this exact call is not measured; the change makes the size query consistent with the rest of the function.The test commit adds the three assertions to
TestJsonTextinGuestNpCommonRuntime.cpp.Tested
Linux x86-64, a throwaway archive build with the host CPU gate patched.
guest_np_common_runtimepasses. I did not run the new assertions against the unfixed code.tools/check_conventions.py --base upstream/mainandgit diff --checkpass.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)