Skip to content
REFERENCE / ZLIB × LEAN

StreamQueries.lean

Source snapshot · 19d83d5100da3fdf · 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.Memory
2
3namespace ZlibF.Spec.Public
4open C
5
6/-- The stream and inflate record accepted by the public state check. This is a
7representation condition, to be established by init and preserved by stream operations. -/
8def InflateView (h : Heap) (r : ZStreamRef) (i : Nat) (z : ZStream) (s : InflateState) : Prop :=
9  r.get h = some z ∧ z.state = StateRef.ofInflateState (some (.tab i)) ∧
10  h.istates i = some s ∧ s.strm = some r ∧ z.zalloc ≠ .null ∧ z.zfree ≠ .null ∧
11  HEAD ≤ s.mode ∧ s.mode ≤ SYNC
12
13/-- The stream and deflate record accepted by the public state check. -/
14def DeflateView (h : Heap) (r : ZStreamRef) (i : Nat) (z : ZStream) (s : DeflateState) : Prop :=
15  r.get h = some z ∧ z.state = StateRef.ofDeflateState (some (.tab i)) ∧
16  h.dstates i = some s ∧ s.strm = some r ∧ z.zalloc ≠ .null ∧ z.zfree ≠ .null ∧
17  (s.status = INIT_STATE ∨ s.status = GZIP_STATE ∨ s.status = EXTRA_STATE ∨
18   s.status = NAME_STATE ∨ s.status = COMMENT_STATE ∨ s.status = HCRC_STATE ∨
19   s.status = BUSY_STATE ∨ s.status = FINISH_STATE)
20
21def putInflate (h : Heap) (i : Nat) (s : InflateState) : Heap :=
22  { h with istates := upd h.istates i (some s) }
23
24def putDeflate (h : Heap) (i : Nat) (s : DeflateState) : Heap :=
25  { h with dstates := upd h.dstates i (some s) }
26
27/-- Cleanly rejected pointers contain enough live storage for the source state check.
28A dangling or wrongly typed state is not a permitted caller argument. -/
29def RefusedInflate (h : Heap) (p : ZStreamPtr) : Prop :=
30  p = none ∨ ∃ r z, p = some r ∧ r.get h = some z ∧
31    (z.zalloc = .null ∨ z.zfree = .null ∨ z.state = none ∨
32      ∃ i s, z.state = some (.inflate i) ∧ h.istates i = some s ∧
33        (s.strm ≠ some r ∨ s.mode < HEAD ∨ SYNC < s.mode))
34
35def RefusedDeflate (h : Heap) (p : ZStreamPtr) : Prop :=
36  p = none ∨ ∃ r z, p = some r ∧ r.get h = some z ∧
37    (z.zalloc = .null ∨ z.zfree = .null ∨ z.state = none ∨
38      ∃ i s, z.state = some (.deflate i) ∧ h.dstates i = some s ∧
39        (s.strm ≠ some r ∨ ¬ (s.status = INIT_STATE ∨ s.status = GZIP_STATE ∨
40          s.status = EXTRA_STATE ∨ s.status = NAME_STATE ∨ s.status = COMMENT_STATE ∨
41          s.status = HCRC_STATE ∨ s.status = BUSY_STATE ∨ s.status = FINISH_STATE)))
42
43def CheckedInflate {α : Type} (program : ZStreamPtr → M α) (error : α)
44    (accepted : Prop) : Prop :=
45  (∀ h p, RefusedInflate h p → C.run (program p) h = .ok (error, h)) ∧ accepted
46
47def CheckedDeflate {α : Type} (program : ZStreamPtr → M α) (error : α)
48    (accepted : Prop) : Prop :=
49  (∀ h p, RefusedDeflate h p → C.run (program p) h = .ok (error, h)) ∧ accepted
50
51/-- `int inflateSyncPoint(z_streamp strm)`.
52The answer is exactly the stored-block boundary test; all memory is preserved. -/
53def Goal.inflateSyncPoint : Prop :=
54  CheckedInflate Zlib.Inflate.inflateSyncPoint Z_STREAM_ERROR <|
55  ∀ h r i z s, InflateView h r i z s →
56    C.run (Zlib.Inflate.inflateSyncPoint (some r)) h =
57      .ok ((if s.mode = STORED ∧ s.bits = 0 then 1 else 0), h)
58
59/-- `long inflateMark(z_streamp strm)`.
60The high half counts code bits; the low half counts remaining stored bytes or match bytes
61already copied. The internal ranges are obligations of the stream invariant. -/
62def Goal.inflateMark : Prop :=
63  CheckedInflate Zlib.Inflate.inflateMark (-65536) <|
64  ∀ h r i z s, InflateView h r i z s →
65    C.run (Zlib.Inflate.inflateMark (some r)) h = .ok
66      (Int64.ofInt (s.back.toInt * 65536 +
67        (if s.mode = COPY then s.length.toNat else
68         if s.mode = MATCH then (s.was - s.length).toNat else 0)), h)
69
70/-- `unsigned long inflateCodesUsed(z_streamp strm)`.
71Return the number of used decode-table slots, with no memory effect. The fixed C
72array has 1444 entries; init and stream preservation establish this representation fact. -/
73def Goal.inflateCodesUsed : Prop :=
74  CheckedInflate Zlib.Inflate.inflateCodesUsed 0xffffffffffffffff <|
75  ∀ h r i z s n, InflateView h r i z s → s.codes.size = 1444 →
76    s.next = .ref (.istate_codes i) n → n ≤ s.codes.size →
77    C.run (Zlib.Inflate.inflateCodesUsed (some r)) h = .ok (UInt64.ofNat n, h)
78
79/-- `int inflateUndermine(z_streamp strm, int subvert)`.
80The default build refuses the extension and restores strict distance checking. -/
81def Goal.inflateUndermine : Prop :=
82  ∀ subvert, CheckedInflate (fun p => Zlib.Inflate.inflateUndermine p subvert) Z_STREAM_ERROR <|
83  ∀ h r i z s, InflateView h r i z s →
84    C.run (Zlib.Inflate.inflateUndermine (some r) subvert) h =
85      .ok (Z_DATA_ERROR, putInflate h i { s with sane := 1 })
86
87/-- `int inflateValidate(z_streamp strm, int check)`.
88Toggle validation in both current and requested wrappers; retain every other field. -/
89def Goal.inflateValidate : Prop :=
90  ∀ check, CheckedInflate (fun p => Zlib.Inflate.inflateValidate p check) Z_STREAM_ERROR <|
91  ∀ h r i z s, InflateView h r i z s →
92    C.run (Zlib.Inflate.inflateValidate (some r) check) h = .ok
93      (Z_OK, putInflate h i { s with
94        wrap := if check ≠ 0 ∧ s.wrap ≠ 0 then s.wrap ||| 4 else s.wrap &&& ~~~4
95        reqwrap := if check ≠ 0 ∧ s.reqwrap ≠ 0 then s.reqwrap ||| 4 else s.reqwrap &&& ~~~4 })
96
97/-- `int inflatePrime(z_streamp strm, int bits, int value)`.
98Negative counts clear pending bits. Counts above 16 or a total above 32 are refused.
99Otherwise append exactly the requested low bits, without allocation. -/
100def Goal.inflatePrime : Prop :=
101  ∀ bits value, CheckedInflate (fun p => Zlib.Inflate.inflatePrime p bits value) Z_STREAM_ERROR <|
102  ∀ h r i z s, InflateView h r i z s → s.bits.toNat ≤ 39 →
103    C.run (Zlib.Inflate.inflatePrime (some r) bits value) h =
104      if bits = 0 then .ok (Z_OK, h)
105      else if bits.toInt < 0 then .ok (Z_OK, putInflate h i { s with hold := 0, bits := 0 })
106      else if 16 < bits.toInt ∨ 32 < s.bits.toNat + bits.toInt.toNat then .ok (Z_STREAM_ERROR, h)
107      else .ok (Z_OK, putInflate h i { s with
108        hold := s.hold + ((value.toUInt32 &&& ((1 <<< bits.toUInt32) - 1)).toUInt64 <<< s.bits.toUInt64)
109        bits := s.bits + bits.toUInt32 })
110
111/-- `int deflatePending(z_streamp strm, unsigned *pending, int *bits)`.
112Optional output cells are independent; omitted cells remain absent. -/
113def Goal.deflatePending : Prop :=
114  ∀ pending bits, CheckedDeflate (fun p => Zlib.Deflate.deflatePending p pending bits)
115    (Z_STREAM_ERROR, none, none) <|
116  ∀ h r i z s, DeflateView h r i z s →
117    C.run (Zlib.Deflate.deflatePending (some r) pending bits) h =
118      .ok (((if pending ∧ 2 ^ 32 ≤ s.pending.toNat then Z_BUF_ERROR else Z_OK),
119        if pending then some (if 2 ^ 32 ≤ s.pending.toNat then 0xffffffff else s.pending.toUInt32) else none,
120        if bits then some s.bi_valid else none), h)
121
122/-- `int deflateUsed(z_streamp strm, int *bits)`.
123Return the modulo-eight bit-use count through the optional scalar result. -/
124def Goal.deflateUsed : Prop :=
125  ∀ bits, CheckedDeflate (fun p => Zlib.Deflate.deflateUsed p bits) (Z_STREAM_ERROR, none) <|
126  ∀ h r i z s, DeflateView h r i z s →
127    C.run (Zlib.Deflate.deflateUsed (some r) bits) h =
128      .ok ((Z_OK, if bits then some s.bi_used else none), h)
129
130/-- `int deflateTune(z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain)`.
131All signed arguments are covered. The three unsigned fields use C conversion. -/
132def Goal.deflateTune : Prop :=
133  ∀ good lazy nice chain,
134  CheckedDeflate (fun p => Zlib.Deflate.deflateTune p good lazy nice chain) Z_STREAM_ERROR <|
135  ∀ h r i z s, DeflateView h r i z s →
136    C.run (Zlib.Deflate.deflateTune (some r) good lazy nice chain) h =
137      .ok (Z_OK, putDeflate h i { s with
138        good_match := good.toUInt32
139        max_lazy_match := lazy.toUInt32
140        nice_match := nice
141        max_chain_length := chain.toUInt32 })
142
143/-- `int deflateSetHeader(z_streamp strm, gz_headerp head)`.
144Only the gzip wrapper accepts the pointer. The record is retained and read by later calls. -/
145def Goal.deflateSetHeader : Prop :=
146  ∀ head, CheckedDeflate (fun p => Zlib.Deflate.deflateSetHeader p head) Z_STREAM_ERROR <|
147  ∀ h r i z s, DeflateView h r i z s →
148    C.run (Zlib.Deflate.deflateSetHeader (some r) head) h =
149      if s.wrap = 2 then .ok (Z_OK, putDeflate h i { s with gzhead := head })
150      else .ok (Z_STREAM_ERROR, h)
151
152end ZlibF.Spec.Public
ZLIB × LEAN

Global contents

READING NOWStreamQueries.lean