Skip to content
REFERENCE / ZLIB × LEAN

deflate.c.init.failure.lean

Source snapshot · be9eff47189f8fd5 · 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.Proof.«deflate.c.init.frame»
2
3/-! # deflate.c: actual default allocation failure and cleanup heap -/
4
5namespace Zlib.Deflate.Proofs.DefaultInit
6open C Zlib.Deflate Zlib.Deflate.Spec ZlibF.Spec.Public
7set_option autoImplicit false
8
9def failureState (ph : Heap) (r : ZStreamRef) : DeflateState :=
10  { bufferState ph (baseState r) with status := FINISH_STATE }
11
12def failureStream (h : Heap) (z : ZStream) (m : BPtr) : ZStream :=
13  { stateStream z h.nextBlk with msg := m }
14
15def failureMsgHeap (h : Heap) (r : ZStreamRef) (z : ZStream) (m : BPtr) : Heap :=
16  let ph := publishedHeap h r z
17  r.put (setD (buffersHeap ph) h.nextBlk (failureState ph r)) (failureStream h z m)
18
19def failureHeap (h : Heap) (r : ZStreamRef) (z : ZStream) (m : BPtr) : Heap :=
20  endHeap (failureMsgHeap h r z m) r h.nextBlk (failureStream h z m)
21    (failureState (publishedHeap h r z) r)
22
23def clearDHeap (h : Heap) (ds : Nat) : Heap := { h with dstates := upd h.dstates ds none }
24
25theorem failure_heap_eq (h : Heap) (r : ZStreamRef) (z : ZStream) (m : BPtr) :
26    failureHeap h r z m = clearDHeap
27      (r.put (rollbackBuffers (publishedHeap h r z) (failureMsgHeap h r z m))
28        { failureStream h z m with state := none }) h.nextBlk := by
29  unfold failureHeap endHeap clearDHeap
30  rw [ZStreamRef.put_dstates, (rollback_stable _ _).dstates]
31  rfl
32
33theorem get_failure_raw {h : Heap} {r : ZStreamRef} {z : ZStream} (hz : r.get h = some z) :
34    r.get (setD (buffersHeap (publishedHeap h r z)) h.nextBlk
35      (failureState (publishedHeap h r z) r)) = some (stateStream z h.nextBlk) := by
36  simp [publishedHeap, ZStreamRef.get_put_same hz]
37
38theorem get_failure_message {h : Heap} {r : ZStreamRef} {z : ZStream} (hz : r.get h = some z) (m : BPtr) :
39    r.get (failureMsgHeap h r z m) = some (failureStream h z m) := by
40  exact ZStreamRef.get_put_same (get_failure_raw hz) _
41
42theorem memory_message (h : Heap) : ∃ m, ERR_MSG Z_MEM_ERROR h = .ok (m, h) := by
43  obtain ⟨i, hr, _⟩ := Zlib.Zutil.Proofs.strLit_run h
44    (Zlib.Zutil.Spec.errText Z_MEM_ERROR.toInt) (Zlib.Zutil.Proofs.errText_lit _)
45  refine ⟨.ref (.str i) 0, ?_⟩
46  unfold ERR_MSG
47  rw [Zlib.Zutil.Proofs.zError_eval]
48  exact hr
49
50/-- The actual failed-buffer branch sets FINISH_STATE, obtains the actual
51error literal and invokes cleanup on the partially constructed stream. -/
52theorem finish_failure {h : Heap} {r : ZStreamRef} {z : ZStream}
53    (hz : r.get h = some z) (hd : DefAlloc z) (level : Int32)
54    (bad : ((bufferPointers (publishedHeap h r z)).1 == .null ||
55      (bufferPointers (publishedHeap h r z)).2.1 == .null ||
56      (bufferPointers (publishedHeap h r z)).2.2.1 == .null ||
57      (bufferPointers (publishedHeap h r z)).2.2.2 == .null) = true) :
58    ∃ m, finish (some r) (some (.tab h.nextBlk)) level (bufferPointers (publishedHeap h r z))
59        (setD (buffersHeap (publishedHeap h r z)) h.nextBlk
60          (bufferState (publishedHeap h r z) (baseState r))) =
61      .ok (Z_MEM_ERROR, failureHeap h r z m) := by
62  let ph := publishedHeap h r z
63  let gf := setD (buffersHeap ph) h.nextBlk (failureState ph r)
64  obtain ⟨m, hm⟩ := memory_message gf
65  have hzF : r.get gf = some (stateStream z h.nextBlk) := get_failure_raw hz
66  have hzM := get_failure_message hz m
67  have hl : DLive (failureMsgHeap h r z m) r h.nextBlk (failureStream h z m) (failureState ph r) := by
68    refine ⟨hzM, ?_, rfl, rfl, ?_, ?_, ?_⟩
69    · simp [failureMsgHeap, ph]
70    · simp [failureState, GoodStatus]
71    · simpa [failureStream, stateStream] using (show z.zalloc ≠ .null by rw [hd.1]; decide)
72    · simpa [failureStream, stateStream] using (show z.zfree ≠ .null by rw [hd.2]; decide)
73  obtain ⟨hw, hp, hq, hb, hwb, hpq⟩ := buffers_freeable ph
74  have release := end_partial_run hl (by simpa [failureStream, stateStream] using hd.2)
75    (by simpa [FreeableB, failureMsgHeap, failureState, bufferState, bufferPointers] using hb)
76    (by simpa [FreeableB, failureMsgHeap, failureState, bufferState, bufferPointers] using hw)
77    (by simpa [FreeableW, failureMsgHeap, failureState, bufferState, bufferPointers] using hq)
78    (by simpa [FreeableW, failureMsgHeap, failureState, bufferState, bufferPointers] using hp)
79    (by simpa [failureState, bufferState, bufferPointers] using hwb)
80    (by simpa [failureState, bufferState, bufferPointers] using hpq)
81  refine ⟨m, ?_⟩
82  unfold finish
83  simp only []
84  rw [bad]
85  simp only [ite_true, bind_app, wrD_eq, setD_dstates_same, setD_setD]
86  change (do
87    let m ← ERR_MSG Z_MEM_ERROR
88    zwr (some r) (fun z => { z with msg := m })
89    let _ ← deflateEnd (some r)
90    pure Z_MEM_ERROR) gf = _
91  rw [bind_app, hm]
92  simp only [bind_app, zwr_eq, hzF]
93  change (do let _ ← deflateEnd (some r); pure Z_MEM_ERROR) (failureMsgHeap h r z m) = _
94  rw [bind_app, release]
95  rfl
96
97theorem slot_clearD_except (h : Heap) (ds x : Nat) (hn : x ≠ ds) :
98    SlotSame h (clearDHeap h ds) x := by
99  simp [SlotSame, clearDHeap, upd_ne _ _ _ _ hn]
100
101theorem failure_count (h : Heap) (r : ZStreamRef) (z : ZStream) (m : BPtr) :
102    (failureHeap h r z m).nalloc = h.nalloc + 5 := by
103  simp only [failure_heap_eq, clearDHeap, ZStreamRef.put_nalloc, rollback_nalloc,
104    failureMsgHeap, ZStreamRef.put_nalloc, setD_nalloc, buffers_nalloc,
105    publishedHeap, stateHeap, ZStreamRef.put_nalloc, Nat.add_assoc]
106
107theorem failure_next (h : Heap) (r : ZStreamRef) (z : ZStream) (m : BPtr) :
108    h.nextBlk ≤ (failureHeap h r z m).nextBlk := by
109  have hb := buffers_next (publishedHeap h r z)
110  have hn : (publishedHeap h r z).nextBlk = h.nextBlk + 1 := by simp [publishedHeap, stateHeap]
111  have he : (failureHeap h r z m).nextBlk = (buffersHeap (publishedHeap h r z)).nextBlk := by
112    simp only [failure_heap_eq, clearDHeap, ZStreamRef.put_nextBlk, rollback_next,
113      failureMsgHeap, setD_nextBlk]
114  omega
115
116/-- Failure keeps every old object outside the stream; permission changes
117at newly allocated then freed slots are outside the old-object frame. -/
118theorem failure_frame {h : Heap} (r : ZStreamRef) (z : ZStream) (m : BPtr) (hf : Fresh h) :
119    Frame h (failureHeap h r z m) (StreamRoot r) := by
120  let ph := publishedHeap h r z
121  let gm := failureMsgHeap h r z m
122  have sb := buffers_stable ph
123  have sr := rollback_stable ph gm
124  refine frame_of_old (g := failureHeap h r z m) r hf ?_ ?_ ?_
125    (failure_next h r z m) (by rw [failure_count]; omega) ?_
126  · rw [failure_heap_eq]
127    change h.static = (r.put (rollbackBuffers ph gm) { failureStream h z m with state := none }).static
128    rw [ZStreamRef.put_static, sr.static]
129    change h.static = (r.put (setD (buffersHeap ph) h.nextBlk (failureState ph r)) (failureStream h z m)).static
130    rw [ZStreamRef.put_static, setD_static, sb.static]
131    simp [ph, publishedHeap, stateHeap]
132  · rw [failure_heap_eq]
133    change h.allocOk = (r.put (rollbackBuffers ph gm) { failureStream h z m with state := none }).allocOk
134    rw [ZStreamRef.put_allocOk, sr.allocOk]
135    change h.allocOk = (r.put (setD (buffersHeap ph) h.nextBlk (failureState ph r)) (failureStream h z m)).allocOk
136    rw [ZStreamRef.put_allocOk, setD_allocOk, sb.allocOk]
137    simp [ph, publishedHeap, stateHeap]
138  · rw [failure_heap_eq]
139    change h.garbage = (r.put (rollbackBuffers ph gm) { failureStream h z m with state := none }).garbage
140    rw [ZStreamRef.put_garbage, sr.garbage]
141    change h.garbage = (r.put (setD (buffersHeap ph) h.nextBlk (failureState ph r)) (failureStream h z m)).garbage
142    rw [ZStreamRef.put_garbage, setD_garbage, sb.garbage]
143    simp [ph, publishedHeap, stateHeap]
144  · intro x hx hn
145    have hp : h.nextBlk < ph.nextBlk := by simp [ph, publishedHeap, stateHeap]
146    have hds : x ≠ h.nextBlk := by omega
147    have a : SlotSame h ph x :=
148      (slot_put_except h r (stateStream z h.nextBlk) x hn).trans
149        (slot_stateHeap_old _ (baseState r) x (by simpa using hx))
150    have b := a.trans (buffers_old ph x (by omega))
151    have c := b.trans (slot_setD_except _ h.nextBlk (failureState ph r) x hds)
152    have d : SlotSame h gm x := c.trans (slot_put_except _ r (failureStream h z m) x hn)
153    have e := d.trans (rollback_old ph gm x (by omega))
154    have f := e.trans (slot_put_except _ r { failureStream h z m with state := none } x hn)
155    rw [failure_heap_eq]
156    exact f.trans (slot_clearD_except _ h.nextBlk x hds)
157
158/-- Cleanup restores the existence of exactly the original objects.
159This is pointwise: internal table capacities may remain enlarged. -/
160theorem failure_shape {h : Heap} {r : ZStreamRef} {z : ZStream}
161    (hz : r.get h = some z) (hf : Fresh h) (m : BPtr) : Shape h (failureHeap h r z m) := by
162  let ph := publishedHeap h r z
163  let gf := setD (buffersHeap ph) h.nextBlk (failureState ph r)
164  let gm := failureMsgHeap h r z m
165  let gr := rollbackBuffers ph gm
166  let zc : ZStream := { failureStream h z m with state := none }
167  have hfp : Fresh ph := fresh_stateHeap ((shape_put hz (stateStream z h.nextBlk)).fresh (by simp) hf) _
168  have hzF : r.get gf = some (stateStream z h.nextBlk) := get_failure_raw hz
169  have hzM : r.get gm = some (failureStream h z m) := get_failure_message hz m
170  have hzR : r.get gr = some (failureStream h z m) := by simpa [gr] using hzM
171  have si := shape_put hz (stateStream z h.nextBlk)
172  have sm := shape_put hzF (failureStream h z m)
173  have se := shape_put hzR zc
174  have sb := buffers_stable ph
175  have sr := rollback_stable ph gm
176  have hd : h.dstates h.nextBlk = none := (Heap.not_live.mp (hf _ (Nat.le_refl _))).2.2.2.2.1
177  intro x
178  have arrays := rollback_arrays_at (g := gm) hfp x
179    (by simp [gm, failureMsgHeap, ph]) (by simp [gm, failureMsgHeap, ph])
180  have bytes : (failureHeap h r z m).bytes x = h.bytes x := by
181    rw [failure_heap_eq]
182    simpa [clearDHeap, ph, publishedHeap, stateHeap, gr] using arrays.1
183  have words : (failureHeap h r z m).words x = h.words x := by
184    rw [failure_heap_eq]
185    simpa [clearDHeap, ph, publishedHeap, stateHeap, gr] using arrays.2
186  have dstates : (failureHeap h r z m).dstates x = h.dstates x := by
187    rw [failure_heap_eq]
188    change upd (r.put gr zc).dstates h.nextBlk none x = h.dstates x
189    rw [ZStreamRef.put_dstates, sr.dstates]
190    change upd (r.put gf (failureStream h z m)).dstates h.nextBlk none x = h.dstates x
191    rw [ZStreamRef.put_dstates]
192    simp only [gf, setD, upd_upd, buffers_dstates]
193    simp only [ph, publishedHeap, stateHeap_dstates, ZStreamRef.put_dstates,
194      ZStreamRef.put_nextBlk, upd_upd, upd_apply]
195    by_cases hx : x = h.nextBlk <;> simp [hx, hd]
196  refine ⟨congrArg Option.isSome bytes, congrArg Option.isSome words, ?_, ?_,
197    congrArg Option.isSome dstates, ?_, ?_⟩
198  · rw [failure_heap_eq]
199    change ((r.put gr zc).streams x).isSome = (h.streams x).isSome
200    rw [(se x).2.2.1, sr.streams]
201    change ((r.put gf (failureStream h z m)).streams x).isSome = _
202    rw [(sm x).2.2.1]
203    change ((buffersHeap ph).streams x).isSome = _
204    rw [sb.streams]
205    simpa [ph, publishedHeap, stateHeap] using (si x).2.2.1
206  · rw [failure_heap_eq]
207    change ((r.put gr zc).gzheaders x).isSome = _
208    rw [ZStreamRef.put_gzheaders, sr.gzheaders]
209    change ((r.put gf (failureStream h z m)).gzheaders x).isSome = _
210    rw [ZStreamRef.put_gzheaders]
211    change ((buffersHeap ph).gzheaders x).isSome = _
212    rw [sb.gzheaders]
213    simp [ph, publishedHeap, stateHeap]
214  · rw [failure_heap_eq]
215    change ((r.put gr zc).istates x).isSome = _
216    rw [ZStreamRef.put_istates, sr.istates]
217    change ((r.put gf (failureStream h z m)).istates x).isSome = _
218    rw [ZStreamRef.put_istates]
219    change ((buffersHeap ph).istates x).isSome = _
220    rw [sb.istates]
221    simp [ph, publishedHeap, stateHeap]
222  · rw [failure_heap_eq]
223    change ((r.put gr zc).gzstates x).isSome = (h.gzstates x).isSome
224    rw [(se x).2.2.2.2.2.2, sr.gzstates]
225    change ((r.put gf (failureStream h z m)).gzstates x).isSome = _
226    rw [(sm x).2.2.2.2.2.2]
227    change ((buffersHeap ph).gzstates x).isSome = _
228    rw [sb.gzstates]
229    simpa [ph, publishedHeap, stateHeap] using (si x).2.2.2.2.2.2
230
231theorem failure_stream_cleared {h : Heap} {r : ZStreamRef} {z : ZStream}
232    (hz : r.get h = some z) (m : BPtr) :
233    r.get (failureHeap h r z m) = some { failureStream h z m with state := none } := by
234  rw [failure_heap_eq]
235  simp only [clearDHeap, ZStreamRef.get_dstates]
236  exact ZStreamRef.get_put_same (by simpa using get_failure_message hz m) _
237
238end Zlib.Deflate.Proofs.DefaultInit
ZLIB × LEAN

Global contents

READING NOWdeflate.c.init.failure.lean