Skip to content

Backport three rocqchk fixes (vm_caml_prim arity, -norec validation order, VM bytecode trust) - #9

Merged
archanaburra merged 4 commits into
v9.2+typewise-isomorphism-stablefrom
backport/checker-vm-and-validation-v9.2-stable
Aug 18, 2026
Merged

Backport three rocqchk fixes (vm_caml_prim arity, -norec validation order, VM bytecode trust)#9
archanaburra merged 4 commits into
v9.2+typewise-isomorphism-stablefrom
backport/checker-vm-and-validation-v9.2-stable

Conversation

@JasonGross

@JasonGross JasonGross commented Aug 18, 2026

Copy link
Copy Markdown
Member

Backports three rocqchk fixes from upstream onto the 9.2 stable branch, in this order:

Two regression tests come with the commits: test-suite/misc/rocqchk_vm_bytecode.sh and test-suite/misc/norec-validation-order.sh. Both pass here, as does a full rocqchk -bytecode-compiler yes run over Corelib.Init.Prelude (658 constants).

Note on overlap: this branch already carries 24dd96e "Verify serialized VM bytecode in coqchk" (#8), which attacks the same problem by recompiling each constant's bytecode and comparing it against the stored one. Upstream deliberately did not take that route — stored and recompiled code legitimately differ in relocation names, alias collapsing, the unused-argument mask, and the inlining of const_inline_code bodies. With rocq-prover#22353 applied, const_body_code has already been replaced by the recompiled code before check_constant_declaration sees it, so that check degenerates into comparing a recompilation against itself: harmless and passing, but redundant work. That check is removed in this PR (0163210). Besides being dead weight — it roughly doubled the bytecode compilation work — the two recompilations it compares happen in slightly different environments, so keeping it left a spurious rejection structurally possible for no benefit. The equality helpers #8 added to kernel/vmemitcodes.ml{,i} (equal_body_code, equal_to_patch_and_patches, equal_fv_elem, and Positions.equal) had no other users and are removed with it, restoring both files to their pre-#8 contents.

The same three commits have been applied directly to master+typewise-isomorphism and v9.2+typewise-isomorphism.

Opened autonomously by Claude (Opus 5) on behalf of Jason Gross (jason@theorem.dev).

JasonGross and others added 4 commits August 18, 2026 20:29
checker/values.ml capped vm_caml_prim at 6, the number of caml_prim
constructors when the VM validator was added in 09336f2. 15c0443 grew
the type to 12 by adding the string primitives without updating the
validator, so rocqchk -bytecode-compiler yes failed to intern any .vo whose
VM data references one, including Corelib.Strings.PrimString.

Fixes rocq-prover#22360.

(cherry picked from commit d9af170)
rocqchk read the marshalled data of a library without validation whenever
it was interned in Dep mode, that is as a dependency of a -norec argument.
Since the first intern of a library wins and the -norec roots are interned
in reverse command line order, a library named with -norec could be pulled
in as a dependency of another one and read raw, with neither structural
validation nor a comparison of the recorded segment checksums. Which files
were validated thus depended on the order of the -norec arguments.

Force validation for the libraries named on the command line, minus those
named with -admit. What gets checked is unchanged.

Fixes rocq-prover#22362.

(cherry picked from commit 527737e)
rocqchk with -bytecode-compiler yes typechecked each constant's body but took
the VM bytecode from the separately serialized vmlibrary segment of the .vo,
with nothing binding the two together. A crafted file whose vmlibrary disagrees
with its library makes a VM conversion prove False, and rocqchk accepts the
result with no axioms reported.

The checker now compiles the bytecode itself, from the bodies it checks, so the
two agree by construction. The vmlibrary segment is not read at all, and the
code descriptor stored in each declaration (const_body_code) is replaced rather
than kept: BCalias and the unused-argument mask are attacker-controlled too, and
the mask is used by ordinary conversion as well. Libraries imported with -admit
or as dependencies of -norec get the same treatment, so the trusted surface is
uniformly the declarations that are read.

Recompiling the bytecode and comparing it against the stored one instead is not
workable: stored and recompiled code legitimately differ in relocation names
(user vs canonical), in alias collapsing, in the unused-argument mask, and in
the inlining of const_inline_code bodies.

Fixes rocq-prover#22352.

Co-authored-by: Jason Gross <jason@theorem.dev>
(cherry picked from commit 89832f7)
The check compared the VM bytecode stored in the .vo against bytecode
recompiled from the checked body, and rejected the constant when the two
differed. That cannot be made to work: stored and recompiled bytecode
differ for perfectly ordinary code. The stored relocation entries name
constants by their user names while a fresh compilation produces
canonical ones, get_alias collapses aliases, the unused-argument mask is
computed from information the checker does not have, and bodies declared
inline are inlined into their callers' code. A module containing an
axiom and a definition that mentions it is already enough to trip it.

It is also pointless here. The checker now compiles the bytecode of
every constant itself and replaces const_body_code wholesale before any
constant is checked, and it never reads the vmlibrary segment of the .vo
at all, so by the time check_constant_declaration ran there was no
stored bytecode left to compare against: the check was comparing one
recompilation against another. That doubled the bytecode compilation
work, and because the two compilations happen in slightly different
environments it could also reject honest code for no reason.

Drop the check and the equality helpers in kernel/vmemitcodes that
existed only to serve it. Nothing else used them.
@archanaburra
archanaburra merged commit 1f3085b into v9.2+typewise-isomorphism-stable Aug 18, 2026
3 of 7 checks passed
@archanaburra
archanaburra deleted the backport/checker-vm-and-validation-v9.2-stable branch August 18, 2026 22:46
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.

2 participants