REFERENCE / ZLIB × LEAN
public-infback-init.lean
Source snapshot ·
1803e20232f0a2b4 · Source at the matching commit ↗Lean source with line numbers. Follow a line number to locate a statement, or an import to read its dependency.
1import ZlibF.Spec.Public.Domains
2import ZlibF.Proof.«infback.c.end»
3
4open C Zlib.Inflate Zlib.Inflate.Spec Zlib.Inflate.Proofs Zlib.Infback Zlib.Infback.Spec Zlib.Infback.Proofs ZlibF.Spec.Public
5
6namespace ZlibF.Spec.Public.InflateBackInitProof
7
8theorem version_value_read {h : Heap} {v : BPtr} {byte : UInt8} (hv : VersionValue h v (some byte)) :
9 v ≠ .null ∧ OkOn h (index8 v 0) byte := by
10 rcases hv with ⟨_,h⟩ | ⟨b, hb, hbytes⟩
11 · cases h
12 · cases hb
13 rcases hbytes with ⟨_,hn,_⟩ | ⟨ref,off,a,rfl,hget,hfit,hlist⟩
14 · cases hn
15 · refine ⟨by simp, ?_⟩
16 have ha : off < a.size := by omega
17 have he : a[off]? = some byte := by
18 have hh := congrArg (fun l : List UInt8 => l[0]?) hlist
19 simpa [List.getElem?_take, List.getElem?_drop] using hh.symm
20 have hbyte : a[off] = byte := by
21 have := Array.getElem?_eq_getElem ha
22 rw [this] at he
23 exact Option.some.inj he
24 have hr := Ptr.index_ok (h := h) (r := ref) (a := a) (off := off) (i := 0) hget (by omega)
25 simpa [hbyte] using hr
26
27theorem init_refusals :
28 (∀ h p wb window version head size, VersionValue h version head →
29 (head ≠ some 49 ∨ size ≠ 112) →
30 C.run (inflateBackInit_ p wb window version size) h = .ok (Z_VERSION_ERROR, h)) ∧
31 (∀ h p wb window version, VersionValue h version (some 49) →
32 (p = none ∨ window = .null ∨ wb.toInt < 8 ∨ 15 < wb.toInt) →
33 C.run (inflateBackInit_ p wb window version 112) h = .ok (Z_STREAM_ERROR, h)) := by
34 constructor
35 · intro h p wb window version head size hv hbad
36 cases head with
37 | none =>
38 rcases hv with ⟨rfl,_⟩ | ⟨b,hb,_⟩
39 · exact inflateBackInit__version_null p wb window size h
40 · cases hb
41 | some b =>
42 obtain ⟨hn,hr⟩ := version_value_read hv
43 by_cases hb : b = 49
44 · subst b
45 have hs : size ≠ 112 := by simpa using hbad
46 exact inflateBackInit__version_size p wb window version size h hn hr hs
47 · exact inflateBackInit__version_char p wb window version size h b hn hr hb
48 · intro h p wb window version hv hbad
49 obtain ⟨hn,hr⟩ := version_value_read hv
50 have hbad' : p = none ∨ window = .null ∨ wb < 8 ∨ wb > 15 := by
51 rcases hbad with h | h | h | h
52 · exact Or.inl h
53 · exact Or.inr (Or.inl h)
54 · exact Or.inr (Or.inr (Or.inl (Int32.lt_iff_toInt_lt.mpr (by simpa using h))))
55 · exact Or.inr (Or.inr (Or.inr (Int32.lt_iff_toInt_lt.mpr (by simpa using h))))
56 exact inflateBackInit__stream_error p wb window version h hn hr hbad'
57
58theorem back_init_success_valid {h : Heap} {r : ZStreamRef} {z : ZStream} {wb : Int32} {window : BPtr}
59 (hF : Fresh h) (hU : Uniq h) (hglob : LibraryGlobals h) (hz : r.get h = some z)
60 (hza : z.zalloc = .null ∨ z.zalloc = .fn "zcalloc") (hzf : z.zfree = .null ∨ z.zfree = .fn "zcfree")
61 (h8 : ¬ wb < 8) (h15 : ¬ wb > 15) (hwin : window ≠ .null)
62 (hw : Writable h window (2 ^ wb.toInt.toNat)) :
63 BackValid (backOkHeap h r z window wb) r h.nextBlk
64 (initStream2 z h.nextBlk) (backState (h.garbage h.nalloc) window wb) := by
65 have hr := i2u_range h8 h15
66 have hwb : (i2u wb).toNat = wb.toInt.toNat := by
67 unfold i2u
68 rw [Int32.toNat_toUInt32_of_le]
69 · rfl
70 · rw [Int32.le_iff_toInt_le]
71 have hnot : ¬ wb.toInt < 8 := fun he => h8 (Int32.lt_iff_toInt_lt.mpr (by simpa using he))
72 simp only [Int32.toInt_zero]
73 omega
74 have ⟨hu,hf⟩ := backOk_shape hz hF window wb hU
75 refine ⟨?_,?_,?_,?_,?_,wf_backState _ _ _,?_,?_,?_,?_,?_,hf,hu,?_⟩
76 · simp [backOkHeap, hz]
77 · simp [backOkHeap]
78 · simp [initStream2]
79 · rcases hza with e | e <;> simp [initStream2, initStream, e]
80 · rcases hzf with e | e <;> simp [initStream2, initStream, e]
81 · simpa [backState, i2u] using hr.1
82 · simpa [backState, i2u] using hr.2
83 · simp only [backState]
84 exact shl32_one hr.2
85 · simpa [backState] using hwin
86 · rcases hw with ⟨hn,_⟩ | ⟨ref,off,a,hptr,hget,hro,hfit⟩
87 · exact (hwin hn).elim
88 · right
89 refine ⟨ref,off,a,hptr,?_,?_,?_⟩
90 · cases ref <;> simp_all [Space.get, backOkHeap, allocIstHeap]
91 · cases ref <;> simp_all [Space.ro, backOkHeap, allocIstHeap]
92 · simpa [backState, shl32_one hr.2, hwb] using hfit
93 · simpa [LibraryGlobals, backOkHeap, allocIstHeap] using hglob
94
95#print axioms back_init_success_valid
96
97theorem back_init_frame {h : Heap} {r : ZStreamRef} {z : ZStream} {window : BPtr} {wb : Int32}
98 (hz : r.get h = some z) (hF : Fresh h) :
99 Frame h (backOkHeap h r z window wb) (StreamRoot r) := by
100 cases r with
101 | tab k =>
102 have hk : h.streams k = some z := hz
103 simp only [Frame, backOkHeap, allocIstHeap, ZStreamRef.put, hk, upd_same, true_and]
104 refine ⟨by omega, by omega, ?_⟩
105 intro b hb hn
106 have hne : b ≠ h.nextBlk := fun he => hF b (by omega) hb
107 have hk : b ≠ k := fun he => hn (by simpa [StreamRoot] using he)
108 simp [upd_ne, hne, hk]
109 | in_gzstate_strm k =>
110 cases hg : h.gzstates k with
111 | none => simp [ZStreamRef.get, hg] at hz
112 | some g =>
113 simp only [Frame, backOkHeap, allocIstHeap, ZStreamRef.put, hg, upd_same, true_and]
114 refine ⟨by omega, by omega, ?_⟩
115 intro b hb hn
116 have hne : b ≠ h.nextBlk := fun he => hF b (by omega) hb
117 have hk : b ≠ k := fun he => hn (by simpa [StreamRoot] using he)
118 simp [upd_ne, hne, hk]
119
120theorem back_init_live {h : Heap} {r : ZStreamRef} {z : ZStream} {window : BPtr} {wb : Int32}
121 (hz : r.get h = some z) (hF : Fresh h) :
122 LiveChange h (backOkHeap h r z window wb) (fun b => b = h.nextBlk) (fun _ => False) := by
123 have hFp : Fresh (r.put h (initStream z)) := (shape_put hz _).fresh (by simp) hF
124 have hz0 : r.get (allocIstHeap (r.put h (initStream z)) (backState (h.garbage h.nalloc) window wb)) =
125 some (initStream z) := by simp [hz]
126 have ho : h.Owns (fun b => h.live b) := fun _ => Iff.rfl
127 have h1 := owns_allocIst hFp (backState (h.garbage h.nalloc) window wb) ((shape_put hz _).owns ho)
128 simp only [ZStreamRef.put_nextBlk] at h1
129 have h2 := (shape_put hz0 (initStream2 z h.nextBlk)).owns h1
130 intro b
131 simpa [LiveChange, backOkHeap] using h2 b
132
133/-- `int inflateBackInit_(z_streamp strm, int windowBits, unsigned char *window,
134The exact public result, state, frame and ownership contract. -/
135theorem back_init_public : Goal.inflateBackInit_ := by
136 obtain ⟨hversion, hstream⟩ := init_refusals
137 refine ⟨hversion, hstream, ?_⟩
138 intro h r z wb window version hF hU hglob hz halloc hv hlo hhi hwin hwrite
139 obtain ⟨hvn, hv0⟩ := version_value_read hv
140 have h8 : ¬ wb < 8 := by
141 intro hh
142 have hh' := Int32.lt_iff_toInt_lt.mp hh
143 simp at hh'
144 omega
145 have h15 : ¬ wb > 15 := by
146 intro hh
147 have hh' := Int32.lt_iff_toInt_lt.mp hh
148 simp at hh'
149 omega
150 obtain ⟨hza, hzf⟩ := halloc
151 by_cases hok : h.allocOk h.nalloc = true
152 · refine ⟨Z_OK, backOkHeap h r z window wb, ?_, ?_, ?_⟩
153 · exact inflateBackInit__success hz hF hok hza hzf hvn hv0 hwin h8 h15
154 · simp [backOkHeap, allocIstHeap]
155 · have hnot : h.allocOk h.nalloc ≠ false := by rw [hok]; decide
156 simp only [hnot]
157 refine ⟨trivial, ?_, back_init_frame hz hF, back_init_live hz hF⟩
158 simpa [preparedStream, initStream2, initStream, backInitialState, backState, i2u] using
159 (back_init_success_valid hF hU hglob hz hza hzf h8 h15 hwin hwrite)
160 · have hfail : h.allocOk h.nalloc = false := by
161 cases he : h.allocOk h.nalloc <;> simp_all
162 refine ⟨Z_MEM_ERROR, initMemHeap h r z, ?_, ?_, ?_⟩
163 · exact inflateBackInit__memfail hz hF hok hza hzf hvn hv0 hwin h8 h15
164 · simp [initMemHeap]
165 · simp only [hfail, ite_true]
166 refine ⟨trivial, ?_⟩
167 simp [SameObjects, initMemHeap, preparedStream, initStream]
168
169#print axioms back_init_public
170
171
172theorem public_witness_fresh : Fresh witnessHeap := by
173 intro b hb hl
174 have h1 : b ≠ 1 := by simp [witnessHeap] at hb; omega
175 have h2 : b ≠ 2 := by simp [witnessHeap] at hb; omega
176 have h0 : b ≠ 0 := by simp [witnessHeap] at hb; omega
177 simp [Heap.live, witnessHeap, Heap.empty, upd_ne _ _ _ _ h1, upd_ne _ _ _ _ h2, upd_ne _ _ _ _ h0] at hl
178
179theorem public_witness_uniq : Uniq witnessHeap := by
180 intro b
181 by_cases h1 : b = 1
182 · subst h1; simp [witnessHeap, Heap.empty, cnt]
183 by_cases h2 : b = 2
184 · subst h2; simp [witnessHeap, Heap.empty, cnt]
185 by_cases h0 : b = 0
186 · subst h0; simp [witnessHeap, Heap.empty, cnt]
187 simp [witnessHeap, Heap.empty, cnt, upd_ne _ _ _ _ h1, upd_ne _ _ _ _ h2, upd_ne _ _ _ _ h0]
188
189theorem public_witness_domain : InitDomain witnessHeap (.tab 0) (.ref (.blk 1) 0) := by
190 refine ⟨public_witness_fresh, public_witness_uniq, ?_, ?_, default, ?_, ?_, ?_⟩
191 · rfl
192 · right
193 refine ⟨49, rfl, ?_⟩
194 right
195 refine ⟨.blk 1, 0, #[49, 0], rfl, ?_, ?_, ?_⟩ <;> simp [witnessHeap, Space.get, Heap.empty]
196 · simp [ZStreamRef.get, witnessHeap]
197 · exact ⟨Or.inl rfl, Or.inl rfl⟩
198 · rfl
199
200theorem back_domain_general :
201 ∀ h r version wb window,
202 InitDomain h r version → 8 ≤ wb.toInt → wb.toInt ≤ 15 →
203 window ≠ .null → Writable h window (2 ^ wb.toInt.toNat) → h.allocOk h.nalloc = true →
204 ∃ after z s, C.run (inflateBackInit_ (some r) wb window version 112) h =
205 .ok (Z_OK, after) ∧ BackValid after r h.nextBlk z s ∧ s.window = window ∧
206 s.wbits = wb.toUInt32 ∧ Frame h after (StreamRoot r) ∧
207 LiveChange h after (fun b => b = h.nextBlk) (fun _ => False) := by
208 intro h r version wb window hd hlo hhi hn hw ha
209 obtain ⟨hf, hu, hg, hv, z, hz, hd, _⟩ := hd
210 obtain ⟨rc, after, hrun, _, hs⟩ := back_init_public.2.2 h r z wb window version hf hu hg hz hd hv hlo hhi hn hw
211 simp only [ha, Bool.true_eq_false, ite_false] at hs
212 obtain ⟨rfl, valid, frame, live⟩ := hs
213 exact ⟨after, _, _, hrun, valid, rfl, rfl, frame, live⟩
214
215#print axioms public_witness_domain
216#print axioms back_domain_general
217
218theorem public_witness_window {wb : Int32} (hhi : wb.toInt ≤ 15) :
219 Writable witnessHeap (.ref (.blk 2) 0) (2 ^ wb.toInt.toNat) := by
220 right
221 refine ⟨.blk 2, 0, Array.replicate 32768 0, rfl, ?_, ?_, ?_⟩
222 · simp [witnessHeap, Space.get, Heap.empty]
223 · simp [witnessHeap, Space.ro, Heap.empty]
224 · simp only [Nat.zero_add, Array.size_replicate]
225 have he : wb.toInt.toNat ≤ 15 := Int.toNat_le.mpr (by omega)
226 exact Nat.le_trans (Nat.pow_le_pow_right (by decide) he) (by decide)
227
228/-- `int inflateBackInit_(z_streamp strm, int windowBits, unsigned char *window,
229Initialization establishes the public representation domain. -/
230theorem back_init_domain_public : Goal.inflate_back_initialisation_domain := by
231 refine ⟨back_domain_general, public_witness_domain, ?_⟩
232 intro wb hlo hhi
233 obtain ⟨after, z, s, hr, hv, hw, _, _, _⟩ :=
234 back_domain_general witnessHeap (.tab 0) (.ref (.blk 1) 0) wb (.ref (.blk 2) 0)
235 public_witness_domain hlo hhi (by simp) (public_witness_window hhi) (by rfl)
236 exact ⟨after, z, s, hr, hv, hw⟩
237
238#print axioms back_init_domain_public
239
240
241theorem back_immediate_end {h : Heap} {r : ZStreamRef} {i : Nat} {z : ZStream} {s : InflateState}
242 (hv : BackValid h r i z s) :
243 C.run (inflateBackEnd (some r)) h = .ok (Z_OK, backEndHeap h r z i) := by
244 obtain ⟨hz, hs, hstate, _, hfree, _⟩ := hv
245 show inflateBackEnd (some r) h = _
246 unfold inflateBackEnd
247 have hz0 : z.zfree ≠ .null := by rw [hfree]; intro c; cases c
248 have hs0 : z.state ≠ none := by rw [hstate]; intro c; cases c
249 isimp [hz, hs0, hz0, hstate, hfree, zfrees_run hz hfree hs, backEndHeap]
250
251theorem back_end_window {h : Heap} {r : ZStreamRef} {i : Nat} {z : ZStream} {s : InflateState}
252 (hv : BackValid h r i z s) :
253 Writable (backEndHeap h r z i) s.window s.wsize.toNat := by
254 have hw := hv.2.2.2.2.2.2.2.2.2.2.1
255 rcases hw with ⟨hn, hl⟩ | ⟨ref, off, a, hp, hg, hr, hn⟩
256 · exact Or.inl ⟨hn,hl⟩
257 · right
258 refine ⟨ref, off, a, hp, ?_, ?_, hn⟩
259 · cases ref <;> simpa [backEndHeap, freeIst, Space.get] using hg
260 · cases ref <;> simp_all [backEndHeap, freeIst, Space.ro]
261
262#print axioms back_end_window
263
264theorem back_init_then_end {h : Heap} {r : ZStreamRef} {version : BPtr}
265 {wb : Int32} {window : BPtr}
266 (hd : InitDomain h r version) (hlo : 8 ≤ wb.toInt) (hhi : wb.toInt ≤ 15)
267 (hn : window ≠ .null) (hw : Writable h window (2 ^ wb.toInt.toNat))
268 (ha : h.allocOk h.nalloc = true) :
269 ∃ middle final z,
270 C.run (inflateBackInit_ (some r) wb window version 112) h = .ok (Z_OK, middle) ∧
271 C.run (inflateBackEnd (some r)) middle = .ok (Z_OK, final) ∧
272 r.get final = some z ∧ z.state = none ∧
273 Writable final window (2 ^ wb.toInt.toNat) ∧
274 (∀ b, final.live b ↔ h.live b) := by
275 obtain ⟨middle, z, s, hi, hv, hwin, hbits, _, hlive⟩ :=
276 back_domain_general h r version wb window hd hlo hhi hn hw ha
277 let final := backEndHeap middle r z h.nextBlk
278 have hrun := back_immediate_end hv
279 have hget : r.get final = some { z with state := none } := by
280 have hz := hv.1
281 simp [final, backEndHeap, hz]
282 have hwrite := back_end_window hv
283 have hnat : s.wsize.toNat = 2 ^ wb.toInt.toNat := by
284 have hsize := hv.2.2.2.2.2.2.2.2.1
285 rw [hbits] at hsize
286 have hwb : wb.toUInt32.toNat = wb.toInt.toNat := by
287 rw [Int32.toNat_toUInt32_of_le]
288 · rfl
289 · rw [Int32.le_iff_toInt_le]
290 simp only [Int32.toInt_zero]
291 omega
292 simpa [hwb] using hsize
293 refine ⟨middle, final, { z with state := none }, hi, hrun, hget, rfl, ?_, ?_⟩
294 · simpa [final, hwin, hnat] using hwrite
295 · have huniq := hv.2.2.2.2.2.2.2.2.2.2.2.2.1
296 have hs := hv.2.1
297 have hz := hv.1
298 have ho : middle.Owns (fun b => middle.live b) := fun _ => Iff.rfl
299 have hf := owns_freeIst huniq hs ho
300 have hz' : r.get (freeIst middle h.nextBlk) = some z := by simpa using hz
301 have hend := (shape_put hz' {z with state := none}).owns hf
302 intro b
303 have hbefore : ¬ h.live h.nextBlk := (hd.1) _ (Nat.le_refl _)
304 have hmid := hlive b
305 have he := hend b
306 simp only [not_false_eq_true, and_true] at hmid
307 constructor
308 · intro hh
309 have hparts := he.mp hh
310 rcases hmid.mp hparts.1 with old | new
311 · exact old
312 · exact (hparts.2 new).elim
313 · intro hh
314 apply he.mpr
315 refine ⟨hmid.mpr (Or.inl hh), ?_⟩
316 intro eq
317 subst b
318 exact hbefore hh
319
320#print axioms back_init_then_end
321
322end ZlibF.Spec.Public.InflateBackInitProof