fix(clone): compare oracle-call restrictions when overriding a module type - #1133
Merged
Merged
Conversation
strub
force-pushed
the
fix-clone-modtype-oinfos
branch
from
September 11, 2026 17:30
686d350 to
18f1399
Compare
… type `clone ... with module type X <- Y` (and `=`, `<=`) only compared parameters and procedure signatures, ignoring the allowed oracle calls. Since lemmas about `A <: X` are replayed verbatim for `A <: Y`, a looser `Y` made `false` derivable (EasyCrypt#1123). `EqTest.for_module_sig` now also requires, per procedure, equal sets of allowed calls (after parameter renaming and normalisation). Equality is exact: a tighter `Y` is unsound as well. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
strub
force-pushed
the
fix-clone-modtype-oinfos
branch
from
September 11, 2026 17:31
18f1399 to
0972608
Compare
strub
approved these changes
Sep 11, 2026
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.
Summary
clone ... with module type X <- Y(likewise=and<=) acceptedYwhenever its parameters and procedure names/types matched those ofX; the allowed-oracle-call sets (proc f() : t {O.g}) were never compared. Lemmas proved forA <: Xare replayed verbatim forA <: Y, so with a looserYthey can be instantiated with adversaries the original proof never accounted for, which yieldsfalse(see the MRE in the issue).Fixes #1123
Root cause
src/ecTheoryReplay.ml,replay_modtype, decides the override withEcReduction.EqTest.for_msig. Its implementation,for_module_siginsrc/ecReduction.ml, comparesmis_paramsandmis_bodyonly and ignoresmis_oinfos, in bothAliasandInlinemodes. The typing-side checkEcTyping.check_item_compatible(mode`Eq) does compare the sets, but the clone path bypasses it.Fix
for_module_signow additionally requires, per procedure, equality of the allowed-call sets: the parameter renaming already applied to the body is applied to the oracle infos, the paths are normalised withNormMp.norm_xfunwhen~normis set, and the lists are compared asSxsets, so the order in which the oracles are written is irrelevant.Since
for_module_typefalls back tofor_module_sigfor parameters whose type names differ, the signatures of functor parameters are covered as well.for_msighas no other caller;for_mexpr(module overrides inclone) inherits the stricter comparison of its parameters, where it is equally required.Exact equality is required in both directions, as in
check_item_compatible. A looserYis unsound as explained above. A tighterYis unsound too: module-type binders also occur negatively, in lemma hypotheses(forall (A <: X), ...) => ..., and the replayed proofs (which are not re-checked) may instantiate anX-lemma or axiom at a module such asWrap(B)that inhabitsXbut notY.Impact
Only
cloneoverrides of module types (and, through the parameter comparison, of modules) whose oracle-call sets differ are affected; they are now rejected with the existingmodule type X is incompatibleerror. Nocloneintheories/orexamples/overrides a module type or a module at all (the only such override is intests/clone-module-stateless.ec, with equal oracle sets), so no existing development relied on the lax check;make unitandmake stdlibpass, andmake examplesshows only the pre-existingChaChaPoly/chacha_poly.ecprover-timeout failure that occurs identically on unpatchedmain.Test
tests/clone-modtype-oinfos.ec: overrides that loosen or tighten the oracle set (via<-,=and<=) must fail, a mismatch inside a functor parameter's signature must fail, and the same set written in a different order must be accepted. The file fails on unpatchedmain(everyfail cloneis accepted there) and passes with this patch. The issue's MRE is now rejected at thecloneline.