Skip to content

Run the tests where poppler does not go, and on 32-bit - #10

Merged
tannevaled merged 2 commits into
mainfrom
everywhere
Sep 26, 2026
Merged

tannevaled merged 2 commits into
mainfrom
everywhere

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

What this changes

One job, six lanes — riscv64, loong64, ppc64le, s390x, 386, arm —
each running the full test suite under qemu-user-static. fail-fast: false,
so one architecture failing does not hide the next one's result.

Why a cross-compile was not enough

A build proves the code is well-formed for a target. It proves nothing about
whether it computes the right answer there, and this is a byte-stream reader:
every multi-byte number it reassembles is a place an endianness assumption can
sit undisturbed for as long as nobody looks, and every width × height is a
product that fits a 64-bit int and may not fit a 32-bit one.

That is not hypothetical. The same two lanes added to go-pdfkit/render found a
ceiling that a 32-bit int walked straight through — 65535 × 65535 wraps to
−131 071, so a 1 KB file made the decoder ask for four gigabytes — and, from
the same thread, a MediaBox of 1e300 that panicked the renderer on 64-bit
too
.

Where this leaves the references

poppler and pdfium test on none of the four 64-bit architectures here. 32-bit
ARM they do hold, and we did not.

🤖 Generated with Claude Code

Cross-compiling proves the code is well-formed for a target. It says nothing
about whether it computes the right answer there, and this package reassembles
multi-byte numbers out of a byte stream and multiplies widths by heights -- the
two shapes in which an endianness assumption and an integer overflow hide.

Six lanes under qemu-user-static: riscv64, loong64, ppc64le, s390x (big-endian)
and 386/arm (32-bit int).

The same lanes on go-pdfkit/render found a real defect within the hour: a
ceiling written as `cw*ch > max` that a 32-bit int wrapped past, letting a 1 KB
file ask the decoder for four gigabytes.
The lanes added in this branch did not even build:

    ./tounicodebound_test.go:137: cannot use 0xffff0000 (untyped int constant
    4294901760) as int value in map index (overflows)

A ToUnicode code is assembled into an int a byte at a time, so a four-byte code
lands on a different number depending on how wide an int is: 4 294 901 760 where
int is 64 bits, minus 65 536 where it is 32. Reading and writing both go through
that same conversion, so the package is self-consistent on either width -- but a
constant written out in the test is not, and on 32-bit it is not even a legal
int.

The test now assembles the key the way the package does.
@tannevaled
tannevaled merged commit dfa91ea into main Sep 26, 2026
7 checks passed
@tannevaled
tannevaled deleted the everywhere branch September 26, 2026 10:09
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