TechnicalDebt.md only links back to this section; the list of calls that
act on a cancellation request and the note on the asynchronous type are
the Thread cancellation entry of debt/libkernel.md.
The table said Aps5StartGuest had no implementation on main, but
MainThreadMacOs.cpp defines it and libkernel's CMakeLists builds it. It
starts the guest on a second pthread (at least 8 MiB of stack) as
entry(block, nullptr) while the main thread runs the CFRunLoop, and it
aborts if the entry returns.
The directory limits (128 records, 256 MiB) throw CaptureLimit, which
WriteOptional catches: capture disables itself with one stderr line and
the pipeline is still created. Only the per-record 36 MiB limit throws
out of the capture, so the old sentence described both as an error.
TraceThread::Slice holds five eight-byte members (scope, stage, begin,
length and the recorder batch), so an event takes 40 bytes, not 32.
The example sizes follow: 10 MiB at the default 262,144 events, 120 MiB
at 3,145,728 and 160 MiB at the 4,194,304 maximum.
Main took request serialization version 48 for the fragment barycentric
built-ins flag (#9193). The depth export clamp bounds are now written at
version 49 and read only for versions from 49, so a version 48 request as main
writes it still decodes, with default bounds. Tests: version 49 is the
emitted prefix, 50 the first unsupported one, a depth exporting request
without its bounds decodes at 48, 47 and 46 (the last two without main's
barycentric byte), and a version 48 two-sample dithered request decodes as
written.
scePthreadMutexattrSetkind called NotImplemented_nid_no_patch for a kind
outside 1 to 4. Firmware 13.42's libkernel, run in an emulator, makes it
call pthread_mutexattr_setkind_np, which stores any kind as a signed
16-bit value and returns 0, and turns a null attribute's -1 with errno 22
into 0x8001FFFF. It now forwards to pthread_mutexattr_setkind_np and
converts the result with sceKernelError, so a null attribute or object
still returns 0x8001FFFF and now also sets errno 22.
An out-of-range kind is refused by scePthreadMutexInit with 0x80020016,
leaving the mutex untouched, as measured for the same module.
scePthreadMutexattrGetkind is unchanged; kind 0 now reaches it and
returns 0.
setenv replaced a variable's string with a new allocation and freed the
old one, and unsetenv freed it as well, so a pointer that getenv had
returned for that variable dangled. A guest that reads such a pointer
after setenv(name, value, 1) reads freed host memory: AddressSanitizer
reports a heap-use-after-free on that read.
FreeBSD 11.4's getenv.c, which holds the setenv, unsetenv and putenv the
console's libc exports next to getenv, never frees a variable's string
("No previous variables are ever freed here to avoid causing a
segmentation fault in a user's code", lib/libc/stdlib/getenv.c lines
449-520 at 8c639945a4). setenv and unsetenv mark the old string
inactive; setenv writes the new value over the latest string of that
name when the value fits and allocates a new string otherwise; putenv
strings stay the caller's and are only forgotten.
The guest environment now keeps every string it allocates with its value
capacity and an active flag and follows that code: getenv and the time
zone lookup read the name's latest active string, setenv reuses the
latest string of the name when it fits, an unset one included, and
otherwise appends a new one and deactivates the old, putenv replaces an
earlier putenv string or deactivates the setenv one, and unsetenv
deactivates them all. Built on the host next to this library, FreeBSD's
getenv.c gave the same results, errno, pointer reuse and contents of
every earlier pointer over 160,000 random calls once the putenv flag it
leaves uninitialized in new setenv strings was cleared; the debt entry
records that the console may allocate where this reuses.
guest_environment checks the reuse, that earlier values stay readable
after a longer setenv and after unsetenv, and that putenv and setenv
leave each other's strings alone.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01DXPnhogDW4zpeNCBro4Ctt
The libc.prx that titles ship evaluates the rational step as
((Q(z) + g*P(z)) + 1) / ((Q(z) - g*P(z)) + 1), with its own ln 2 split
and coefficients in the double case, and returns 1 only for arguments
within half an epsilon of zero. main used a different rational form
with a doubling step and an epsilon-wide shortcut, which left about one
result in five one ulp away from titles.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
sceNpMatching2SignalingGetConnectionStatus reports every member inactive
for a known context, since no room is joined offline, and leaves the peer
address and port untouched; a null status pointer throws.
sceNpMatching2AbortContextStart returns NOT_INITIALIZED before
initialization and 0 afterwards. Checks follow shadPS4, with RPCS3's
differences recorded in the technical debt entry.
The 816 bytes after the 128-byte device name are the PS4
SceAutoMounterClientUsbDeviceInfo fields up to the serial length in
flatz's ps4_stub_lib_maker_v2 header: the total and available space, the
vendor id, product id and release, and the manufacturer, product and
serial strings with their lengths. libSceUsbStorage's device-info record
starts with the same layout. Every field offset is now asserted; the
size and offsets do not change.
Callers of ApplicationProcessParameters_nid_no_patch read the compiled SDK
version at offset 16 without a null check, so the null result for the
no-parameters record would crash them. The lookup now returns a static
zeroed 0x40-byte block for that record, and the heap recognises it by
address and keeps registering its default allocator.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>