Skip to content

Commit aa9414b

Browse files
committed
fix: reject value substitution on non-sorry'd definitions
Compare.loop's dependency walk accepts any constant whose type matches between challenge and solution, even when the value (body) differs. A submitter can exploit this by redefining a non-sorry'd definition to make a false challenge statement true in the solution. Guard the type-only fallback with hasSorryAxValue: only fire when the challenge-side value references sorryAx. Non-sorry definitions with mismatched values are now rejected. Reproducer: https://github.com/savarin/comparator-proof-bypass
1 parent 8d84e67 commit aa9414b

1 file changed

Lines changed: 14 additions & 2 deletions

File tree

Comparator/Compare.lean

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ def addWorklist (n : Lean.Name) : CompareM Unit := do
3434
def addRelevantConsts (info : Lean.ConstantInfo) : CompareM Unit := do
3535
runForUsedConsts info addWorklist
3636

37+
/-- Check whether a ConstantInfo's value expression references `sorryAx`. -/
38+
def hasSorryAxValue : Lean.ConstantInfo → Bool
39+
| .defnInfo dv => dv.value.getUsedConstants.any (· == ``sorryAx)
40+
| .opaqueInfo ov => ov.value.getUsedConstants.any (· == ``sorryAx)
41+
| .thmInfo tv => tv.value.getUsedConstants.any (· == ``sorryAx)
42+
| _ => false
43+
3744
partial def loop : CompareM Unit := do
3845
if (← get).worklist.isEmpty then
3946
return ()
@@ -52,8 +59,13 @@ partial def loop : CompareM Unit := do
5259
solutionConst.type.getUsedConstants.forM addWorklist
5360
else
5461
if challengeConst != solutionConst then
55-
throw s!"Const does not match between challenge and target '{target}'"
56-
addRelevantConsts solutionConst
62+
if challengeConst.toConstantVal == solutionConst.toConstantVal
63+
&& hasSorryAxValue challengeConst then
64+
solutionConst.type.getUsedConstants.forM addWorklist
65+
else
66+
throw s!"Const does not match between challenge and target '{target}'"
67+
else
68+
addRelevantConsts solutionConst
5769

5870
modify fun s => { s with checked := s.checked.insert target }
5971
loop

0 commit comments

Comments
 (0)