参考文档 / ZLIB × LEAN
inffast.c.body-origin.lean
此页源文件快照 ·
250cb14d7ef6d156 · 对应提交的原文 ↗本页保留 Lean 源码及行号。点击行号可定位语句,点击 import 中的模块名可查看依赖。
1import ZlibF.Spec.InflateFastBodyOrigin
2import ZlibF.Proof.«inffast.c.origin»
3import ZlibF.Proof.«inffast.c.body»
4import ZlibF.Proof.«inffast.c.distance-origin»
5
6/-!
7# The actual fast body preserves its source-bit origin
8
9Every source refill and drop updates the exact suffix invariant. Copying
10and control fields preserve the buffered bits. No decoding-table semantic
11contract is assumed; the existing table safety domain is retained.
12-/
13
14namespace Zlib.Inffast.Proofs.BodyOriginProof
15open C Zlib.Inffast Zlib.Inffast.Spec Zlib.Inffast.Proofs ZlibF.Spec
16
17variable {e : Env} {c : Ctx}
18
19private theorem pull_origin {l : L} {i o used : Nat}
20 (hl : LS e l i o) (origin : Origin.Inv e l.hold.toNat l.bits.toNat i used)
21 (buffer : l.bits.toNat ≤ 22) (available : i < e.i0 + e.sm0.avail_in.toNat) :
22 Origin.Inv e (pullL l (e.IN.getD i 0) (.ref (.blk e.ib) (i + 1))).hold.toNat
23 (pullL l (e.IN.getD i 0) (.ref (.blk e.ib) (i + 1))).bits.toNat (i + 1) used := by
24 have next := pull_preserves_origin e l.hold.toNat l.bits.toNat i used origin available
25 simpa only [pullL_hold l _ _ hl.hb hl.hH, pullL_bits l _ _ hl.hb] using next
26
27private theorem drop_origin {l : L} {i o used : Nat} (count : UInt32)
28 (hl : LS e l i o) (origin : Origin.Inv e l.hold.toNat l.bits.toNat i used)
29 (available : count.toNat ≤ l.bits.toNat) :
30 Origin.Inv e (dropL l count).hold.toNat (dropL l count).bits.toNat i (used + count.toNat) := by
31 exact (actual_drop_preserves_origin e e.h0 l i o used count hl origin available).2.2
32
33private theorem refill_origin_wp (hc : CtxOK e c) (A : Array UInt8) (msg : BPtr) (m : UInt32) (l : L) (i o s used : Nat)
34 (hls : LS e l i o) (hA : e.o0 + e.sm0.avail_out.toNat ≤ A.size) (ho : o + 258 ≤ e.o0 + e.sm0.avail_out.toNat)
35 (hAb : A.size < 2 ^ 63) (hbroke : l.broke = false) (hlen : 3 ≤ l.len.toNat ∧ l.len.toNat ≤ 258)
36 (hs6 : s + 6 ≤ e.i0 + e.sm0.avail_in.toNat) (hT : i ≤ s + 3) (hT3 : i = s + 3 → 4 ≤ l.bits.toNat)
37 (origin : Origin.Inv e l.hold.toNat l.bits.toNat i used) :
38 Wp (dolenRefill c l) (e.heap A msg m) (fun l' _ =>
39 ∃ i' o' used', LS e l' i' o' ∧ Origin.Inv e l'.hold.toNat l'.bits.toNat i' used' ∧ used ≤ used') := by
40 unfold dolenRefill
41 by_cases h1 : l.bits < 15
42 · simp only [h1, ite_true]
43 have h1' : l.bits.toNat < 15 := by simpa using UInt32.lt_iff_toNat_lt.mp h1
44 have hiin : i < e.i0 + e.sm0.avail_in.toNat := by omega
45 refine Wp.bindO (pull_run e _ l i o hls (by omega) hiin (e.heap_bytes_in A msg m)) ?_
46 have hl3 := hls.pullL (by omega) hiin
47 have origin3 := pull_origin hls origin (by omega) hiin
48 have hb3 := pullL_bits l (e.IN.getD i 0) (.ref (BRef.blk e.ib) (i + 1)) hls.hb
49 have hi2 : i + 1 < e.i0 + e.sm0.avail_in.toNat := by omega
50 have hb3' : (pullL l (e.IN.getD i 0) (.ref (BRef.blk e.ib) (i + 1))).bits.toNat ≤ 22 := by
51 simp only [pullL] at hb3 ⊢; omega
52 refine Wp.bindO (pull_run e _ _ (i + 1) o hl3 hb3' hi2 (e.heap_bytes_in A msg m)) ?_
53 have hl4 := hl3.pullL hb3' hi2
54 have origin4 := pull_origin hl3 origin3 hb3' hi2
55 have hb4 := pullL_bits (pullL l (e.IN.getD i 0) (.ref (BRef.blk e.ib) (i + 1))) (e.IN.getD (i + 1) 0)
56 (.ref (BRef.blk e.ib) (i + 1 + 1)) hl3.hb
57 simp only [pullL] at hb3 hb4
58 obtain ⟨lr, hr, run, _, endOrigin⟩ := actual_distance_block_preserves_origin e c A msg m _ (i + 1 + 1) o used
59 hc hl4 hA ho hAb hbroke hlen (by simp only [pullL]; omega) (by
60 by_cases hc3 : i = s + 3
61 · right; have := hT3 hc3; simp only [pullL]; omega
62 · left; omega) origin4
63 exact Wp.of_eq run endOrigin
64 · simp only [h1, ite_false]
65 have h1' : 15 ≤ l.bits.toNat := by
66 have : ¬ (l.bits.toNat < 15) := fun h => h1 (UInt32.lt_iff_toNat_lt.mpr (by simpa using h))
67 omega
68 obtain ⟨lr, hr, run, _, endOrigin⟩ := actual_distance_block_preserves_origin e c A msg m l i o used
69 hc hls hA ho hAb hbroke hlen h1' (Or.inl (by omega)) origin
70 exact Wp.of_eq run endOrigin
71
72private theorem ext_origin_wp (hc : CtxOK e c) (A : Array UInt8) (msg : BPtr) (m : UInt32) (l : L) (i o s used : Nat)
73 (hls : LS e l i o) (hA : e.o0 + e.sm0.avail_out.toNat ≤ A.size) (ho : o + 258 ≤ e.o0 + e.sm0.avail_out.toNat)
74 (hAb : A.size < 2 ^ 63) (hbroke : l.broke = false) (hx : l.op.toNat ≤ 5) (hxb : l.op.toNat ≤ l.bits.toNat)
75 (hlen : 3 ≤ l.len.toNat ∧ l.len.toNat + 2 ^ l.op.toNat ≤ 259)
76 (hs6 : s + 6 ≤ e.i0 + e.sm0.avail_in.toNat) (hT : i ≤ s + 3) (hT3 : i = s + 3 → 4 + l.op.toNat ≤ l.bits.toNat)
77 (origin : Origin.Inv e l.hold.toNat l.bits.toNat i used) :
78 Wp (dolenExt c l) (e.heap A msg m) (fun l' _ =>
79 ∃ i' o' used', LS e l' i' o' ∧ Origin.Inv e l'.hold.toNat l'.bits.toNat i' used' ∧ used ≤ used') := by
80 unfold dolenExt
81 have hxs : l.op.toNat < 32 := by omega
82 refine Wp.bindO (shl32_ok hxs) ?_
83 dsimp only
84 have hlow := hold_low32 (x := l.hold) (k := l.op) hxs
85 have hlowlt : l.hold.toNat % 2 ^ l.op.toNat < 2 ^ l.op.toNat := Nat.mod_lt _ (Nat.pow_pos (by omega))
86 have hpow : 0 < 2 ^ l.op.toNat := Nat.pow_pos (by omega)
87 have hlen' : (l.len + (l.hold.toUInt32 &&& (1 <<< l.op) - 1)).toNat = l.len.toNat + l.hold.toNat % 2 ^ l.op.toNat := by
88 rw [u32_toNat_add (by rw [hlow]; omega), hlow]
89 refine Wp.bindO (shr64_ok (x := l.hold) (n := l.op.toUInt64) (by rw [UInt32.toNat_toUInt64]; omega)) ?_
90 have hls1 : LS e (dropL l l.op) i o := hls.dropL l.op hxb (by omega)
91 have origin1 := drop_origin l.op hls origin hxb
92 have hbn := dropL_bits l l.op hxb
93 refine Wp.mono (refill_origin_wp hc A msg m
94 { in_ := l.in_, out := l.out, hold := l.hold >>> l.op.toUInt64, bits := l.bits - l.op, here := l.here, op := l.op,
95 len := l.len + (l.hold.toUInt32 &&& (1 <<< l.op) - 1), dist := l.dist, from_ := l.from_, broke := l.broke,
96 againL := l.againL, againD := l.againD } i o s (used + l.op.toNat) (LS.congr hls1 rfl rfl rfl rfl) hA ho hAb hbroke
97 (by rw [hlen']; omega) hs6 hT (by intro h3; have := hT3 h3; show 4 ≤ (l.bits - l.op).toNat; simp only [dropL] at hbn; omega)
98 origin1) ?_
99 intro l' h' result
100 obtain ⟨i', o', used', locals, finalOrigin, mono⟩ := result
101 exact ⟨i', o', used', locals, finalOrigin, by omega⟩
102
103private theorem len_origin_wp (hc : CtxOK e c) (A : Array UInt8) (msg : BPtr) (m : UInt32) (l : L) (i o s used : Nat)
104 (hls : LS e l i o) (hA : e.o0 + e.sm0.avail_out.toNat ≤ A.size) (ho : o + 258 ≤ e.o0 + e.sm0.avail_out.toNat)
105 (hAb : A.size < 2 ^ 63) (hbroke : l.broke = false) (hx : l.op.toNat ≤ 5)
106 (hlen : 3 ≤ l.len.toNat ∧ l.len.toNat + 2 ^ l.op.toNat ≤ 259)
107 (hs6 : s + 6 ≤ e.i0 + e.sm0.avail_in.toNat) (hT : i ≤ s + 2) (hb2 : i = s + 2 → 1 ≤ l.bits.toNat)
108 (origin : Origin.Inv e l.hold.toNat l.bits.toNat i used) :
109 Wp (dolenLen c l) (e.heap A msg m) (fun l' _ =>
110 ∃ i' o' used', LS e l' i' o' ∧ Origin.Inv e l'.hold.toNat l'.bits.toNat i' used' ∧ used ≤ used') := by
111 unfold dolenLen
112 by_cases h0 : l.op != 0
113 · simp only [h0, ite_true]
114 have h0' : l.op.toNat ≠ 0 := by
115 intro h; apply (by simpa using h0 : l.op ≠ 0); exact UInt32.toNat_inj.mp (by simpa using h)
116 by_cases h1 : l.bits < l.op
117 · simp only [h1, ite_true]
118 have h1' : l.bits.toNat < l.op.toNat := UInt32.lt_iff_toNat_lt.mp h1
119 have hiin : i < e.i0 + e.sm0.avail_in.toNat := by omega
120 refine Wp.bindO (pull_run e _ l i o hls (by omega) hiin (e.heap_bytes_in A msg m)) ?_
121 have hl3 := hls.pullL (by omega) hiin
122 have origin3 := pull_origin hls origin (by omega) hiin
123 have hb3 := pullL_bits l (e.IN.getD i 0) (.ref (BRef.blk e.ib) (i + 1)) hls.hb
124 exact ext_origin_wp hc A msg m _ (i + 1) o s used hl3 hA ho hAb hbroke (by simp only [pullL]; omega)
125 (by simp only [pullL] at hb3 ⊢; omega) (by simp only [pullL]; omega) hs6 (by omega)
126 (by intro h3; simp only [pullL] at hb3 ⊢; have := hb2 (by omega); omega) origin3
127 · simp only [h1, ite_false]
128 have h1' : l.op.toNat ≤ l.bits.toNat := by
129 have : ¬ (l.bits.toNat < l.op.toNat) := fun h => h1 (UInt32.lt_iff_toNat_lt.mpr h)
130 omega
131 exact ext_origin_wp hc A msg m l i o s used hls hA ho hAb hbroke hx h1' hlen hs6 (by omega)
132 (by intro h3; omega) origin
133 · simp only [h0, ite_false]
134 exact refill_origin_wp hc A msg m l i o s used hls hA ho hAb hbroke ⟨hlen.1, by
135 have : 0 < 2 ^ l.op.toNat := Nat.pow_pos (by omega)
136 omega⟩ hs6 (by omega) (by intro h3; omega) origin
137
138set_option maxHeartbeats 1000000 in
139/-- One actual length-table pass either follows its one permitted link or
140establishes the reviewed body postcondition. -/
141private theorem pass_origin_wp (hc : CtxOK e c) (A : Array UInt8) (msg : BPtr) (m : UInt32)
142 (l : L) (i o s d k used : Nat) (hls : LS e l i o) (hAsz : A.size = e.A0.size)
143 (ho : o + 258 ≤ e.o0 + e.sm0.avail_out.toNat) (hbroke : l.broke = false)
144 (hs6 : s + 6 ≤ e.i0 + e.sm0.avail_in.toNat) (hsi : s ≤ i) (hT : i ≤ s + 2)
145 (hb15 : 15 ≤ l.bits.toNat + d) (hbi2 : i = s + 2 → 16 ≤ l.bits.toNat + d)
146 (hhere : l.here = .ref e.rl k) (hk : k < e.LCA.size)
147 (hEb : (e.LCA.getD k default).bits.toNat ≤ l.bits.toNat)
148 (hEd : (e.LCA.getD k default).bits.toNat + d ≤ 15)
149 (hcl : (LenLink (e.LCA.getD k default) ∧ LinkOK LenLeaf e.LCA e.ol (e.LCA.getD k default)) ∨
150 LenLeaf d (e.LCA.getD k default))
151 (origin : Origin.Inv e l.hold.toNat l.bits.toNat i used) :
152 Wp (dolen c l) (e.heap A msg m) (fun l' h' =>
153 ((l'.againL = true ∧ l'.broke = false ∧ h' = e.heap A msg m ∧
154 LenLink (e.LCA.getD k default) ∧
155 ∃ j, j < 2 ^ (e.LCA.getD k default).op.toNat ∧
156 l'.here = .ref e.rl (e.ol + (e.LCA.getD k default).val.toNat + j) ∧
157 LS e l' i o ∧ l'.bits.toNat = l.bits.toNat - (e.LCA.getD k default).bits.toNat) ∨
158 StepPost e A msg m s o l' h') ∧
159 ∃ i' o' used', LS e l' i' o' ∧ Origin.Inv e l'.hold.toNat l'.bits.toNat i' used' ∧ used ≤ used') := by
160 have hA : e.o0 + e.sm0.avail_out.toNat ≤ A.size := by rw [hAsz]; exact e.hAsz
161 have hAb : A.size < 2 ^ 63 := by rw [hAsz]; exact e.hAbig
162 have hkE : e.LCA[k]'hk = e.LCA.getD k default := by simp [Array.getD_eq_getD_getElem?, hk]
163 have hld : OkOn (e.heap A msg m) (Ptr.load l.here) (e.LCA.getD k default) := by
164 rw [hhere, ← hkE]; exact Ptr.load_ok (e.heap_cget_LCA A msg m) hk
165 have hEbn : (e.LCA.getD k default).bits.toUInt32.toNat = (e.LCA.getD k default).bits.toNat := toNat32 _
166 have hEb64 : (e.LCA.getD k default).bits.toUInt32.toUInt64.toNat = (e.LCA.getD k default).bits.toNat := by simp [toNat32]
167 have hls1 := hls.dropL (e.LCA.getD k default).bits.toUInt32 (by omega) (by omega)
168 have origin1 := drop_origin (e.LCA.getD k default).bits.toUInt32 hls origin (by omega)
169 rw [dolen_eq_len]
170 dsimp only
171 refine Wp.bindO hld ?_
172 refine Wp.bindO (shr64_ok (x := l.hold) (by omega)) ?_
173 refine Wp.bindO hld ?_
174 generalize e.LCA.getD k default = E at *
175 by_cases hz : (E.op.toUInt32 == 0) = true
176 · simp only [hz, ite_true]
177 refine Wp.bindO hld ?_
178 have hst : store8 l.out E.val.toUInt8 (e.heap A msg m) =
179 .ok ((), e.heap (A.set! o E.val.toUInt8) msg m) := by
180 rw [hls.hout, ← e.heap_put A (A.set! o E.val.toUInt8) msg m]
181 exact Ptr.store_ok (e.heap_bytes_ob A msg m) (e.heap_ro_ob A msg m) (by omega)
182 refine Wp.bindE hst ?_
183 refine Wp.bindO (x := Ptr.ref (BRef.blk e.ob) (o + 1)) ?_ ?_
184 · rw [hls.hout]
185 exact Ptr.add_nat_ok (e.heap_bytes_ob _ msg m) (by simp; omega)
186 · refine Wp.pure' ⟨Or.inr ?_, ?_⟩
187 · refine ⟨i, o + 1, A.set! o E.val.toUInt8, msg, m, ?_, hsi, by omega, by omega, by omega,
188 by simp, rfl, rfl, ?_, ?_, ?_⟩
189 · exact ⟨hls.hin, rfl, hls.hi0, hls.hi1, by have := hls.ho0; omega, hls1.hb, hls1.hH, hls1.hacc⟩
190 · intro j hj
191 have hne : o ≠ j := by omega
192 simp [Array.set!, hne]
193 · intro _; exact ⟨by omega, rfl, rfl⟩
194 · intro h; simp [hbroke] at h
195 · refine ⟨i, o + 1, used + E.bits.toUInt32.toNat, ?_, origin1, by omega⟩
196 exact ⟨hls.hin, rfl, hls.hi0, hls.hi1, by have := hls.ho0; omega, hls1.hb, hls1.hH, hls1.hacc⟩
197 · have hz' : E.op ≠ 0 := by rw [mask0] at hz; simpa using hz
198 by_cases hb16 : (E.op.toUInt32 &&& 16 != 0) = true
199 · simp only [hz, hb16, ite_true, ite_false, Bool.false_eq_true]
200 have hb16' : E.op &&& 16 ≠ 0 := by rw [mask16] at hb16; simpa using hb16
201 have hbase : (E.op &&& 15).toNat ≤ 5 ∧ 3 ≤ E.val.toNat ∧
202 E.val.toNat + 2 ^ (E.op &&& 15).toNat ≤ 259 := by
203 rcases hcl with h | h
204 · exact False.elim (hb16' h.1.2.1)
205 · rcases h.2 with h0 | h | h
206 · exact False.elim (hz' h0)
207 · exact h.2
208 · exact False.elim (hb16' h.1)
209 refine Wp.bindO hld ?_
210 let stage : L :=
211 { in_ := l.in_, out := l.out, hold := l.hold >>> E.bits.toUInt32.toUInt64, bits := l.bits - E.bits.toUInt32,
212 here := l.here, op := E.op.toUInt32 &&& 15, len := E.val.toUInt32, dist := l.dist, from_ := l.from_,
213 broke := l.broke, againL := false, againD := l.againD }
214 have stageLocals : LS e stage i o := LS.congr hls1 rfl rfl rfl rfl
215 have stageOrigin : Origin.Inv e stage.hold.toNat stage.bits.toNat i (used + E.bits.toUInt32.toNat) := origin1
216 have stageExtra : stage.op.toNat ≤ 5 := by dsimp [stage]; rw [mask15]; exact hbase.1
217 have stageLength : 3 ≤ stage.len.toNat ∧ stage.len.toNat + 2 ^ stage.op.toNat ≤ 259 := by
218 simpa [stage, mask15] using hbase.2
219 have stageBits : i = s + 2 → 1 ≤ stage.bits.toNat := by
220 intro hi
221 have := hbi2 hi
222 dsimp [stage]
223 rw [u32_toNat_sub (by omega), hEbn]
224 omega
225 obtain ⟨l', h', run, outOrigin⟩ := len_origin_wp hc A msg m stage i o s (used + E.bits.toUInt32.toNat)
226 stageLocals hA ho hAb hbroke stageExtra stageLength hs6 hT stageBits stageOrigin
227 have step := Wp.at_run (dolenLen_step_wp hc A msg m stage i o s stageLocals hAsz ho
228 hbroke rfl stageExtra stageLength hs6 hsi hT stageBits) run
229 refine Wp.of_eq run ⟨Or.inr step, ?_⟩
230 obtain ⟨i', o', used', locals', origin', mono⟩ := outOrigin
231 exact ⟨i', o', used', locals', origin', by omega⟩
232 · have hb16' : E.op &&& 16 = 0 := by rw [mask16] at hb16; simpa using hb16
233 by_cases hb64 : (E.op.toUInt32 &&& 64 == 0) = true
234 · simp only [hz, hb16, hb64, ite_true, ite_false, Bool.false_eq_true]
235 have hb64' : E.op &&& 64 = 0 := by rw [mask64] at hb64; simpa using hb64
236 have hl : LenLink E := ⟨hz', hb16', hb64'⟩
237 have hlk : LinkOK LenLeaf e.LCA e.ol E := by
238 rcases hcl with h | h
239 · exact h.2
240 · rcases h.2 with h0 | h | h
241 · exact False.elim (hz' h0)
242 · exact False.elim (h.1 hb16')
243 · exact False.elim (h.2 hb64')
244 refine Wp.bindO hld ?_
245 have hlc : c.lcode = .ref e.rl e.ol := by rw [hc.lcode]; exact e.hlc
246 have hop32 : E.op.toUInt32.toNat < 32 := by rw [toNat32]; have := hlk.2.2.1; omega
247 refine Wp.bindO (x := Ptr.ref e.rl (e.ol + E.val.toNat)) ?_ ?_
248 · rw [hlc]
249 exact Ptr.add_nat_ok (h := e.heap A msg m) (r := e.rl) (a := e.LCA) (off := e.ol)
250 (n := E.val.toNat) (e.heap_cget_LCA A msg m)
251 (Nat.le_trans (Nat.le_add_right _ _) hlk.2.2.2.1)
252 refine Wp.bindO (shl32_ok hop32) ?_
253 have hlow := hold_low64 (x := l.hold >>> E.bits.toUInt32.toUInt64) (k := E.op.toUInt32) hop32
254 have hjlt : (l.hold >>> E.bits.toUInt32.toUInt64).toNat % 2 ^ E.op.toUInt32.toNat < 2 ^ E.op.toNat := by
255 rw [toNat32]; exact Nat.mod_lt _ (Nat.pow_pos (by omega))
256 generalize hjd : (l.hold >>> E.bits.toUInt32.toUInt64).toNat % 2 ^ E.op.toUInt32.toNat = j at hlow hjlt
257 refine Wp.bindO (x := Ptr.ref e.rl (e.ol + E.val.toNat + j)) ?_ ?_
258 · rw [hlow]
259 exact Ptr.add_nat_ok (h := e.heap A msg m) (r := e.rl) (a := e.LCA) (off := e.ol + E.val.toNat)
260 (n := j) (e.heap_cget_LCA A msg m) (by have := hlk.2.2.2.1; omega)
261 refine Wp.pure' ⟨Or.inl ⟨rfl, hbroke, rfl, hl, j, hjlt, rfl,
262 LS.congr hls1 rfl rfl rfl rfl, ?_⟩,
263 i, o, used + E.bits.toUInt32.toNat, LS.congr hls1 rfl rfl rfl rfl, origin1, by omega⟩
264 rw [u32_toNat_sub (by omega), hEbn]
265 · simp only [hz, hb16, hb64, ite_false, Bool.false_eq_true]
266 by_cases hb32 : (E.op.toUInt32 &&& 32 != 0) = true
267 · simp only [hb32, ite_true]
268 refine Wp.bindE (e.heap_ldstate hc A msg m) ?_
269 refine Wp.bindE (e.heap_stmode hc A msg m TYPE _ rfl) ?_
270 refine Wp.pure' ⟨Or.inr ?_, i, o, used + E.bits.toUInt32.toNat,
271 LS.congr hls1 rfl rfl rfl rfl, origin1, by omega⟩
272 refine ⟨i, o, A, msg, TYPE, LS.congr hls1 rfl rfl rfl rfl, hsi, by omega, by omega, by omega,
273 rfl, rfl, rfl, (fun _ _ => rfl), ?_, (fun _ => Or.inl rfl)⟩
274 intro h; cases h
275 · simp only [hb32, ite_false, Bool.false_eq_true]
276 obtain ⟨ip, hip⟩ := badData_run hc A msg m "invalid literal/length code" (by decide +kernel)
277 refine Wp.bindE hip ?_
278 refine Wp.pure' ⟨Or.inr ?_, i, o, used + E.bits.toUInt32.toNat, LS.congr hls1 rfl rfl rfl rfl, origin1, by omega⟩
279 refine ⟨i, o, A, .ref (BRef.str ip) 0, BAD, LS.congr hls1 rfl rfl rfl rfl, hsi, by omega, by omega, by omega,
280 rfl, rfl, rfl, (fun _ _ => rfl), ?_, (fun _ => Or.inr rfl)⟩
281 intro h; cases h
282
283/-- The actual `dolen` root/link loop ends after at most two passes. -/
284private theorem loop_origin_wp (hc : CtxOK e c) (A : Array UInt8) (msg : BPtr) (m : UInt32)
285 (l : L) (i o s kidx used : Nat) (hls : LS e l i o) (hAsz : A.size = e.A0.size)
286 (ho : o + 258 ≤ e.o0 + e.sm0.avail_out.toNat) (hbroke : l.broke = false)
287 (hs6 : s + 6 ≤ e.i0 + e.sm0.avail_in.toNat) (hsi : s ≤ i) (hT : i ≤ s + 2)
288 (hb15 : 15 ≤ l.bits.toNat) (hbi2 : i = s + 2 → 16 ≤ l.bits.toNat)
289 (hk : kidx < 2 ^ e.s0.lenbits.toNat) (hhere : l.here = .ref e.rl (e.ol + kidx))
290 (origin : Origin.Inv e l.hold.toNat l.bits.toNat i used) :
291 Wp (cdoWhile (dolen c) (fun l => pure (l.againL, l)) l) (e.heap A msg m)
292 (fun l' h' => StepPost e A msg m s o l' h' ∧
293 ∃ i' o' used', LS e l' i' o' ∧ Origin.Inv e l'.hold.toNat l'.bits.toNat i' used' ∧ used ≤ used') := by
294 have hts := e.hlt
295 obtain ⟨hR, hsz, hall⟩ := hts
296 have hksz : e.ol + kidx < e.LCA.size := by omega
297 have hclass : (LenLink (e.LCA.getD (e.ol + kidx) default) ∧
298 LinkOK LenLeaf e.LCA e.ol (e.LCA.getD (e.ol + kidx) default)) ∨
299 LenLeaf 0 (e.LCA.getD (e.ol + kidx) default) := by
300 have hh := hall kidx hk
301 by_cases hl : LenLink (e.LCA.getD (e.ol + kidx) default)
302 · rw [ite_eq_left hl] at hh; exact Or.inl ⟨hl, hh⟩
303 · rw [ite_eq_right hl] at hh; exact Or.inr hh
304 have hEd0 : (e.LCA.getD (e.ol + kidx) default).bits.toNat + 0 ≤ 15 := by
305 rcases hclass with h | h
306 · exact h.2.1
307 · exact h.1
308 obtain ⟨l1, h1, e1, hq1, origin1⟩ := pass_origin_wp hc A msg m l i o s 0 (e.ol + kidx) used hls hAsz ho hbroke
309 hs6 hsi hT (by omega) (by intro hi; have := hbi2 hi; omega) hhere hksz (by omega) hEd0 hclass origin
310 generalize hE0 : e.LCA.getD (e.ol + kidx) default = E0 at hq1 hclass hEd0
311 rcases hq1 with ⟨hag, hbr, hh, hlink, j, hjlt, hhere1, hls1, hb1⟩ | hend
312 · subst hh
313 obtain ⟨i1, o1, used1, locals1, O1, mono1⟩ := origin1
314 have i1eq : i1 = i := (Ptr.ref.inj (locals1.hin.symm.trans hls1.hin)).2
315 have o1eq : o1 = o := (Ptr.ref.inj (locals1.hout.symm.trans hls1.hout)).2
316 subst i1 o1
317 have hlk : LinkOK LenLeaf e.LCA e.ol E0 := by
318 rcases hclass with h | h
319 · exact h.2
320 · rcases h.2 with h0 | h | h
321 · exact False.elim (hlink.1 h0)
322 · exact False.elim (h.1 hlink.2.1)
323 · exact False.elim (h.2 hlink.2.2)
324 have hleaf := hlk.2.2.2.2 j hjlt
325 have hk2 : e.ol + E0.val.toNat + j < e.LCA.size := by have := hlk.2.2.2.1; omega
326 obtain ⟨l2, h2, e2, hq2, origin2⟩ := pass_origin_wp hc A msg m l1 i o s E0.bits.toNat (e.ol + E0.val.toNat + j) used1
327 hls1 hAsz ho hbr hs6 hsi hT (by omega) (by intro hi; have := hbi2 hi; omega)
328 hhere1 hk2 (by have := hleaf.1; omega) hleaf.1 (Or.inr hleaf) O1
329 rcases hq2 with ⟨_, _, _, hl2, _⟩ | hend2
330 · rcases hleaf.2 with h0 | h | h
331 · exact False.elim (hl2.1 h0)
332 · exact False.elim (h.1 hl2.2.1)
333 · exact False.elim (h.2 hl2.2.2)
334 · have c1 : (fun l : L => (pure (l.againL, l) : M (Bool × L))) l1 (e.heap A msg m) =
335 .ok ((true, l1), e.heap A msg m) := by simp [hag]
336 have c2 : (fun l : L => (pure (l.againL, l) : M (Bool × L))) l2 h2 =
337 .ok ((false, l2), h2) := by simp [StepPost.againL hend2]
338 refine Wp.of_eq (cdoWhile_two e1 c1 e2 c2) ⟨hend2, ?_⟩
339 obtain ⟨i2, o2, used2, locals2, O2, mono2⟩ := origin2
340 exact ⟨i2, o2, used2, locals2, O2, by omega⟩
341 · have c1 : (fun l : L => (pure (l.againL, l) : M (Bool × L))) l1 h1 =
342 .ok ((false, l1), h1) := by simp [StepPost.againL hend]
343 exact Wp.of_eq (cdoWhile_one e1 c1) ⟨hend, origin1⟩
344
345
346/-- Root-table lookup followed by the actual length root/link loop. -/
347private theorem root_origin_wp (hc : CtxOK e c) (A : Array UInt8) (msg : BPtr) (m : UInt32)
348 (l : L) (i o s used : Nat) (hls : LS e l i o) (hAsz : A.size = e.A0.size)
349 (ho : o + 258 ≤ e.o0 + e.sm0.avail_out.toNat) (hbroke : l.broke = false)
350 (hs6 : s + 6 ≤ e.i0 + e.sm0.avail_in.toNat) (hsi : s ≤ i) (hT : i ≤ s + 2)
351 (hb15 : 15 ≤ l.bits.toNat) (hbi2 : i = s + 2 → 16 ≤ l.bits.toNat)
352 (origin : Origin.Inv e l.hold.toNat l.bits.toNat i used) :
353 Wp (do
354 let here ← c.lcode.add (l.hold &&& c.lmask.toUInt64).toNat
355 cdoWhile (dolen c) (fun l => pure (l.againL, l)) {l with here})
356 (e.heap A msg m) (fun l' h' => StepPost e A msg m s o l' h' ∧
357 ∃ i' o' used', LS e l' i' o' ∧ Origin.Inv e l'.hold.toNat l'.bits.toNat i' used' ∧ used ≤ used') := by
358 have hlc : c.lcode = .ref e.rl e.ol := by rw [hc.lcode]; exact e.hlc
359 have hR : e.s0.lenbits.toNat < 32 := by have := e.hlt.1; omega
360 have hmask : c.lmask.toUInt64.toNat = 2 ^ e.s0.lenbits.toNat - 1 := by
361 rw [hc.lmask, UInt32.toNat_toUInt64]; exact u32_shl1_sub1 hR
362 have hidx := u64_and_mask (x := l.hold) hmask
363 have hmod : l.hold.toNat % 2 ^ e.s0.lenbits.toNat < 2 ^ e.s0.lenbits.toNat :=
364 Nat.mod_lt _ (Nat.pow_pos (by omega))
365 refine Wp.bindO (x := Ptr.ref e.rl (e.ol + l.hold.toNat % 2 ^ e.s0.lenbits.toNat)) ?_ ?_
366 · rw [hlc, hidx]
367 exact Ptr.add_nat_ok (e.heap_cget_LCA A msg m) (by have := e.hlt.2.1; omega)
368 · exact loop_origin_wp hc A msg m _ i o s _ used (LS.congr hls rfl rfl rfl rfl) hAsz ho hbroke
369 hs6 hsi hT hb15 hbi2 hmod rfl origin
370
371
372/-- Every source path retains the original body postcondition and an exact
373source suffix; accepted table-symbol semantics are a separate obligation. -/
374theorem actual_body_preserves_origin : BodyOrigin.Goal.actual_body_preserves_origin := by
375 intro e c A msg m l i o used hp origin
376 rcases hp with ⟨hc, hls, hAsz, hi6, ho258, hbroke⟩
377 change Wp (inflate_fast_body c l) (e.heap A msg m) (fun l' h' => StepPost e A msg m i o l' h' ∧
378 ∃ i' o' used', LS e l' i' o' ∧ Origin.Inv e l'.hold.toNat l'.bits.toNat i' used' ∧ used ≤ used')
379 unfold inflate_fast_body
380 by_cases h1 : l.bits < 15
381 · simp only [h1, ite_true]
382 have hb : l.bits.toNat < 15 := by simpa using UInt32.lt_iff_toNat_lt.mp h1
383 have hiin : i < e.i0 + e.sm0.avail_in.toNat := by omega
384 refine Wp.bindO (pull_run e _ l i o hls (by omega) hiin (e.heap_bytes_in A msg m)) ?_
385 have hl1 := hls.pullL (by omega) hiin
386 have origin1 := pull_origin hls origin (by omega) hiin
387 have hb1 := pullL_bits l (e.IN.getD i 0) (.ref (BRef.blk e.ib) (i + 1)) hls.hb
388 have hi2 : i + 1 < e.i0 + e.sm0.avail_in.toNat := by omega
389 have hb1' : (pullL l (e.IN.getD i 0) (.ref (BRef.blk e.ib) (i + 1))).bits.toNat ≤ 22 := by
390 simp only [pullL] at hb1 ⊢; omega
391 refine Wp.bindO (pull_run e _ _ (i + 1) o hl1 hb1' hi2 (e.heap_bytes_in A msg m)) ?_
392 have hl2 := hl1.pullL hb1' hi2
393 have origin2 := pull_origin hl1 origin1 hb1' hi2
394 have hb2 := pullL_bits (pullL l (e.IN.getD i 0) (.ref (BRef.blk e.ib) (i + 1)))
395 (e.IN.getD (i + 1) 0) (.ref (BRef.blk e.ib) (i + 1 + 1)) hl1.hb
396 exact root_origin_wp hc A msg m _ (i + 1 + 1) o i used hl2 hAsz ho258 hbroke hi6 (by omega) (by omega)
397 (by simp only [pullL] at hb1 hb2 ⊢; omega)
398 (by intro _; simp only [pullL] at hb1 hb2 ⊢; omega) origin2
399 · simp only [h1, ite_false]
400 have hb : 15 ≤ l.bits.toNat := by
401 have : ¬ l.bits.toNat < 15 := fun h => h1 (UInt32.lt_iff_toNat_lt.mpr (by simpa using h))
402 omega
403 exact root_origin_wp hc A msg m l i o i used hls hAsz ho258 hbroke hi6 (by omega) (by omega) hb (by omega) origin
404
405end Zlib.Inffast.Proofs.BodyOriginProof
406
407namespace Zlib.Inffast.Proofs
408open Zlib.Inffast.Spec
409/-- The entire actual body retains the exact entry-stream origin on every exit. -/
410theorem actual_body_preserves_origin : BodyOrigin.Goal.actual_body_preserves_origin :=
411 BodyOriginProof.actual_body_preserves_origin
412end Zlib.Inffast.Proofs