Repository navigation
fix(libc): follow the default heap's alignment, errno and realloc to zero as measured on a PS5 - #8720
Conversation
…zero as measured on a PS5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
I noticed |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks, good catch. |
|
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.
|
|
Thanks for the update and the added two-sided |
MarcZX10
left a comment
There was a problem hiding this comment.
Reviewed the updated allocator wrappers and rechecked the rerun matrix. The default-heap behavior is isolated through ApplicationHeapDefault_nid_no_patch; replacement heaps retain their prior paths. reallocf now delegates to the same realloc error classification and frees the original block only after a nonzero-size failure, with tests for both sides of the measured limit and zero-size retention. The relinker and register-context matrix is green, including Windows; the full Linux/Windows build jobs were skipped by workflow rules. I am relying on the author’s Windows full-suite and PS5 payload measurements for the allocator behavior.
|
Linux data point for
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Measured |
|
@orezraey Please remove GuestReallocalign.cpp’s final loose-block loop asserting that reallocalign(loose, 0, 4096) throws for the explicitly unmeasured case. The tests should not pin unimplemented behaviour. Keep measured aligned zero-size retention, alignment rounding, errno boundaries and replacement-heap controls, then rerun the focused Linux and Windows tests on this exact head; the earlier Linux report covers 55e4819 rather than this revision. |
…nment Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Removed the final loose-block loop from |
What
With the default heap, the malloc family followed FreeBSD 11.4's jemalloc for failures and alignments, and
realloc(ptr, 0)freed the block; the debt entry said none of it was measured on the console. In a payload process on a PS5 (firmware 13.60), libSceLibcInternal's heap behaves differently, and this PR follows it:mainbefore this PRrealloc(block, 0),reallocalign(block, 0, a)malloc_usable_size0; a laterreallocof it to 64 bytes returns a new blockmemalign(a, n),reallocalign(p, n, a)witha0 or not a power of twoarounded up to a power of two, at least 32, as formalloc(100 → 128, 1000 → 1024, 4097 → 8192, 12288 → 16384)errnoEINVALaligned_alloc(a, n)witha0 or not a power of twoerrnountouchedEINVALerrnountouchedmalloc,calloc,realloc,memalign,aligned_alloc,reallocalignfailing for a size up to the limit belowerrnoEINVAL(22), from 2^33 upENOMEMEINVALSIZE_MAX - 0x1008f, or aboveSIZE_MAX - (A + 0x100af)for an alignment above 32 rounded up toA; acallocproduct that overflowserrnountouchedENOMEMerrnountouchedmemalign,aligned_alloc,reallocalignwith an alignment of 2^63 or moreerrnountouched (2^62 + 1 and 3·2^61 fail withEINVAL)EINVALfor a non-power of two,ENOMEMfor 2^63errnountouchedposix_memalignfailingENOMEMand setserrnotoEINVAL, except for a request above the limit or an alignment of 2^63, whereerrnois untouched; an alignment below 8 or not a power of two returnsEINVALwithout touchingerrnoor the outputENOMEM,errnountouchedreallocThe limit was found by bisection:
malloc(0xfffffffffffeff70)fails withEINVAL,malloc(0xfffffffffffeff71)leaveserrnoalone, andcalloc(1, n),realloc(block, n),aligned_alloc(16, n),reallocalign(p, n, 16)andposix_memalign(&p, 16, n)switch at the same size. Formemalignandreallocalignwith an alignment above 32 it moves by the rounded alignment: 64 →0xfffffffffffeff10, 128 →…fed0, 256 →…fe50, 512 →…fd50, 1024 →…fb50, 2048 →…f750, 4096 →…eef50, 8192 →…edf50, 65536 →…dff50, 2^30 →0xffffffffbffeff50, 2^40 →0xfffffefffffeff50, 2^62 →0xbffffffffffeff50, and 3·2^61 →0x7ffffffffffeff50, the same as 2^63. Alignments up to 32 (0, 3, 32) use themalloclimit.Heaps a title replaces through its process parameters keep the old behaviour: the console was measured only with its own heap, so
ApplicationHeapDefault_nid_no_patchtells the two apart and the replacement path keeps its old behaviour.reallocalign(block, 0, a)for a block that does not already have the rounded alignment was not measured and throws.reallocfnow calls thisreallocand frees the block only when it fails for a nonzero size, as FreeBSD 11'sreallocf.cdoes, so it reports the sameerrnoandreallocf(block, 0)keeps the block.reallocfitself was not called on the console.Debt: the heap entry in
docs/dev/debt/libc.mdnow records the measured rules, what is still unmeasured (the title-replaced heap, a title process,reallocalignto 0 bytes with a stricter alignment), and thereallocfentry says it now inheritsrealloc's result anderrno.How the console was measured
resolvelines show thatmalloc,calloc,realloc,memalign,aligned_alloc,reallocalign,posix_memalign,malloc_usable_sizeandfreewere taken fromlibSceLibcInternal.sprxbydlsymand called through those pointers.errnowas set to 1234 before each call, so "untouched" means it was still 1234 after the call.EINVAL) andSIZE_MAX(leaveserrnoalone).[SceLibcInternalHeap] A too large request for the heap.report on each failed request; those lines are left out of the excerpt.main.crenamed<probe>_main.c.Console output (excerpt, lines copied unchanged)
The
heapN:prefix names the probe; the rest of each line is copied unchanged.Tested
Build: Windows 11 x86-64, full build with WinLibs MinGW-w64 GCC 15.2.0 (posix-seh, ucrt, r7) and
-DBUILD_TESTING=ON. The full suite ran onmain2962d21; after rebasing onto 339217e the heap tests below were rebuilt and run again.Tests:
guest_allocator_failures,guest_reallocalign,guest_heap_rounding_overflowand the nineapplication_heap_*tests pass. They now check:reallocandreallocalignto 0 bytes;posix_memalignreturn values anderrno;reallocalign(block, 0, 4096)on a block without that alignment throws.agc_driver_image_array_window_past_layer_limitdoes not compile with MinGW (alignas(65536), fixed by test(agc): align the array window test's texels at run time #8310).select_tests, a test oftools/select_tests.py, fails here while creating a directory link in TEMP.agc_driver_lookup_log_fits_buildfailed once under-j8and passed when run alone.Old code, new tests: with the four libc sources reverted to
mainand the new tests kept:guest_allocator_failuresreports 24 failed checks (errno12 where the console gives 22 or leaves it alone, andmemalign(3, 40)returning null);guest_reallocalignandapplication_heap_defaultabort.Not run here: Linux and macOS. The tests are portable except
GuestHeapRounding.cpp, which is Windows only.Console: behaviour measured on a PS5 (firmware 13.60), as described above.
Overlaps:
tools/pr_overlap.pyreports no conflicting lines.main.FileAndHeap.cpp, and other open PRs change other entries ofdocs/dev/debt/libc.md.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)