net: span the embedded-pointer class across all five decode routes - #50
Merged
Conversation
The embed net generated a pointer embed on half its 16,000 shapes and then
called allocPointers on every one before encoding, so the OCCUPANCY axis
carried a single value: every generated pointer embed reached the codecs
ALLOCATED. The nil arm was reached by nothing but an instance pin.
Worse on the decode side. fieldByIndex's refusal to write through a nil
UNEXPORTED embedded pointer has five call sites -- the compiled binary
decoder, JSON decode's present-key and default-fill arms, and the resolved
decoder's writer-op and reader-default arms. TestRegression_EmbeddedPointer-
StructNoPanic pinned one. The other four error arms were executed by no test
in the suite at all.
Behavior is correct on all five (verified against encoding/json, which
refuses the same shape for the same reason and which fieldByIndex's comment
already claimed parity with) -- this closes the net, it does not fix a bug.
- TestMatrix_NilEmbedPointerRouteAgreement: occupancy {nil, pre-allocated}
x exportedness {exported, unexported} x route {5 decode sites}, plus the
3 encode sites against an all-zero map twin. encoding/json supplies the
accept/reject verdict cell by cell.
- TestInvariant_EveryFieldByIndexSiteHasARouteCell: derives the call-site
set from source by AST scan and reds in BOTH directions -- a new site
landing without a cell, or a listed site going away.
- roundTripNilEmbed: the occupancy arm inside the generative net, now
7,544 of its round trips carry a NIL pointer embed, with a floor that
fails if the axis goes dead again.
Neuter evidence, one distinct red per mechanism (exit != 0, RUN > 0, no
"panic:"):
neutered arm matrix generative old pin
unsafe.go deserRecordFast RED green RED
json_decode present-key RED green green
json_decode default-fill RED green green
resolve.go writer-op RED green green
resolve.go reader-default RED green green
fieldByIndexZero nil detection RED RED panics
fieldTypeByIndex leaf resolution green RED green
The four green cells in the old-pin column are the gap this closes; the last
row is a defect only the generative arm's deeper index paths can see.
Coverage: 4 blocks went from covered-by-nothing to covered, 4 from
reachable-only-via-TestRegression to covered. Full suite green, -race green.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A real hole in the suite, found by auditing the
TestRegressionbattery.Stacked on #49. No behavior change — this is test coverage only.
The gap
fieldByIndexrefuses to write through a nil unexported embedded pointer,because Go reflection cannot allocate one. That refusal has five call sites.
The suite proved it on one:
unsafe.godeserRecordFastjson_decode.godecodeRecordStruct x2resolve.godeserStruct x2Four of five routes had no test at all. Neutering each left the pin green.
Behavior is correct on all five
Verified against
encoding/json, which refuses the identical shape for thesame reason —
json: cannot set embedded pointer to unexported struct— andwhich
fieldByIndex's own comment already claimed parity with. That claim wasexecuted rather than trusted. No bug here; a class proven on one route in
five.
Why the generative net missed it
TestGenerative_EmbedShapeWalkerAgreementgenerates a pointer embed on half ofits 16,000 shapes — and then called
allocPointerson every one beforeencoding. So for the net's entire history the occupancy axis carried a single
value while the shape axis looked fully crossed. A net can be enormous and
still be blind along an axis it appears to sweep.
What now spans it
TestMatrix_NilEmbedPointerRouteAgreement— occupancy {nil, pre-allocated}x exportedness x route {5 decode sites}, plus the 3 encode sites against an
all-zero map twin.
encoding/jsongives the accept/reject verdict cell bycell, with a guard that fails if the oracle ever answers uniformly.
TestInvariant_EveryFieldByIndexSiteHasARouteCell— derives the call-siteset by AST scan and reds in both directions, so a new caller cannot ship
unexercised. It caught a mis-keyed table entry on its first run.
roundTripNilEmbed— the occupancy arm inside the generative net. 7,544round trips now carry a nil pointer embed, with a liveness floor that fails
if the axis goes dead again.
Neuter gate — one distinct red per mechanism
unsafe.gocompiled decodeEvery red: exit != 0, RUN > 0, no
panic:, each naming its own cell. The fourgreen cells in the pin column are the gap. The last row is a deeper-index-path
defect only the generative arm can see — the hand matrix's 1-deep path makes
that neuter a no-op, which is why both extensions earn their place.
Coverage: 4 blocks covered-by-nothing and 4 reachable-only-via-regression are
now netted. Only-regression 183 -> 179, dark 284 -> 279. Suite green,
-racegreen.