Skip to content

README: the 32-bit refusal, and a count three review rounds had falsified - #42

Merged
tannevaled merged 1 commit into
mainfrom
docs/linearization-refuses-unaddressable-values
Nov 13, 2026
Merged

tannevaled merged 1 commit into
mainfrom
docs/linearization-refuses-unaddressable-values

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

Two README claims about the linearization checker, after the deep-check work landed.

A published count that three review rounds had falsified

"The four cases that gate it" was true when written. The overflow-hint table alone now carries five cases, the hint table more, and the last round added four more again. Nobody noticed, because nothing can notice a number in prose.

The replacement states the method instead — a same-width edit of the committed qpdf fixture, so /L still matches and the front of the file is still correct. That is what a reader needs in order to add a case, and it is the part that does not go stale. The count added nothing and was the only part that could rot.

The 32-bit refusal was public behaviour and was undocumented

The merged change made every integer in the parameter dictionary go through one conversion that refuses a value this build cannot address, rather than letting int(Integer) discard the high half. That is a new error a caller can receive (ErrLinearizationMalformed) and it was not in the README.

The section also records why the two findings were not the same size, since only one of them had a symptom:

  • CI's 386 and arm lanes went red on values that become -1. Those land where a bound already objects, so they were caught by accident of magnitude.
  • Review named the one that has no symptom: /H of 2³²+127 truncating to 127, which is the committed fixture's own hint length. Every later check accepts it. The same bytes would be judged sound on a 32-bit build and refused on a 64-bit one, with nothing to say which had happened.

It also records that the limit is a variable the tests shrink, because on a 64-bit build the refusal is unreachable from any file — otherwise that branch is exercised only by CI, which is to say only after pushing.

No code change; go test green.

Refs #40, #41.

🤖 Generated with Claude Code

…d falsified

⛔ A PUBLISHED COUNT DRIFTS AND NOTHING NOTICES. "The four cases that gate it"
was true when written and had not been true for three review rounds — the
overflow table alone carries five. The sentence is about the METHOD, which is
what a reader needs and what does not go stale: a same-width edit of the
committed qpdf fixture, so /L still matches and the front of the file is
still correct. The number added nothing and was the only part that could rot.

⛔⛔ AND THE 32-BIT REFUSAL WAS NOT DOCUMENTED AT ALL, though it is public
behaviour: a new error for values this build cannot address, on every entry
including /P. A caller on a 32-bit build was previously handed a truncated
value with no way to know.

The README says why the hazard is not the value that becomes -1 — that one
lands where a bound objects — but the one that lands on a PLAUSIBLE value:
2^32+127 truncating to 127, the fixture's own hint length. Both findings are
recorded with their provenance, because they were not the same size and CI
found only the smaller one.

Refs #40.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit 94073c7 into main Nov 13, 2026
9 checks passed
@tannevaled
tannevaled deleted the docs/linearization-refuses-unaddressable-values branch November 13, 2026 16:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant