Skip to content
REFERENCE / ZLIB × LEAN

deflate.c.life.end.lean

Source snapshot · 8e557e36664bf503 · 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.base»
2
3/-!
4# deflate.c: `deflateEnd`
5
6`deflateEnd` frees the four buffers (`pending_buf`, `head`, `prev`, `window`, in this order) and the state, clears
7`strm->state`, and returns `Z_DATA_ERROR` if the stream was in the middle of a block (`BUSY_STATE`) and `Z_OK` otherwise.
8-/
9
10namespace Zlib.Deflate.Spec
11open C
12
13/-- The heap after `free(p)` of a byte pointer that is `NULL` or the start of a block. -/
14def freeBytes (h : Heap) (p : BPtr) : Heap :=
15  match p with
16  | .ref (.blk w) 0 => { h with bytes := upd h.bytes w none }
17  | _ => h
18
19/-- The heap after `free(p)` of a pointer to words that is `NULL` or the start of a block. -/
20def freeWords (h : Heap) (p : WPtr) : Heap :=
21  match p with
22  | .ref (.blk w) 0 => { h with words := upd h.words w none }
23  | _ => h
24
25/-- The heap after `deflateEnd` of the stream `r` (record `z`) whose state is the record `d` at block `ds`: the four
26buffers and the state record are gone, and the stream record has `state = NULL`. -/
27def endHeap (h : Heap) (r : ZStreamRef) (ds : Nat) (z : ZStream) (d : DeflateState) : Heap :=
28  { r.put (freeBytes (freeWords (freeWords (freeBytes h d.pending_buf) d.head) d.prev) d.window) { z with state := none }
29    with dstates := upd h.dstates ds none }
30
31end Zlib.Deflate.Spec
32
33namespace Zlib.Deflate.Proofs
34open C Zlib.Deflate Zlib.Deflate.Spec
35
36@[simp] theorem freeBytes_dstates (h : Heap) (p : BPtr) : (freeBytes h p).dstates = h.dstates := by
37  unfold freeBytes; split <;> rfl
38@[simp] theorem freeBytes_streams (h : Heap) (p : BPtr) : (freeBytes h p).streams = h.streams := by
39  unfold freeBytes; split <;> rfl
40@[simp] theorem freeBytes_gzstates (h : Heap) (p : BPtr) : (freeBytes h p).gzstates = h.gzstates := by
41  unfold freeBytes; split <;> rfl
42@[simp] theorem freeBytes_words (h : Heap) (p : BPtr) : (freeBytes h p).words = h.words := by
43  unfold freeBytes; split <;> rfl
44@[simp] theorem freeBytes_nextBlk (h : Heap) (p : BPtr) : (freeBytes h p).nextBlk = h.nextBlk := by
45  unfold freeBytes; split <;> rfl
46@[simp] theorem freeWords_dstates (h : Heap) (p : WPtr) : (freeWords h p).dstates = h.dstates := by
47  unfold freeWords; split <;> rfl
48@[simp] theorem freeWords_streams (h : Heap) (p : WPtr) : (freeWords h p).streams = h.streams := by
49  unfold freeWords; split <;> rfl
50@[simp] theorem freeWords_gzstates (h : Heap) (p : WPtr) : (freeWords h p).gzstates = h.gzstates := by
51  unfold freeWords; split <;> rfl
52@[simp] theorem freeWords_bytes (h : Heap) (p : WPtr) : (freeWords h p).bytes = h.bytes := by
53  unfold freeWords; split <;> rfl
54@[simp] theorem freeWords_nextBlk (h : Heap) (p : WPtr) : (freeWords h p).nextBlk = h.nextBlk := by
55  unfold freeWords; split <;> rfl
56@[simp] theorem freeWords_ro (h : Heap) (p : WPtr) : (freeWords h p).ro = h.ro := by
57  unfold freeWords; split <;> rfl
58@[simp] theorem freeBytes_ro (h : Heap) (p : BPtr) : (freeBytes h p).ro = h.ro := by
59  unfold freeBytes; split <;> rfl
60@[simp] theorem freeWords_gzheaders (h : Heap) (p : WPtr) : (freeWords h p).gzheaders = h.gzheaders := by
61  unfold freeWords; split <;> rfl
62@[simp] theorem freeBytes_gzheaders (h : Heap) (p : BPtr) : (freeBytes h p).gzheaders = h.gzheaders := by
63  unfold freeBytes; split <;> rfl
64@[simp] theorem freeWords_istates (h : Heap) (p : WPtr) : (freeWords h p).istates = h.istates := by
65  unfold freeWords; split <;> rfl
66@[simp] theorem freeBytes_istates (h : Heap) (p : BPtr) : (freeBytes h p).istates = h.istates := by
67  unfold freeBytes; split <;> rfl
68
69@[simp] theorem ZStreamRef.get_freeBytes (h : Heap) (p : BPtr) (r : ZStreamRef) : r.get (freeBytes h p) = r.get h := by
70  cases r <;> simp [ZStreamRef.get]
71@[simp] theorem ZStreamRef.get_freeWords (h : Heap) (p : WPtr) (r : ZStreamRef) : r.get (freeWords h p) = r.get h := by
72  cases r <;> simp [ZStreamRef.get]
73
74theorem zfreeB_run {h : Heap} {r : ZStreamRef} {z : ZStream} (hz : r.get h = some z) (hf : z.zfree = .fn "zcfree")
75    {p : BPtr} (hp : p = .null ∨ ∃ b a, p = .ref (.blk b) 0 ∧ h.bytes b = some a ∧ h.ro b = false) :
76    ZFREE_bytes (some r) p h = .ok ((), freeBytes h p) := by
77  rcases hp with rfl | ⟨b, a, rfl, hb, hro⟩
78  · simp [ZFREE_bytes, zfree_default, ldZ_eq, hz, hf, freeBytes, freeB_null, bind_app]
79  · simp [ZFREE_bytes, zfree_default, ldZ_eq, hz, hf, freeBytes, freeB_ok hb hro, bind_app]
80
81theorem zfreeW_run {h : Heap} {r : ZStreamRef} {z : ZStream} (hz : r.get h = some z) (hf : z.zfree = .fn "zcfree")
82    {p : WPtr} (hp : p = .null ∨ ∃ b a, p = .ref (.blk b) 0 ∧ h.words b = some a) :
83    ZFREE_words (some r) p h = .ok ((), freeWords h p) := by
84  rcases hp with rfl | ⟨b, a, rfl, hb⟩
85  · simp [ZFREE_words, zfree_default, ldZ_eq, hz, hf, freeWords, bind_app]; rfl
86  · simp [ZFREE_words, zfree_default, ldZ_eq, hz, hf, freeWords, freeW_ok hb, bind_app]
87
88
89@[simp] theorem ZStreamRef.get_dstates (g : Heap) (r : ZStreamRef) (t : Tbl (Option DeflateState)) :
90    r.get { g with dstates := t } = r.get g := by cases r <;> rfl
91
92theorem ZStreamRef.put_with_dstates (g : Heap) (r : ZStreamRef) (t : Tbl (Option DeflateState)) (v : ZStream) :
93    r.put { g with dstates := t } v = { r.put g v with dstates := t } := by
94  cases r with
95  | tab i => simp only [ZStreamRef.put]; cases g.streams i <;> rfl
96  | in_gzstate_strm i => simp only [ZStreamRef.put]; cases g.gzstates i <;> rfl
97
98theorem zfree_default_run {h : Heap} {r : ZStreamRef} {z : ZStream} (hz : r.get h = some z)
99    (hf : z.zfree = .fn "zcfree") : zfree_default (some r) h = .ok ((), h) := by
100  simp [zfree_default, ldZ_eq, hz, hf, bind_app]
101
102theorem freeDeflateState_free_ok {h' : Heap} {ds : Nat} {d : DeflateState} (hd : h'.dstates ds = some d) :
103    freeDeflateState (some (.tab ds)) h' = .ok ((), { h' with dstates := upd h'.dstates ds none }) :=
104  freeDeflateState_tab hd
105
106theorem deflateEnd_run {h : Heap} {r : ZStreamRef} {ds : Nat} {z : ZStream} {d : DeflateState} {w p q b : Nat}
107    (hL : DLive h r ds z d) (hf : z.zfree = .fn "zcfree") (hB : DBlocks h d w p q b) :
108    deflateEnd (some r) h =
109      .ok ((if d.status == BUSY_STATE then Z_DATA_ERROR else Z_OK), endHeap h r ds z d) := by
110  obtain ⟨wa, hwa, -⟩ := hB.wa
111  obtain ⟨pa, hpa, -⟩ := hB.pa
112  obtain ⟨qa, hqa, -⟩ := hB.qa
113  obtain ⟨ba, hba, -⟩ := hB.ba
114  have hbw : b ≠ w := fun e => hB.wb e.symm
115  have f1 := zfreeB_run (h := h) hL.hz hf (p := d.pending_buf) (Or.inr ⟨b, ba, hB.pbuf, hba, hB.bro⟩)
116  have f2 := zfreeW_run (h := freeBytes h d.pending_buf) (r := r) (z := z) (by simpa using hL.hz) hf (p := d.head)
117    (Or.inr ⟨q, qa, hB.head, by simpa using hqa⟩)
118  have f3 := zfreeW_run (h := freeWords (freeBytes h d.pending_buf) d.head) (r := r) (z := z) (by simpa using hL.hz) hf
119    (p := d.prev) (Or.inr ⟨p, pa, hB.prev, by
120      have : (freeWords (freeBytes h d.pending_buf) d.head).words p = h.words p := by
121        rw [hB.head]; simp [freeWords, upd_ne _ _ _ _ hB.pq]
122      rw [this]; exact hpa⟩)
123  have f4 := zfreeB_run (h := freeWords (freeWords (freeBytes h d.pending_buf) d.head) d.prev) (r := r) (z := z)
124    (by simpa using hL.hz) hf (p := d.window) (Or.inr ⟨w, wa, hB.win, by
125      simp only [freeWords_bytes, freeBytes, hB.pbuf, hB.win]
126      simp [upd_ne _ _ _ _ hbw.symm, hwa], by simpa using hB.wro⟩)
127  simp only [hB.pbuf, hB.head, hB.prev, hB.win] at f1 f2 f3 f4
128  unfold deflateEnd
129  dsimp' [stateCheck_live hL, hL.zst, hL.hz, hL.hs, hB.pbuf, hB.head, hB.prev, hB.win, f1, f2, f3, f4]
130  have hz' : ∀ h' : Heap, r.get h' = r.get h → zfree_default (some r) h' = .ok ((), h') := fun h' e =>
131    zfree_default_run (by rw [e]; exact hL.hz) hf
132  rw [hz']
133  · simp only [bind_app, pure_app]
134    rw [freeDeflateState_free_ok (d := d)]
135    · simp only [ZStreamRef.get_dstates, ZStreamRef.get_freeBytes, ZStreamRef.get_freeWords, hL.hz,
136        ZStreamRef.put_with_dstates, endHeap, hB.win, hB.prev, hB.head, hB.pbuf, freeBytes_dstates, freeWords_dstates]
137    · simp [hL.hs]
138  · simp
139
140
141theorem endHeap_eq {h : Heap} {r : ZStreamRef} {ds : Nat} {z : ZStream} {d : DeflateState} {w p q b : Nat}
142    (hB : DBlocks h d w p q b) :
143    endHeap h r ds z d = { r.put { h with bytes := upd (upd h.bytes b none) w none,
144                                          words := upd (upd h.words q none) p none } { z with state := none }
145                           with dstates := upd h.dstates ds none } := by
146  unfold endHeap
147  rw [hB.win, hB.prev, hB.head, hB.pbuf]
148  simp only [freeBytes, freeWords]
149
150theorem DOwned_iff {d : DeflateState} {ds w p q b : Nat} {h : Heap} (hB : DBlocks h d w p q b) (x : Nat) :
151    DOwned d ds x ↔ x = ds ∨ x = w ∨ x = p ∨ x = q ∨ x = b := by
152  unfold DOwned
153  rw [hB.win, hB.prev, hB.head, hB.pbuf]
154  constructor
155  · rintro (h1 | ⟨w', h2, h3⟩ | ⟨p', h2, h3⟩ | ⟨q', h2, h3⟩ | ⟨b', h2, h3⟩)
156    · exact Or.inl h1
157    · cases h2; exact Or.inr (Or.inl h3)
158    · cases h2; exact Or.inr (Or.inr (Or.inl h3))
159    · cases h2; exact Or.inr (Or.inr (Or.inr (Or.inl h3)))
160    · cases h2; exact Or.inr (Or.inr (Or.inr (Or.inr h3)))
161  · rintro (h1 | h1 | h1 | h1 | h1)
162    · exact Or.inl h1
163    · exact Or.inr (Or.inl ⟨w, by simp, h1⟩)
164    · exact Or.inr (Or.inr (Or.inl ⟨p, by simp, h1⟩))
165    · exact Or.inr (Or.inr (Or.inr (Or.inl ⟨q, by simp, h1⟩)))
166    · exact Or.inr (Or.inr (Or.inr (Or.inr ⟨b, by simp, h1⟩)))
167
168theorem ZStreamRef.get_bw (g : Heap) (r : ZStreamRef) (bs : Tbl (Option (Array UInt8))) (ws : Tbl (Option (Array UInt16))) :
169    r.get { g with bytes := bs, words := ws } = r.get g := by cases r <;> rfl
170
171theorem ZStreamRef.put_streams (r : ZStreamRef) (g : Heap) (v : ZStream) (x : Nat)
172    (hx : ∀ i, r = .tab i → x ≠ i) : (r.put g v).streams x = g.streams x := by
173  cases r with
174  | tab i => 
175    have := hx i rfl
176    simp only [ZStreamRef.put]; split <;> simp [upd_apply, this]
177  | in_gzstate_strm i => simp only [ZStreamRef.put]; split <;> rfl
178
179theorem ZStreamRef.put_gzstates (r : ZStreamRef) (g : Heap) (v : ZStream) (x : Nat)
180    (hx : ∀ i, r = .in_gzstate_strm i → x ≠ i) : (r.put g v).gzstates x = g.gzstates x := by
181  cases r with
182  | tab i => simp only [ZStreamRef.put]; split <;> rfl
183  | in_gzstate_strm i =>
184    have := hx i rfl
185    simp only [ZStreamRef.put]; split <;> simp [upd_apply, this]
186
187theorem endHeap_tables {h : Heap} {r : ZStreamRef} {ds : Nat} {z : ZStream} {d : DeflateState} {w p q b : Nat}
188    (hB : DBlocks h d w p q b) (hz : r.get h = some z) (x : Nat) :
189    (endHeap h r ds z d).bytes x = (if x = w ∨ x = b then none else h.bytes x) ∧
190    (endHeap h r ds z d).words x = (if x = p ∨ x = q then none else h.words x) ∧
191    (endHeap h r ds z d).dstates x = (if x = ds then none else h.dstates x) ∧
192    ((endHeap h r ds z d).streams x).isSome = (h.streams x).isSome ∧
193    ((endHeap h r ds z d).gzstates x).isSome = (h.gzstates x).isSome ∧
194    (endHeap h r ds z d).gzheaders x = h.gzheaders x ∧ (endHeap h r ds z d).istates x = h.istates x := by
195  have hS : Shape { h with bytes := upd (upd h.bytes b none) w none, words := upd (upd h.words q none) p none }
196      (r.put { h with bytes := upd (upd h.bytes b none) w none, words := upd (upd h.words q none) p none }
197        { z with state := none }) := shape_put (by rw [ZStreamRef.get_bw]; exact hz) _
198  obtain ⟨-, -, e4, -, -, -, e5⟩ := hS x
199  rw [endHeap_eq hB]
200  refine ⟨?_, ?_, ?_, ?_, ?_, ?_, ?_⟩
201  · simp only [ZStreamRef.put_bytes]; simp only [upd_apply]
202    by_cases h1 : x = w <;> by_cases h2 : x = b <;> simp [h1, h2]
203  · simp only [ZStreamRef.put_words]; simp only [upd_apply]
204    by_cases h1 : x = p <;> by_cases h2 : x = q <;> simp [h1, h2]
205  · simp only [ZStreamRef.put_dstates]; simp only [upd_apply]
206  · exact e4
207  · exact e5
208  · simp
209  · simp
210
211theorem endHeap_live {h : Heap} {r : ZStreamRef} {ds : Nat} {z : ZStream} {d : DeflateState} {w p q b : Nat}
212    (hB : DBlocks h d w p q b) (hU : Uniq h) (hz : r.get h = some z) (hs : h.dstates ds = some d) (x : Nat) :
213    (endHeap h r ds z d).live x ↔ h.live x ∧ ¬ (x = ds ∨ x = w ∨ x = p ∨ x = q ∨ x = b) := by
214  obtain ⟨wa, hwa, -⟩ := hB.wa
215  obtain ⟨pa, hpa, -⟩ := hB.pa
216  obtain ⟨qa, hqa, -⟩ := hB.qa
217  obtain ⟨ba, hba, -⟩ := hB.ba
218  obtain ⟨t1, t2, t3, t4, t5, t6, t7⟩ := endHeap_tables (ds := ds) hB hz x
219  have key : (endHeap h r ds z d).live x ↔
220      ((endHeap h r ds z d).bytes x ≠ none ∨ (endHeap h r ds z d).words x ≠ none ∨ (h.streams x).isSome ∨
221        h.gzheaders x ≠ none ∨ (endHeap h r ds z d).dstates x ≠ none ∨ h.istates x ≠ none ∨ (h.gzstates x).isSome) := by
222    unfold Heap.live
223    rw [t6, t7, ← Option.isSome_iff_ne_none (o := (endHeap h r ds z d).streams x), t4,
224      ← Option.isSome_iff_ne_none (o := (endHeap h r ds z d).gzstates x), t5]
225  rw [key]
226  unfold Heap.live
227  rw [t1, t2, t3]
228  by_cases hx : x = ds ∨ x = w ∨ x = p ∨ x = q ∨ x = b
229  · simp only [hx, not_true_eq_false, and_false, iff_false]
230    rcases hx with rfl | rfl | rfl | rfl | rfl
231    · obtain ⟨e1, e2, e3, e4, e5, e6⟩ := hU.dstates_only hs
232      simp [e1, e2, e3, e4, e5, e6]
233    · obtain ⟨e1, e2, e3, e4, e5, e6⟩ := hU.bytes_only hwa
234      simp [e1, e2, e3, e4, e5, e6, Option.isSome_none]
235    · obtain ⟨e1, e2, e3, e4, e5, e6⟩ := hU.words_only hpa
236      simp [e1, e2, e3, e4, e5, e6, Option.isSome_none]
237    · obtain ⟨e1, e2, e3, e4, e5, e6⟩ := hU.words_only hqa
238      simp [e1, e2, e3, e4, e5, e6, Option.isSome_none]
239    · obtain ⟨e1, e2, e3, e4, e5, e6⟩ := hU.bytes_only hba
240      simp [e1, e2, e3, e4, e5, e6, Option.isSome_none]
241  · have hx1 : ¬ (x = w ∨ x = b) := fun e => hx (by rcases e with e | e <;> simp [e])
242    have hx2 : ¬ (x = p ∨ x = q) := fun e => hx (by rcases e with e | e <;> simp [e])
243    have hx3 : ¬ x = ds := fun e => hx (Or.inl e)
244    have hn : ¬ (x = w ∨ x = p ∨ x = q ∨ x = b) := fun e => hx (Or.inr e)
245    simp only [hx1, hx2, hx3, ite_false]
246    simp [hn, Option.isSome_iff_ne_none]
247
248theorem endHeap_uniq {h : Heap} {r : ZStreamRef} {ds : Nat} {z : ZStream} {d : DeflateState} {w p q b : Nat}
249    (hB : DBlocks h d w p q b) (hU : Uniq h) (hz : r.get h = some z) : Uniq (endHeap h r ds z d) := by
250  intro x
251  obtain ⟨t1, t2, t3, t4, t5, t6, t7⟩ := endHeap_tables (ds := ds) hB hz x
252  have := hU x
253  have c1 : cnt ((endHeap h r ds z d).bytes x) ≤ cnt (h.bytes x) := by
254    rw [t1]; split <;> simp [cnt]
255  have c2 : cnt ((endHeap h r ds z d).words x) ≤ cnt (h.words x) := by
256    rw [t2]; split <;> simp [cnt]
257  have c3 : cnt ((endHeap h r ds z d).dstates x) ≤ cnt (h.dstates x) := by
258    rw [t3]; split <;> simp [cnt]
259  have c4 : cnt ((endHeap h r ds z d).streams x) = cnt (h.streams x) := by simp only [cnt, t4]
260  have c5 : cnt ((endHeap h r ds z d).gzstates x) = cnt (h.gzstates x) := by simp only [cnt, t5]
261  rw [t6, t7]
262  omega
263
264/-- **deflateEnd, safety and specification.** On an initialised stream with the invariant and the default `zfree`, the
265call never faults. It returns `Z_DATA_ERROR` if the status was `BUSY_STATE` (the stream ended in the middle of a block)
266and `Z_OK` otherwise. It frees exactly the state record and its four buffers (`window`, `prev`, `head`, `pending_buf`) and
267sets `strm->state` to `NULL`: the live blocks afterwards are the old ones minus those five (no leak, no double
268free), every other block of every table is as before, and the heap is again `Uniq` and `Fresh`. (The blocks are named by
269`DBlocks`.) -/
270theorem deflateEnd_safe {h : Heap} {r : ZStreamRef} {ds : Nat} {z : ZStream} {d : DeflateState}
271    (hG : DGood h r ds z d) (hf : z.zfree = .fn "zcfree") :
272    ∃ w p q b, DBlocks h d w p q b ∧ ∃ h',
273      C.run (deflateEnd (some r)) h = .ok ((if d.status = BUSY_STATE then Z_DATA_ERROR else Z_OK), h') ∧
274      h' = endHeap h r ds z d ∧ r.get h' = some { z with state := none } ∧
275      h'.dstates ds = none ∧ h'.bytes w = none ∧ h'.bytes b = none ∧ h'.words p = none ∧ h'.words q = none ∧
276      (∀ x, x ≠ ds → h'.dstates x = h.dstates x) ∧ (∀ x, x ≠ w → x ≠ b → h'.bytes x = h.bytes x) ∧
277      (∀ x, x ≠ p → x ≠ q → h'.words x = h.words x) ∧ h'.ro = h.ro ∧ h'.gzheaders = h.gzheaders ∧
278      h'.istates = h.istates ∧ h'.nextBlk = h.nextBlk ∧ h'.nalloc = h.nalloc ∧
279      (∀ x, (∀ i, r = .tab i → x ≠ i) → h'.streams x = h.streams x) ∧
280      (∀ x, (∀ i, r = .in_gzstate_strm i → x ≠ i) → h'.gzstates x = h.gzstates x) ∧
281      Uniq h' ∧ Fresh h' ∧ (∀ S, h.Owns S → h'.Owns (fun x => S x ∧ ¬ DOwned d ds x)) := by
282  obtain ⟨w, p, q, b, hB⟩ := hG.inv.blocks
283  refine ⟨w, p, q, b, hB, _, ?_, rfl, ?_⟩
284  · have := deflateEnd_run hG.live hf hB
285    rw [C.run, this]
286    simp [BEq.beq]
287  have hU := hG.uniq
288  have hF := hG.fresh
289  obtain ⟨wa, hwa, -⟩ := hB.wa
290  obtain ⟨pa, hpa, -⟩ := hB.pa
291  obtain ⟨qa, hqa, -⟩ := hB.qa
292  obtain ⟨ba, hba, -⟩ := hB.ba
293  have hbw : b ≠ w := fun e => hB.wb e.symm
294  have hz := hG.live.hz
295  have hs := hG.live.hs
296  have hUni := endHeap_uniq (ds := ds) hB hU hz
297  have hLive := endHeap_live hB hU hz hs
298  have hnb : (endHeap h r ds z d).nextBlk = h.nextBlk := by rw [endHeap_eq hB]; simp
299  rw [endHeap_eq hB]
300  refine ⟨?_, by simp, by simp, by simp [hbw], by simp, by simp [hB.pq.symm], ?_, ?_, ?_, by simp, by simp, by simp, by simp,
301    by simp, ?_, ?_, ?_, ?_, ?_⟩
302  · rw [ZStreamRef.get_dstates, ZStreamRef.get_put, ZStreamRef.get_bw, hz]; rfl
303  · intro x hx; simp [upd_apply, hx]
304  · intro x h1 h2; simp [upd_apply, h1, h2]
305  · intro x h1 h2; simp [upd_apply, h1, h2]
306  · intro x hx; simp [ZStreamRef.put_streams r _ _ x hx]
307  · intro x hx; simp [ZStreamRef.put_gzstates r _ _ x hx]
308  · rw [← endHeap_eq hB]; exact hUni
309  · intro x hx hl
310    rw [← endHeap_eq hB] at hl
311    rw [← endHeap_eq hB] at hx
312    rw [hnb] at hx
313    exact hF x hx ((hLive x).1 hl).1
314  · intro S hO x
315    rw [← endHeap_eq hB, hLive x, hO x]
316    show _ ↔ S x ∧ ¬ DOwned d ds x
317    rw [DOwned_iff hB x]
318
319/-- **deflateEnd, refusal.** On a stream the check refuses (including `NULL`) the call returns `Z_STREAM_ERROR` and changes
320nothing (in particular nothing is freed). -/
321theorem deflateEnd_reject {h : Heap} {strm : ZStreamPtr} (hD : StreamDom h strm) (hN : ¬ DInitialised h strm) :
322    C.run (deflateEnd strm) h = .ok (Z_STREAM_ERROR, h) := by
323  unfold deflateEnd
324  exact check_refuse hD hN _ _
325
326end Zlib.Deflate.Proofs
ZLIB × LEAN

Global contents

READING NOWdeflate.c.life.end.lean