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

Initialisation.lean

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

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

1import ZlibF.Spec.Api.Basic
2import ZlibF.Spec.Public.StreamQueries
3import ZlibF.Proof.«inflate.c.base»
4import ZlibF.Proof.«deflate.c.base»
5
6namespace ZlibF.Spec.Public
7open C
8
9/-- A frame over existing allocations. New allocations are governed separately by `LiveChange`. -/
10def Frame (before after : Heap) (changed : Nat → Prop) : Prop :=
11  before.static = after.static ∧ before.allocOk = after.allocOk ∧ before.garbage = after.garbage ∧
12  before.nextBlk ≤ after.nextBlk ∧ before.nalloc ≤ after.nalloc ∧
13  ∀ b, before.live b → ¬ changed b →
14    after.bytes b = before.bytes b ∧ after.words b = before.words b ∧
15    after.streams b = before.streams b ∧ after.gzheaders b = before.gzheaders b ∧
16    after.dstates b = before.dstates b ∧ after.istates b = before.istates b ∧
17    after.gzstates b = before.gzstates b ∧ after.ro b = before.ro b
18
19/-- An exact allocation ledger. A live allocation cannot disappear or remain unaccounted for. -/
20def LiveChange (before after : Heap) (created removed : Nat → Prop) : Prop :=
21  ∀ b, after.live b ↔ (before.live b ∧ ¬ removed b) ∨ created b
22
23def StreamRoot (r : ZStreamRef) (b : Nat) : Prop :=
24  match r with | .tab i | .in_gzstate_strm i => b = i
25
26def InflateOwned (i : Nat) (s : InflateState) (b : Nat) : Prop :=
27  b = i ∨ s.window = .ref (.blk b) 0
28
29def DeflateOwned (i : Nat) (s : DeflateState) (b : Nat) : Prop :=
30  b = i ∨ s.window = .ref (.blk b) 0 ∨ s.prev = .ref (.blk b) 0 ∨
31  s.head = .ref (.blk b) 0 ∨ s.pending_buf = .ref (.blk b) 0
32
33def DefaultOrNull (z : ZStream) : Prop :=
34  (z.zalloc = .null ∨ z.zalloc = .fn "zcalloc") ∧
35  (z.zfree = .null ∨ z.zfree = .fn "zcfree")
36
37def preparedStream (z : ZStream) : ZStream :=
38  { z with
39    msg := .null
40    zalloc := if z.zalloc == .null then .fn "zcalloc" else z.zalloc
41    «opaque» := if z.zalloc == .null then .null else z.opaque
42    zfree := if z.zfree == .null then .fn "zcfree" else z.zfree }
43
44/-- The version check reads only the first byte; the null version is a clean error. -/
45def VersionValue (h : Heap) (p : BPtr) (head : Option UInt8) : Prop :=
46  (p = .null ∧ head = none) ∨ ∃ b, head = some b ∧ Bytes h p 1 [b]
47
48def WindowAllocation (h : Heap) (p : BPtr) : Prop :=
49  p = .null ∨ ∃ b a, p = .ref (.blk b) 0 ∧ h.bytes b = some a ∧ h.ro b = false
50
51/-- Remove a writable byte allocation. Read-only metadata, including its table shape, is
52unchanged. Callers establish WindowAllocation or the corresponding owned-message condition. -/
53def dropWindow (h : Heap) : BPtr → Heap
54  | .ref (.blk b) 0 => { h with bytes := upd h.bytes b none }
55  | _ => h
56
57/-- Init's successful representation includes the complete established invariant, not an
58invariant supplied by the caller. The single allocation is the new state record. -/
59def InflateInitial (before after : Heap) (r : ZStreamRef) (wrap : Api.Wrap) (bits : Nat) : Prop :=
60  ∃ z s, Zlib.Inflate.Spec.Good after r before.nextBlk z s ∧
61    z.zalloc = .fn "zcalloc" ∧ z.zfree = .fn "zcfree" ∧
62    s.mode = HEAD ∧ s.window = .null ∧ s.wbits.toNat = bits ∧ s.reqbits.toNat = bits ∧
63    s.wrap = (match wrap with | .raw => 0 | .zlib => 5 | .gzip => 6 | .auto => 7) ∧
64    s.reqwrap = s.wrap ∧ s.wsize = 0 ∧ s.whave = 0 ∧ s.wnext = 0 ∧
65    s.hold = 0 ∧ s.bits = 0 ∧ s.havedict = 0 ∧ s.head = none ∧
66    z.total_in = 0 ∧ z.total_out = 0 ∧ z.msg = .null ∧
67    Frame before after (StreamRoot r) ∧
68    LiveChange before after (fun b => b = before.nextBlk) (fun _ => False)
69
70/-- Allocation precedes the window-bit check in inflate init. In particular, an invalid
71window configuration can return `Z_MEM_ERROR` before it returns `Z_STREAM_ERROR`. -/
72def InflateInitContract (program : ZStreamPtr → BPtr → Int32 → M Int32) (wb : Int32) : Prop :=
73  (∀ h p version head size, VersionValue h version head →
74    (head ≠ some 49 ∨ size ≠ 112) → C.run (program p version size) h = .ok (Z_VERSION_ERROR, h)) ∧
75  (∀ h version, VersionValue h version (some 49) →
76    C.run (program none version 112) h = .ok (Z_STREAM_ERROR, h)) ∧
77  (∀ h r z version, Fresh h → Zlib.Inflate.Spec.Uniq h → LibraryGlobals h →
78    r.get h = some z → DefaultOrNull z → VersionValue h version (some 49) →
79    ∃ rc after, C.run (program (some r) version 112) h = .ok (rc, after) ∧
80      after.nalloc = h.nalloc + 1 ∧
81      (if h.allocOk h.nalloc = false then
82        rc = Z_MEM_ERROR ∧ SameObjects (r.put h (preparedStream z)) after
83      else match Api.inflWbits wb.toInt with
84      | none => rc = Z_STREAM_ERROR ∧
85          SameObjects (r.put h { preparedStream z with state := none }) after
86      | some (wrap, bits) => rc = Z_OK ∧ InflateInitial h after r wrap bits))
87
88/-- `int inflateInit2_(z_streamp strm, int windowBits, const char *version, int stream_size)`.
89All signed window arguments and every allocation oracle are included, in source error order. -/
90def Goal.inflateInit2_ : Prop :=
91  ∀ wb, InflateInitContract (fun p v size => Zlib.Inflate.inflateInit2_ p wb v size) wb
92
93/-- `int inflateInit_(z_streamp strm, const char *version, int stream_size)`.
94The same version, stream, allocation, cleanup and invariant contract at window bits 15. -/
95def Goal.inflateInit_ : Prop := InflateInitContract Zlib.Inflate.inflateInit_ 15
96
97def DeflateInitial (before after : Heap) (r : ZStreamRef) (p : Api.DeflParams) : Prop :=
98  ∃ z s, Zlib.Deflate.Spec.DGood after r before.nextBlk z s ∧
99    z.zalloc = .fn "zcalloc" ∧ z.zfree = .fn "zcfree" ∧
100    s.level.toInt = p.level ∧ s.strategy.toInt = p.strategy ∧ s.w_bits.toNat = p.wbits ∧
101    s.hash_bits.toNat = p.memLevel + 7 ∧
102    s.wrap = (match p.wrap with | .raw => 0 | .zlib => 1 | .gzip => 2) ∧
103    s.strstart = 0 ∧ s.lookahead = 0 ∧ s.pending = 0 ∧ s.bi_valid = 0 ∧ s.gzhead = none ∧
104    z.total_in = 0 ∧ z.total_out = 0 ∧ z.msg = .null ∧
105    Frame before after (StreamRoot r) ∧
106    LiveChange before after (DeflateOwned before.nextBlk s) (fun _ => False) ∧
107    (∀ b, DeflateOwned before.nextBlk s b ↔ before.nextBlk ≤ b ∧ b < before.nextBlk + 5)
108
109/-- Deflate validates parameters before allocating. Once the state allocation succeeds it
110attempts all four buffer allocations, even when an earlier buffer allocation failed. -/
111def DeflateInitContract (program : ZStreamPtr → BPtr → Int32 → M Int32)
112    (level method wb mem strategy : Int32) : Prop :=
113  (∀ h p version head size, VersionValue h version head →
114    (head ≠ some 49 ∨ size ≠ 112) → C.run (program p version size) h = .ok (Z_VERSION_ERROR, h)) ∧
115  (∀ h version, VersionValue h version (some 49) →
116    C.run (program none version 112) h = .ok (Z_STREAM_ERROR, h)) ∧
117  (∀ h r z version, Fresh h → Zlib.Deflate.Spec.Uniq h → LibraryGlobals h →
118    r.get h = some z → DefaultOrNull z → VersionValue h version (some 49) →
119    ∃ rc after, C.run (program (some r) version 112) h = .ok (rc, after) ∧
120      (match Api.deflInit? level.toInt method.toInt wb.toInt mem.toInt strategy.toInt with
121      | none => rc = Z_STREAM_ERROR ∧ SameObjects (r.put h (preparedStream z)) after ∧
122          after.nalloc = h.nalloc
123      | some p =>
124        if h.allocOk h.nalloc = false then
125          rc = Z_MEM_ERROR ∧ after.nalloc = h.nalloc + 1 ∧
126          SameObjects (r.put h (preparedStream z)) after
127        else after.nalloc = h.nalloc + 5 ∧
128          if (List.range 5).all (fun j => h.allocOk (h.nalloc + j)) then
129            rc = Z_OK ∧ DeflateInitial h after r p
130          else rc = Z_MEM_ERROR ∧
131            (∃ z', r.get after = some z' ∧ z'.state = none) ∧
132            LiveChange h after (fun _ => False) (fun _ => False) ∧
133            Frame h after (StreamRoot r)))
134
135/-- `int deflateInit2_(z_streamp strm, int level, int method, int windowBits, int memLevel,
136int strategy, const char *version, int stream_size)`.
137Every signed argument, source-ordered refusal, five allocations, failure cleanup and success invariant. -/
138def Goal.deflateInit2_ : Prop :=
139  ∀ level method wb mem strategy,
140    DeflateInitContract (fun p v size => Zlib.Deflate.deflateInit2_ p level method wb mem strategy v size)
141      level method wb mem strategy
142
143/-- `int deflateInit_(z_streamp strm, int level, const char *version, int stream_size)`.
144The default method, window, memory level and strategy; the level remains arbitrary. -/
145def Goal.deflateInit_ : Prop :=
146  ∀ level, DeflateInitContract (fun p v size => Zlib.Deflate.deflateInit_ p level v size)
147    level 8 15 8 0
148
149end ZlibF.Spec.Public
ZLIB × LEAN

全局目录

当前位置Initialisation.lean