跳到正文
参考文档 / ZLIB × LEAN

QueryLayout.lean

此页源文件快照 · b3583e0627f9d35b · 对应提交的原文 ↗

本页保留 Lean 源码及行号。点击行号可定位语句,点击 import 中的模块名可查看依赖。

1import ZlibF.Spec.Public.StreamQueries
2import ZlibF.Proof.«inflate.c.misc»
3
4/-! Fixed C array layout for the public decode-table query. The legacy counterexample
5is an impossible C object shape, not a reachable library bug. -/
6namespace ZlibF.Spec.Public.Proofs
7open C Zlib.Inflate Zlib.Inflate.Spec Zlib.Inflate.Proofs
8
9private theorem refused_dom {h : Heap} {p : ZStreamPtr} (hr : RefusedInflate h p) : StreamDom h p := by
10  rcases hr with hnull | ⟨r,z,rfl,hz,hbad⟩
11  · exact Or.inl hnull
12  · refine Or.inr ⟨r,z,rfl,hz,?_⟩
13    rcases hbad with hza | hzf | hs | ⟨i,s,hstate,hsi,_⟩
14    · exact Or.inl hza
15    · exact Or.inr (Or.inl hzf)
16    · exact Or.inr (Or.inr (Or.inl hs))
17    · exact Or.inr (Or.inr (Or.inr ⟨i,s,hstate,hsi⟩))
18
19private theorem refused_not_initialised {h : Heap} {p : ZStreamPtr} (hr : RefusedInflate h p) : ¬ Initialised h p := by
20  intro ⟨r',i',z',s',hp,hL⟩
21  rcases hr with hn | ⟨r,z,hp',hz,hbad⟩
22  · rw [hn] at hp; cases hp
23  · rw [hp'] at hp
24    cases hp
25    have heq : z = z' := Option.some.inj (hz.symm.trans hL.hz)
26    subst z'
27    rcases hbad with ha | hf | hstate | ⟨i,s,hi,hs,hfail⟩
28    · exact hL.zalloc ha
29    · exact hL.zfree hf
30    · have hh := hL.zst
31      rw [hstate] at hh; cases hh
32    · have hieq : i = i' := by
33        have hh := hL.zst
34        rw [hi] at hh
35        cases hh
36        rfl
37      subst i'
38      have hseq : s = s' := Option.some.inj (hs.symm.trans hL.hs)
39      subst s'
40      rcases hfail with hback | hlo | hhi
41      · exact hback hL.back
42      · exact (UInt32.not_lt.mpr hL.mode.1) hlo
43      · exact (UInt32.not_lt.mpr hL.mode.2) hhi
44
45private theorem refused_state_check {h : Heap} {p : ZStreamPtr} (hr : RefusedInflate h p) :
46    inflateStateCheck p h = .ok (1, h) := by
47  obtain ⟨v, hv, hclass⟩ := inflateStateCheck_total (refused_dom hr)
48  rcases hclass with ⟨_, hi⟩ | ⟨rfl, _⟩
49  · exact (refused_not_initialised hr hi).elim
50  · exact hv
51
52/-- The fixed C array bounds make pointer subtraction representable. No callee contract is assumed. -/
53theorem codes_used_record {h : Heap} {r : ZStreamRef} {i : Nat}
54    {z : ZStream} {s : InflateState} {n : Nat}
55    (hv : InflateView h r i z s) (hsize : s.codes.size = 1444)
56    (hnext : s.next = .ref (.istate_codes i) n) (hn : n ≤ s.codes.size) :
57    C.run (inflateCodesUsed (some r)) h = .ok (UInt64.ofNat n, h) := by
58  rcases hv with ⟨hz,hstate,hi,hback,ha,hf,hlo,hhi⟩
59  have hl : Live h r i z s := ⟨hz,hi,hstate,hback,⟨hlo,hhi⟩,ha,hf⟩
60  have hc : Space.get h (CodeRef.istate_codes i) = some s.codes := by simp [Space.get, hl.hs]
61  have hd := Ptr.diff_ok hc (show n ≤ s.codes.size from hn)
62    (show 0 ≤ s.codes.size by omega)
63    (show -(2 ^ 63 : Int) ≤ (n : Int) - (0 : Nat) ∧ (n : Int) - (0 : Nat) < 2 ^ 63 by omega)
64  have hd' : Ptr.diff (Ptr.ref (CodeRef.istate_codes i) n) (Ptr.ref (CodeRef.istate_codes i) 0) h =
65      .ok (Int64.ofInt ((n : Int) - (0 : Nat)), h) := hd
66  unfold C.run inflateCodesUsed
67  isimp [stateCheck_live hl, hl.zst, hl.hz, hl.hs, hnext, codesP, hd']
68  simp [ofInt_toUInt64]
69
70/-- `unsigned long inflateCodesUsed(z_streamp strm)` includes clean refusal and the source's fixed array layout. -/
71theorem inflate_codes_used : Goal.inflateCodesUsed := by
72  constructor
73  · intro h p hr
74    unfold C.run inflateCodesUsed
75    isimp [refused_state_check hr]
76  · intro h r i z s n hv hsize hnext hn
77    exact codes_used_record hv hsize hnext hn
78
79/-- The ordinary init-established invariant entails the fixed-layout condition. -/
80theorem codes_layout_of_good {h : Heap} {r : ZStreamRef} {i : Nat}
81    {z : ZStream} {s : InflateState} (hg : Good h r i z s) : s.codes.size = 1444 :=
82  hg.inv.wf.2.2
83
84/-- The former query condition omitted the fixed C array layout. -/
85def legacyCodesUsed : Prop :=
86  CheckedInflate Zlib.Inflate.inflateCodesUsed 0xffffffffffffffff <|
87  ∀ h r i z s n, InflateView h r i z s →
88    s.next = .ref (.istate_codes i) n → n ≤ s.codes.size →
89    C.run (Zlib.Inflate.inflateCodesUsed (some r)) h = .ok (UInt64.ofNat n, h)
90
91def badSize : Nat := 2 ^ 63
92
93def hugeZ : ZStream := { (default : ZStream) with
94  zalloc := .fn "zcalloc", zfree := .fn "zcfree", state := some (.inflate 1) }
95def hugeS (a : Array Code) : InflateState := { (default : InflateState) with
96  strm := some (.tab 0), mode := HEAD, next := .ref (.istate_codes 1) badSize, codes := a }
97def hugeH (a : Array Code) : Heap := { Heap.empty with
98  streams := ⟨#[some hugeZ]⟩, istates := ⟨#[none, some (hugeS a)]⟩ }
99
100theorem huge_view (a : Array Code) : InflateView (hugeH a) (.tab 0) 1 hugeZ (hugeS a) := by
101  simp [InflateView, hugeH, hugeS, hugeZ, ZStreamRef.get, Tbl.get, StateRef.ofInflateState, HEAD, SYNC]
102
103theorem huge_result (a : Array Code) (ha : badSize ≤ a.size) :
104    C.run (inflateCodesUsed (some (.tab 0))) (hugeH a) =
105      .error (.ub "pointer difference is not a ptrdiff_t") := by
106  have hl : Live (hugeH a) (.tab 0) 1 hugeZ (hugeS a) := by
107    obtain ⟨hz,hstate,hi,hback,ha,hf,hlo,hhi⟩ := huge_view a
108    exact ⟨hz,hi,hstate,hback,⟨hlo,hhi⟩,ha,hf⟩
109  have hd : Ptr.diff (Ptr.ref (CodeRef.istate_codes 1) badSize) (Ptr.ref (CodeRef.istate_codes 1) 0) (hugeH a) =
110      .error (.ub "pointer difference is not a ptrdiff_t") := by
111    have hb : 9223372036854775808 ≤ a.size := by simpa [badSize] using ha
112    simp [Ptr.diff, Space.get, hugeH, hugeS, Tbl.get, hb, badSize]
113  unfold C.run inflateCodesUsed
114  isimp [stateCheck_live hl, hl.zst, hl.hz, hl.hs, hugeS, codesP, hd]
115
116theorem legacy_codes_used_false (a : Array Code) (ha : badSize ≤ a.size) : ¬ legacyCodesUsed := by
117  intro hg
118  have hp := hg.2 (hugeH a) (.tab 0) 1 hugeZ (hugeS a) badSize (huge_view a) rfl ha
119  rw [huge_result a ha] at hp
120  cases hp
121
122/-- The old public condition admits a pointer difference outside ptrdiff_t. -/
123theorem legacy_codes_used_impossible : ¬ legacyCodesUsed := by
124  apply legacy_codes_used_false (Array.replicate badSize (default : Code))
125  simp
126
127
128end ZlibF.Spec.Public.Proofs
ZLIB × LEAN

全局目录

当前位置QueryLayout.lean