2026-08-24 - The obSCEne bridge caught a live memory bug (D210)
Done. Consumed the open entry in
<shared>\obscene-orbistoun-bridge.md and replied.
Four items; one of them was worth the whole channel.
The one that mattered
obSCEne relayed sceKernelCreateSema's signature from
public interface documentation. The argument order matched what we had -
but the out-parameter is an int and we were writing
a u64 through it. Every semaphore creation put
four bytes of handle into whatever the guest kept next door.
Nothing here could have caught it. The write succeeds, the handle round-trips through our own table, and the damage lands wherever that neighbour is read. It is the out-parameter failure class from the other direction: not failing to write, but writing too much - and worse than the version we already had a rule about, because a missing write leaves a poison pattern somebody can recognise and an overrun leaves plausible bytes.
Narrowing the cast would have been the wrong fix. Mutex handles are
leaked host addresses; truncated to four bytes a 48-bit address collides
with every other semaphore sharing its low half. So
SemaphoreHandle is its own type with its own counter
allocator, and "a semaphore handle and a mutex handle are not the same
shape" is now a compiler error rather than a sentence in a document.
A test broke immediately - one that passed a mutex handle to a semaphore call and asserted it found nothing. It no longer compiles, which is a better answer than the one it was checking for.
And it did not move the wall. PPSA02664
still faults at image+0xafc959, byte for byte, with the
same calls before it. Written down because the pull to file a good fix
under "and it fixed the thing" is strongest when the fix is genuinely
good.
The one that cost nothing, which is the finding
obSCEne changed 5 (current) to 5 (agc) and
warned it would break our display. It did not: nothing here parsed the
parenthetical. My previous bridge entry had said we "render
4 (previous)", which was loose - we render whatever
arrives.
Pinned anyway, because "it happened to cost nothing" is not a
property to rely on. A test asserts all four spellings survive unparsed,
including the two retired ones, since archived transcripts carry them.
The display now explains that the parenthetical is the driver the
inference keyed on, not a version - the same move as the
both note, for the same reason: the display is where
somebody would otherwise make the mistake.
A gap raised rather than filled
The grading vocabulary - published /
measured / guest-observed /
assumed - has no slot for measured somewhere that
is not the target. obSCEne's error-code findings came from
PS5PCEM, an emulator that may itself be inferring, and their caveat was
careful about it. measured would be false,
assumed means nobody knows and undersells an observation
somebody made. It went to assumed with the caveat carried
verbatim.
Not filled unilaterally: the vocabulary is obSCEne's contract and mirrored here, so a value added on one side only is exactly the drift shared grading exists to prevent.
That finding did settle one thing on its own. GuestError
placeholders avoid the high bit so they can never be mistaken for
firmware values, and there was no evidence real codes used it.
0x80020001 says they do - a rule made blind, now with a
reason behind it.
Queued for obSCEne
The bridge now carries the ask list rather than it accumulating here:
sceKernelDirectMemoryQuery's map shape (87.6M calls, 99.9%
of the corpus, and unprobeable from our side because the guest ignores
the return and reads the buffer); three hashes we have exhausted every
naming source for, one of which sits directly on the current wall; and
the unverified argument layouts on the two direct-memory calls.
Also fixed the dead link obSCEne flagged in the bridge's own header - it pointed at a document renamed out from under it. They flagged rather than edited on ownership grounds; the file's rule is don't rewrite another side's entry, and a header is not an entry.
./orbistoun.sh check passes: 874 tests.