Fil-C on Nix

Filnix wiki

the formal campaign

rocq/theories/BufferLogic.v

rocq/programs/buffer.c through the program logic of Logic.v.

Buffer.v proves buffer never panics by an assertion at each of its 32 points, checked one symbolic step at a time. This file proves the same theorem (buffer_never_panics) in Iris: the allocation hands the program the new object's pieces (obj), which obj_buf splits into its life and four 8-byte cells (cells); each loop is a Löb induction at the point after its head's phis, carrying the life and the cells; each check lends the life back for one step, and each access takes the one cell it reaches (cells_at). The values the cells hold play no part. Every step is taken by its rule from Logic.v, its premises discharged by Symbolic.v's tactics on the premise alone.

From iris.proofmode Require Import proofmode
From iris.base_logic.lib Require Import gen_heap
From iris.program_logic Require Import language weakestpre
From Stdlib Require Import String ZArith Lia
From Nanofil Require Import Term Syntax Values Memory Runtime Ops Semantics Run Machine Panics StepRules Symbolic Pieces Heap Language Logic Buffer
Open Scope Z_scope
Open Scope list_scope
Arguments Z.add : simpl nomatch
Arguments Z.sub : simpl nomatch
Arguments Z.mul : simpl nomatch
Arguments Z.opp : simpl nomatch

Integer arithmetic on an unknown stays folded when a premise is computed (Symbolic.v).

The blocks, computed once

Block l of buffer, or an empty one.

34Definition bblkl : string : block ≔
Someb
⇒
b
None
⇒

The entry block, which allocates the buffer.

41Definition b_start: block ≔
Eval vm_compute in bblk"start"

The fill loop's head.

43Definition b_L6: block ≔
Eval vm_compute in bblk"L6"

The fill loop's body.

45Definition b_L7: block ≔
Eval vm_compute in bblk"L7"

The sum loop's head.

47Definition b_L24: block ≔
Eval vm_compute in bblk"L24"

The sum loop's body.

49Definition b_L25: block ≔
Eval vm_compute in bblk"L25"

The exit.

51Definition b_L27: block ≔
Eval vm_compute in bblk"L27"

buffer has its entry block.

54Lemma find_start
Explore proof 2 tactics

Initial goal

vm_compute

⊢
Someb_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"v4" P Alloc16 Const32; b_jump ≔ JGotoToTAtom"L6" = Someb_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"v4" P Alloc16 Const32; b_jump ≔ JGotoToTAtom"L6"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

buffer has the fill loop's head.

57Lemma find_L6
Explore proof 2 tactics

Initial goal

vm_compute

⊢
Someb_label ≔ TAtom"L6"; b_phis ≔ PhiTAtom"pr.1" W TAtom"start", Const0; TAtom"L7", TmpTAtom"v18"; b_insts ≔ LetTAtom"v11" W CmpSlt W TmpTAtom"pr.1"; Const4; b_jump ≔ JBranchTmpTAtom"v11" ToTAtom"L7" ToTAtom"L24" = Someb_label ≔ TAtom"L6"; b_phis ≔ PhiTAtom"pr.1" W TAtom"start", Const0; TAtom"L7", TmpTAtom"v18"; b_insts ≔ LetTAtom"v11" W CmpSlt W TmpTAtom"pr.1"; Const4; b_jump ≔ JBranchTmpTAtom"v11" ToTAtom"L7" ToTAtom"L24"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

buffer has the fill loop's body.

60Lemma find_L7
Explore proof 2 tactics

Initial goal

vm_compute

⊢
Someb_label ≔ TAtom"L7"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"v14" L ExtSw TmpTAtom"pr.1"; LetTAtom"v15" L Shl TmpTAtom"v14"; Const3; FlightTAtom"v16" Add FAddressTmpTAtom"v4"; FValueTmpTAtom"v15" LowerOfTmpTAtom"v4"; LetTAtom"v18" W Add TmpTAtom"pr.1"; Const1; LetTAtom"v19" L ExtSw TmpTAtom"v18"; LetTAtom"chk0" A Check0 8 Write 1 TmpTAtom"v16"; RawStoreWl 0 TmpTAtom"v19" TmpTAtom"chk0"; b_jump ≔ JGotoPollTAtom"L6" = Someb_label ≔ TAtom"L7"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"v14" L ExtSw TmpTAtom"pr.1"; LetTAtom"v15" L Shl TmpTAtom"v14"; Const3; FlightTAtom"v16" Add FAddressTmpTAtom"v4"; FValueTmpTAtom"v15" LowerOfTmpTAtom"v4"; LetTAtom"v18" W Add TmpTAtom"pr.1"; Const1; LetTAtom"v19" L ExtSw TmpTAtom"v18"; LetTAtom"chk0" A Check0 8 Write 1 TmpTAtom"v16"; RawStoreWl 0 TmpTAtom"v19" TmpTAtom"chk0"; b_jump ≔ JGotoPollTAtom"L6"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

buffer has the sum loop's head.

63Lemma find_L24
Explore proof 2 tactics

Initial goal

vm_compute

⊢
Someb_label ≔ TAtom"L24"; b_phis ≔ PhiTAtom"pr.3" W TAtom"L25", TmpTAtom"v41"; TAtom"L6", Const0; PhiTAtom"pr.2" L TAtom"L25", TmpTAtom"v39"; TAtom"L6", Const0; b_insts ≔ LetTAtom"v30" W CmpSlt W TmpTAtom"pr.3"; TmpTAtom"v0"; b_jump ≔ JBranchTmpTAtom"v30" ToTAtom"L25" ToTAtom"L27" = Someb_label ≔ TAtom"L24"; b_phis ≔ PhiTAtom"pr.3" W TAtom"L25", TmpTAtom"v41"; TAtom"L6", Const0; PhiTAtom"pr.2" L TAtom"L25", TmpTAtom"v39"; TAtom"L6", Const0; b_insts ≔ LetTAtom"v30" W CmpSlt W TmpTAtom"pr.3"; TmpTAtom"v0"; b_jump ≔ JBranchTmpTAtom"v30" ToTAtom"L25" ToTAtom"L27"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

buffer has the sum loop's body.

66Lemma find_L25
Explore proof 2 tactics

Initial goal

vm_compute

⊢
Someb_label ≔ TAtom"L25"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"v34" W Rem TmpTAtom"pr.3"; Const4; LetTAtom"v35" L ExtSw TmpTAtom"v34"; LetTAtom"v36" L Shl TmpTAtom"v35"; Const3; FlightTAtom"v37" Add FAddressTmpTAtom"v4"; FValueTmpTAtom"v36" LowerOfTmpTAtom"v4"; LetTAtom"chk1" A Check0 8 Read 1 TmpTAtom"v37"; LetTAtom"v38" L RawLoadLdL 0 TmpTAtom"chk1"; LetTAtom"v39" L Add TmpTAtom"pr.2"; TmpTAtom"v38"; LetTAtom"v41" W Add TmpTAtom"pr.3"; Const1; b_jump ≔ JGotoPollTAtom"L24" = Someb_label ≔ TAtom"L25"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"v34" W Rem TmpTAtom"pr.3"; Const4; LetTAtom"v35" L ExtSw TmpTAtom"v34"; LetTAtom"v36" L Shl TmpTAtom"v35"; Const3; FlightTAtom"v37" Add FAddressTmpTAtom"v4"; FValueTmpTAtom"v36" LowerOfTmpTAtom"v4"; LetTAtom"chk1" A Check0 8 Read 1 TmpTAtom"v37"; LetTAtom"v38" L RawLoadLdL 0 TmpTAtom"chk1"; LetTAtom"v39" L Add TmpTAtom"pr.2"; TmpTAtom"v38"; LetTAtom"v41" W Add TmpTAtom"pr.3"; Const1; b_jump ≔ JGotoPollTAtom"L24"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

buffer has its exit.

69Lemma find_L27
Explore proof 2 tactics

Initial goal

vm_compute

⊢
Someb_label ≔ TAtom"L27"; b_phis ≔ [ ]; b_insts ≔ [ ]; b_jump ≔ JRetTmpTAtom"pr.2" = Someb_label ≔ TAtom"L27"; b_phis ≔ [ ]; b_insts ≔ [ ]; b_jump ≔ JRetTmpTAtom"pr.2"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

buffer returns a long.

72Lemma buffer_ret
Explore proof 2 tactics

Initial goal

vm_compute

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

Environments

The buffer

The buffer's region: a 32-byte live heap object at b.

80Definition buf_regb : Z : region ≔
mkRegionb b + 32 Heap Live

Taking a step

Prove an address premise: an alignment to 1 holds at once; the wraps of raw_address are dropped where arithmetic proves them the identity, then arithmetic.

87Ltac addr  ≔
unfold raw_address ; cbn [ ptr_addr ptr_cap r_end buf_reg ] ; rewrite ?Z.mod_1_r ; drop_wraps_goal ; arith

Put the facts about the blocks and the return class in the context, for the side goals of wp_enter and wp_ret.

93Ltac buf_facts  ≔

Unfold the blocks that a frame's point names.

98Ltac unfold_blocks  ≔

Prove one pure premise of a rule of Logic.v: by computation for the op's classes, by a fact for a block and a return class, by addr for an address, by compute_premise for a word, trivially for what the world interpretation must keep (there is no world), and by arithmetic for a bound.

106Ltac side  ≔
lazymatch goal with|- ∀_ : mem _ : unit, _⇒intros ; exact I|- general_op_ = true⇒reflexivity|- op_arg_classes_ _ = _⇒reflexivity|- find_block_ _ = _⇒eassumption|- fn_ret_ = _⇒eassumption|- _ ≤ max_allocation_size⇒apply Z.leb_le ; reflexivity|- ∀m : mem, _⇒intros ? ; compute_premise|- ptr_cap_ = _⇒reflexivity|- context [raw_address]⇒addr|- _ = _⇒first compute_premise | arith|- _⇒cbn [ ptr_addr ptr_cap r_end buf_reg ] ; arithend

Over any runtime

The proof over the runtime R.

124Module BufferLogic R : Runtime
125Module LG ≔ Logic R
126Module L ≔ LG.L
127Module P ≔ LG.P
Import L LG

The genv of the module, whose free is R's.

The expressions of its language.

133Notation bexpr ≔ language.exprnanofil_langno_contracts bge

The rules as tactics

A let of an op that reads no memory, by wp_let.

138Ltac wp_let_  ≔
iApply wp_let ; first side | iNext ; gen_env

A branch, by wp_branch, its target computed.

141Ltac wp_branch_  ≔
iApply wp_branch ; first side | iNext ; cbn [ edge_label Z.eqb Pos.eqb ]

Entering a block, by wp_enter, its body unfolded.

144Ltac wp_enter_  ≔
iApply wp_enter ; first side | iNext ; unfold_blocks ; gen_env

A goto, by wp_goto.

147Ltac wp_goto_  ≔
iApply wp_goto ; iNext ; unfold_blocks

A flight, by wp_flight.

150Ltac wp_flight_  ≔
iApply wp_flight ; first side | iNext ; gen_env
152Section proof
153Context `{!invGS_genhlc Σ, !gen_heapGSpiece pval Σ}

The buffer's four 8-byte cells at b, holding any values.

156Definition cellsb : Z : iPropΣ ≔
∃v0 v1 v2 v3, icellb 0 v0 ∗ icellb 8 v1 ∗ icellb 16 v2 ∗ icellb 24 v3

The cell at offset 8 k, for k from 0 to 3, can be taken from the cells and given back holding anything.

161Lemma cells_at
∀ b k
0 ≤ k < 4
cellsb −∗ ∃v, icellb 8 × k v ∗ ∀w, icellb 8 × k w −∗ cellsb
Explore proof 3 tactics

Initial goal

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
b, k :
Z
⊢
0 ≤ k < 4 → cellsb −∗ ∃v : Z, icellb 8 × k v ∗ ∀w : Z, icellb 8 × k w −∗ cellsb

intros Hk

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
b, k :
Z
Hk :
0 ≤ k < 4
⊢
cellsb −∗ ∃v : Z, icellb 8 × k v ∗ ∀w : Z, icellb 8 × k w −∗ cellsb

iIntros (%v0 & %v1 & %v2 & %v3 & H0 & H1 & H2 & H3)

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
b, k :
Z
Hk :
0 ≤ k < 4
v0, v1, v2, v3 :
Z
H0 :
icellb 0 v0
H1 :
icellb 8 v1
H2 :
icellb 16 v2
H3 :
icellb 24 v3
∗
∃v : Z, icellb 8 × k v ∗ ∀w : Z, icellb 8 × k w −∗ cellsb

assert k = 0 ∨ k = 1 ∨ k = 2 ∨ k = 3 as → | → | → | → by lia ; cbn [ Z.mul ] ; iExists v0 ; iFrame H0 | iExists v1 ; iFrame H1 | iExists v2 ; iFrame H2 | iExists v3 ; iFrame H3 ; iIntros w Hw ; rewrite / cells ; iExists _, _, _, _ ; iFrame

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros Hk
iIntros (%v0 & %v1 & %v2 & %v3 & H0 & H1 & H2 & H3)
assert k = 0 ∨ k = 1 ∨ k = 2 ∨ k = 3 as → | → | → | → by lia ; cbn [ Z.mul ] ; iExists v0 ; iFrame H0 | iExists v1 ; iFrame H1 | iExists v2 ; iFrame H2 | iExists v3 ; iFrame H3 ; iIntros w Hw ; rewrite / cells ; iExists _, _, _, _ ; iFrame

A new 32-byte object, split into its life and its four cells, which hold zero; the aux slots are dropped.

172Lemma obj_buf
∀ base
objbase heap_req16 32 −∗ livebase buf_regbase ∗ cellsbase
Explore proof 7 tactics

Initial goal

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
base :
Z
⊢
objbase heap_req16 32 −∗ livebase buf_regbase ∗ cellsbase

rewrite / obj / live / cells / icell

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
base :
Z
⊢
ptsobj_psbase heap_req16 32 −∗ ptsPLivebase, VLivebuf_regbase ∗ ∃v0 v1 v2 v3 : Z, ptscellbase 0 v0 ∗ ptscellbase 8 v1 ∗ ptscellbase 16 v2 ∗ ptscellbase 24 v3

assert E : obj_psbase heap_req16 32 = PLivebase, VLivebuf_regbase ++ cellbase 0 0 ++ cellbase 8 0 ++ cellbase 16 0 ++ cellbase 24 0 ++ λi ⇒ PAuxbase i, VAuxCNone <$> seqZ0 32 by reflexivity

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
base :
Z
E :
obj_psbase heap_req16 32 = PLivebase, VLivebuf_regbase ++ cellbase 0 0 ++ cellbase 8 0 ++ cellbase 16 0 ++ cellbase 24 0 ++ λi : Z ⇒ PAuxbase i, VAuxCNone <$> seqZ0 32
⊢
ptsobj_psbase heap_req16 32 −∗ ptsPLivebase, VLivebuf_regbase ∗ ∃v0 v1 v2 v3 : Z, ptscellbase 0 v0 ∗ ptscellbase 8 v1 ∗ ptscellbase 16 v2 ∗ ptscellbase 24 v3

rewrite E ! pts_app

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
base :
Z
E :
obj_psbase heap_req16 32 = PLivebase, VLivebuf_regbase ++ cellbase 0 0 ++ cellbase 8 0 ++ cellbase 16 0 ++ cellbase 24 0 ++ λi : Z ⇒ PAuxbase i, VAuxCNone <$> seqZ0 32
⊢
ptsPLivebase, VLivebuf_regbase ∗ ptscellbase 0 0 ∗ ptscellbase 8 0 ∗ ptscellbase 16 0 ∗ ptscellbase 24 0 ∗ ptsλi : Z ⇒ PAuxbase i, VAuxCNone <$> seqZ0 32 −∗ ptsPLivebase, VLivebuf_regbase ∗ ∃v0 v1 v2 v3 : Z, ptscellbase 0 v0 ∗ ptscellbase 8 v1 ∗ ptscellbase 16 v2 ∗ ptscellbase 24 v3

iIntros (Hl & H0 & H8 & H16 & H24 & _)

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
base :
Z
E :
obj_psbase heap_req16 32 = PLivebase, VLivebuf_regbase ++ cellbase 0 0 ++ cellbase 8 0 ++ cellbase 16 0 ++ cellbase 24 0 ++ λi : Z ⇒ PAuxbase i, VAuxCNone <$> seqZ0 32
Hl :
H0 :
ptscellbase 0 0
H8 :
ptscellbase 8 0
H16 :
ptscellbase 16 0
H24 :
ptscellbase 24 0
∗
ptsPLivebase, VLivebuf_regbase ∗ ∃v0 v1 v2 v3 : Z, ptscellbase 0 v0 ∗ ptscellbase 8 v1 ∗ ptscellbase 16 v2 ∗ ptscellbase 24 v3

iFrame Hl

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
base :
Z
E :
obj_psbase heap_req16 32 = PLivebase, VLivebuf_regbase ++ cellbase 0 0 ++ cellbase 8 0 ++ cellbase 16 0 ++ cellbase 24 0 ++ λi : Z ⇒ PAuxbase i, VAuxCNone <$> seqZ0 32
H0 :
ptscellbase 0 0
H8 :
ptscellbase 8 0
H16 :
ptscellbase 16 0
H24 :
ptscellbase 24 0
∗
∃v0 v1 v2 v3 : Z, ptscellbase 0 v0 ∗ ptscellbase 8 v1 ∗ ptscellbase 16 v2 ∗ ptscellbase 24 v3

iExists 0, 0, 0, 0

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
base :
Z
E :
obj_psbase heap_req16 32 = PLivebase, VLivebuf_regbase ++ cellbase 0 0 ++ cellbase 8 0 ++ cellbase 16 0 ++ cellbase 24 0 ++ λi : Z ⇒ PAuxbase i, VAuxCNone <$> seqZ0 32
H0 :
ptscellbase 0 0
H8 :
ptscellbase 8 0
H16 :
ptscellbase 16 0
H24 :
ptscellbase 24 0
∗
ptscellbase 0 0 ∗ ptscellbase 8 0 ∗ ptscellbase 16 0 ∗ ptscellbase 24 0

iFrame

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
rewrite / obj / live / cells / icell
assert E : obj_psbase heap_req16 32 = PLivebase, VLivebuf_regbase ++ cellbase 0 0 ++ cellbase 8 0 ++ cellbase 16 0 ++ cellbase 24 0 ++ λi ⇒ PAuxbase i, VAuxCNone <$> seqZ0 32 by reflexivity
rewrite E ! pts_app
iIntros (Hl & H0 & H8 & H16 & H24 & _)
iFrame Hl
iExists 0, 0, 0, 0
iFrame

What both loops know of the environment e: v4 holds the buffer's own pointer, its base b positive, 16-aligned and ending within the address space.

186Definition holdse : env b : Z : Prop ≔
lookupTAtom"v4" e = SomeWPtrmkPtrb Objb ∧ 0 < b ∧ b mod 16 = 0 ∧ b + 32 ≤ 2 ^ 48

The sum loop, from the point after its head's phis: with pr.3 an int j from 0 below 2^31, pr.2 any long, v0 the input n, owning the buffer, the run is safe. By Löb induction; each iteration reads the cell j mod 4.

194Lemma sum_loop
∀ n b
⊢ ∀e j s, ⌜holdse b ∧ lookupTAtom"pr.3" e = SomeWIntj ∧ 0 ≤ j < 2 ^ 31 ∧ lookupTAtom"pr.2" e = SomeWInts ∧ lookupTAtom"v0" e = SomeWIntn⌝ −∗ liveb buf_regb −∗ cellsb −∗ WPERunmkFramebuffer_fn e [ ] None ExecTAtom"L24" b_instsb_L24 b_jumpb_L24 : bexpr {_. True}
Proof 29 steps Qed
iLöb as IH
iIntros e j s Hv4 & Hb0 & Hb1 & Hb2 & Hj & Hjr & Hs & Hn Hlv Hc
match goal withH : lookupTAtom"v30" _ = SomeWIntif ?c then 1 else 0 |- _⇒destruct c eqn: Hcend
–assert Hj1 : j + 1 < 2 ^ 31
{apply Z.ltb_lt in Hc
revert Hc
destruct 2 ^ 31 ≤? n mod 2 ^ 32 eqn: Hsg ; apply Z.leb_le in Hsg | apply Z.leb_gt in Hsg ; intros ; pose proof Z.mod_pos_boundn 2 ^ 32 ltac:lia ; lia
iDestruct cells_atb j mod 4 with Hc as v [Hv Hc] ; apply Z.mod_pos_bound ; lia |
iApply wp_check with Hlv ; first side | iNext ; iIntros Hlv ; gen_env
iApply wp_raw_load with Hlv Hv ; first side | iNext ; iIntros Hlv Hv ; gen_env
iSpecialize Hc with Hv
iApply IH $! _ j + 1 with [%] Hlv Hc
repeat split ; try eassumption ; lia
iApply wp_ret ; first side | done

The fill loop, from the point after its head's phi: with pr.1 an int i from 0 to 4 and v0 the input n, owning the buffer, the run is safe. By Löb induction; each iteration writes the cell i; when i reaches 4 the sum loop starts with j and the sum 0.

228Lemma fill_loop
∀ n b
⊢ ∀e i, ⌜holdse b ∧ lookupTAtom"pr.1" e = SomeWInti ∧ 0 ≤ i ≤ 4 ∧ lookupTAtom"v0" e = SomeWIntn⌝ −∗ liveb buf_regb −∗ cellsb −∗ WPERunmkFramebuffer_fn e [ ] None ExecTAtom"L6" b_instsb_L6 b_jumpb_L6 : bexpr {_. True}
Proof 27 steps Qed
iLöb as IH
iIntros e i Hv4 & Hb0 & Hb1 & Hb2 & Hi & Hir & Hn Hlv Hc
match goal withH : lookupTAtom"v11" _ = SomeWIntif ?c then 1 else 0 |- _⇒destruct c eqn: Hcend
–assert Hi4 : i < 4 by apply Z.ltb_lt in Hc ; lia
iDestruct cells_atb i with Hc as v [Hv Hc] ; lia |
iApply wp_check with Hlv ; first side | iNext ; iIntros Hlv ; gen_env
iApply wp_raw_store with Hlv Hv ; first side | iNext ; iIntros Hlv Hv ; gen_env
iSpecialize Hc with Hv
iApply IH $! _ i + 1 with [%] Hlv Hc
repeat split ; try eassumption ; lia
–assert Hi4 : i = 4 by apply Z.ltb_ge in Hc ; lia
iApply sum_loopn b $! _ 0 0 with [%] Hlv Hc
repeat split ; try eassumption ; lia

buffer called with the int n is safe.

258Lemma buffer_spec
∀ n
⊢ WPERunmkFramebuffer_fn TAtom"v0", WIntn [ ] None EnterTAtom"start" None : bexpr {_. True}
Explore proof 10 tactics

Initial goal

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
n :
Z
⊢
⊢ WPERunfr_fn ≔ buffer_fn; fr_env ≔ TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ EnterTAtom"start" None : bexpr {_. True}

buf_facts

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
n :
Z
⊢
⊢ WPERunfr_fn ≔ buffer_fn; fr_env ≔ TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ EnterTAtom"start" None : bexpr {_. True}

wp_enter_

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
n :
Z
∗
WPL.ERunfr_fn ≔ buffer_fn; fr_env ≔ TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" LetTAtom"v4" P Alloc16 Const32 JGotoToTAtom"L6" {_. True}

iApply wp_alloc ; first side | iNext ; iIntros base Hb0 & Hb1 & Hb2 Hobj ; gen_env

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
n :
Z
base :
Z
Hb0 :
0 < base
Hb1 :
base mod req_alignheap_req16 32 = 0
Hb2 :
base + req_extentheap_req16 32 ≤ 2 ^ 48
Hobj :
objbase heap_req16 32
∗
WPL.ERunfr_fn ≔ buffer_fn; fr_env ≔ putTAtom"v4" WPtrptr_addr ≔ base; ptr_cap ≔ Objbase TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6" {_. True}

change req_alignheap_req16 32 with 16 in Hb1

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
n :
Z
base :
Z
Hb0 :
0 < base
Hb1 :
base mod 16 = 0
Hb2 :
base + req_extentheap_req16 32 ≤ 2 ^ 48
Hobj :
objbase heap_req16 32
∗
WPL.ERunfr_fn ≔ buffer_fn; fr_env ≔ putTAtom"v4" WPtrptr_addr ≔ base; ptr_cap ≔ Objbase TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6" {_. True}

change req_extentheap_req16 32 with 32 in Hb2

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
n :
Z
base :
Z
Hb0 :
0 < base
Hb1 :
base mod 16 = 0
Hb2 :
base + 32 ≤ 2 ^ 48
Hobj :
objbase heap_req16 32
∗
WPL.ERunfr_fn ≔ buffer_fn; fr_env ≔ putTAtom"v4" WPtrptr_addr ≔ base; ptr_cap ≔ Objbase TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6" {_. True}

iDestruct obj_buf with Hobj as [Hlv Hc]

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
n :
Z
base :
Z
Hb0 :
0 < base
Hb1 :
base mod 16 = 0
Hb2 :
base + 32 ≤ 2 ^ 48
Hlv :
livebase buf_regbase
Hc :
cellsbase
∗
WPL.ERunfr_fn ≔ buffer_fn; fr_env ≔ putTAtom"v4" WPtrptr_addr ≔ base; ptr_cap ≔ Objbase TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6" {_. True}

wp_goto_

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
n :
Z
base :
Z
Hb0 :
0 < base
Hb1 :
base mod 16 = 0
Hb2 :
base + 32 ≤ 2 ^ 48
Hlv :
livebase buf_regbase
Hc :
cellsbase
∗
WPL.ERunfr_fn ≔ buffer_fn; fr_env ≔ putTAtom"v4" WPtrptr_addr ≔ base; ptr_cap ≔ Objbase TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ EnterTAtom"L6" SomeTAtom"start" {_. True}

wp_enter_

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
n :
Z
base :
Z
Hb0 :
0 < base
Hb1 :
base mod 16 = 0
Hb2 :
base + 32 ≤ 2 ^ 48
Hlv :
livebase buf_regbase
Hc :
cellsbase
∗
WPL.ERunfr_fn ≔ buffer_fn; fr_env ≔ putTAtom"pr.1" WInt0 putTAtom"v4" WPtrptr_addr ≔ base; ptr_cap ≔ Objbase TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"L6" LetTAtom"v11" W CmpSlt W TmpTAtom"pr.1"; Const4 JBranchTmpTAtom"v11" ToTAtom"L7" ToTAtom"L24" {_. True}

iApply fill_loopn base $! _ 0 with [%] Hlv Hc

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
n :
Z
base :
Z
Hb0 :
0 < base
Hb1 :
base mod 16 = 0
Hb2 :
base + 32 ≤ 2 ^ 48
⊢
holdsputTAtom"pr.1" WInt0 putTAtom"v4" WPtrptr_addr ≔ base; ptr_cap ≔ Objbase TAtom"v0", WIntn base ∧ lookupTAtom"pr.1" putTAtom"pr.1" WInt0 putTAtom"v4" WPtrptr_addr ≔ base; ptr_cap ≔ Objbase TAtom"v0", WIntn = SomeWInt0 ∧ 0 ≤ 0 ≤ 4 ∧ lookupTAtom"v0" putTAtom"pr.1" WInt0 putTAtom"v4" WPtrptr_addr ≔ base; ptr_cap ≔ Objbase TAtom"v0", WIntn = SomeWIntn

repeat split ; try eassumption ; lia

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
iApply wp_alloc ; first side | iNext ; iIntros base Hb0 & Hb1 & Hb2 Hobj ; gen_env
change req_alignheap_req16 32 with 16 in Hb1
change req_extentheap_req16 32 with 32 in Hb2
iDestruct obj_buf with Hobj as [Hlv Hc]
iApply fill_loopn base $! _ 0 with [%] Hlv Hc
repeat split ; try eassumption ; lia

The resources the proof uses: invariants and the ghost heap.

275Definition bufΣ: gFunctors ≔
#invΣ; gen_heapΣpiece pval

bufΣ has invariants.

278Instance bufΣ_inv: invGpreSbufΣ
Explore proof 2 tactics

Initial goal

⊢
invGpreSbufΣ

apply subG_invΣ

⊢
subGinvΣ bufΣ

apply _

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
apply subG_invΣ
apply _

bufΣ has the ghost heap of pieces.

282Instance bufΣ_heap: gen_heapGpreSpiece pval bufΣ
Explore proof 2 tactics

Initial goal

⊢
gen_heapGpreSpiece pval bufΣ

apply subG_gen_heapGpreS

⊢
subGgen_heapΣpiece pval bufΣ

apply _

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
apply subG_gen_heapGpreS
apply _

buffer never panics: for every input whose first word is an int, with any fuel, no state of its run fails, whatever base its buffer gets. Proved by Iris adequacy (heap_never_panics) from buffer_spec.

289Theorem buffer_never_panics
P.never_panicsbuffer_module TAtom"buffer" λxs ⇒ ∃n rest, xs = WIntn :: rest
Explore proof 11 tactics

Initial goal

⊢
P.never_panicsbuffer_module TAtom"buffer" λxs : listword ⇒ ∃n : Z rest : listword, xs = WIntn :: rest

apply heap_never_panicsbufΣ buffer_module TAtom"buffer" _ buffer_globals buffer_mem buffer_fn

4 open

focused goal
⊢
find_fnbge TAtom"buffer" = SomeDefinedbuffer_fn
focused goal
focused goal
⊢
∀xs : listword, ∃n : Z rest : listword, xs = WIntn :: rest → ∃fr : frame, call_framebuffer_fn xs = Somefr ∧ ∀HinvG : invGS_genHasNoLc bufΣ HheapG : gen_heapGSpiece pval bufΣ, ⊢ WPL.ERunfr {_. True}

–exact buffer_initial

3 open

deferred goal
⊢
find_fnbge TAtom"buffer" = SomeDefinedbuffer_fn
deferred goal
deferred goal
⊢
∀xs : listword, ∃n : Z rest : listword, xs = WIntn :: rest → ∃fr : frame, call_framebuffer_fn xs = Somefr ∧ ∀HinvG : invGS_genHasNoLc bufΣ HheapG : gen_heapGSpiece pval bufΣ, ⊢ WPL.ERunfr {_. True}

–exact buffer_findR.free

2 open

deferred goal
deferred goal
⊢
∀xs : listword, ∃n : Z rest : listword, xs = WIntn :: rest → ∃fr : frame, call_framebuffer_fn xs = Somefr ∧ ∀HinvG : invGS_genHasNoLc bufΣ HheapG : gen_heapGSpiece pval bufΣ, ⊢ WPL.ERunfr {_. True}

–intros b1 r1 b2 r2 E _

2 open

b1 :
Z
r1 :
b2 :
Z
r2 :
⊢
live_atbuffer_mem b2 r2 → b1 ≠ b2 → r_endr1 ≤ b2 ∨ r_endr2 ≤ b1
deferred goal
⊢
∀xs : listword, ∃n : Z rest : listword, xs = WIntn :: rest → ∃fr : frame, call_framebuffer_fn xs = Somefr ∧ ∀HinvG : invGS_genHasNoLc bufΣ HheapG : gen_heapGSpiece pval bufΣ, ⊢ WPL.ERunfr {_. True}

vm_compute in E

2 open

b1 :
Z
r1 :
b2 :
Z
r2 :
E :
None = Somer1
⊢
live_atbuffer_mem b2 r2 → b1 ≠ b2 → r_endr1 ≤ b2 ∨ r_endr2 ≤ b1
deferred goal
⊢
∀xs : listword, ∃n : Z rest : listword, xs = WIntn :: rest → ∃fr : frame, call_framebuffer_fn xs = Somefr ∧ ∀HinvG : invGS_genHasNoLc bufΣ HheapG : gen_heapGSpiece pval bufΣ, ⊢ WPL.ERunfr {_. True}

discriminate E

deferred goal
⊢
∀xs : listword, ∃n : Z rest : listword, xs = WIntn :: rest → ∃fr : frame, call_framebuffer_fn xs = Somefr ∧ ∀HinvG : invGS_genHasNoLc bufΣ HheapG : gen_heapGSpiece pval bufΣ, ⊢ WPL.ERunfr {_. True}

–intros xs n & rest & →

n :
Z
rest :
listword
⊢
∃fr : frame, call_framebuffer_fn WIntn :: rest = Somefr ∧ ∀HinvG : invGS_genHasNoLc bufΣ HheapG : gen_heapGSpiece pval bufΣ, ⊢ WPL.ERunfr {_. True}

eexists

2 open

n :
Z
rest :
listword
⊢
call_framebuffer_fn WIntn :: rest = Some?fr ∧ ∀HinvG : invGS_genHasNoLc bufΣ HheapG : gen_heapGSpiece pval bufΣ, ⊢ WPL.ERun?fr {_. True}
shelved goal
n :
Z
rest :
listword

split ; apply buffer_call_frame |

n :
Z
rest :
listword
⊢
∀HinvG : invGS_genHasNoLc bufΣ HheapG : gen_heapGSpiece pval bufΣ, ⊢ WPL.ERunfr_fn ≔ buffer_fn; fr_env ≔ TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ EnterTAtom"start" None {_. True}

intros HinvG HheapG

n :
Z
rest :
listword
HinvG :
invGS_genHasNoLc bufΣ
HheapG :
gen_heapGSpiece pval bufΣ
⊢
⊢ WPL.ERunfr_fn ≔ buffer_fn; fr_env ≔ TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ EnterTAtom"start" None {_. True}

apply buffer_spec

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
apply heap_never_panicsbufΣ buffer_module TAtom"buffer" _ buffer_globals buffer_mem buffer_fn
–exact buffer_findR.free
–intros b1 r1 b2 r2 E _
vm_compute in E
discriminate E
–intros xs n & rest & →
eexists
split ; apply buffer_call_frame |
intros HinvG HheapG

The theorem for the interpreter's runtime.

303Module InterpBufferLogic ≔ BufferLogic InterpRuntime

buffer.c never panics under the interpreter's runtime, by the program logic.

307Theorem interp_buffer_never_panics_logic
InterpBufferLogic.P.never_panicsbuffer_module TAtom"buffer" λxs ⇒ ∃n rest, xs = WIntn :: rest
Explore proof 1 tactics

Initial goal

⊢
InterpBufferLogic.P.never_panicsbuffer_module TAtom"buffer" λxs : listword ⇒ ∃n : Z rest : listword, xs = WIntn :: rest

exact InterpBufferLogic.buffer_never_panics

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script