Fil-C on Nix

Filnix wiki

the formal campaign

rocq/theories/CountLogic.v

rocq/programs/count.c through the program logic of Logic.v: a helper with its own specification, called in a loop, with memory read after each call.

next_l is strchr for l. Its triple (next_l_spec) is proved once, from wp_strchr, and count_l uses it at both of its calls through wp_call_bind: once on the whole string, then in the loop on the suffix just past each hit, which the string lends (string_suffix) and takes back after the call. The loop is a Löb induction at the point after its head's phis (count_loop): it owns the string, and the pointer it holds is null or a hit before the NUL (found_from). Each iteration reads the byte the pointer lands on through the string's capability (wp_check_read, wp_raw_load_byte), so the read comes after a call and depends on the callee's postcondition: a hit is before the NUL, because l is not 0.

count_logic_safe is the labelled machine's safety from any memory holding the string; interp_count_logic_safe instantiates it on Hi.v's fixture, whose literal "hello" has two ls.

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 ZArith Lia
From Stdlib Require String
From Nanofil Require Import Term Syntax Values Memory Runtime Ops Semantics Run Machine Panics StepRules Symbolic ExternalCalls ExternalMachine Transport Pieces Heap ContractFrame Language Logic StringLogic CountCode Hi HiLogic
Open Scope Z_scope
Open Scope list_scope
Arguments Z.add : simpl nomatch
Arguments Z.sub : simpl nomatch
Arguments Z.mul : simpl nomatch

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

The module

The checked module nanofil makes of count.c (count_term).

42Definition count_module: module ≔
Somemd
⇒
md
None
⇒
[ ]

The fixture decodes to count_module.

46Lemma count_decodes
Explore proof 2 tactics

Initial goal

vm_compute

⊢
SomeIFuncfn_name ≔ TAtom"next_l"; fn_linkage ≔ TAtom"export"; fn_ret ≔ RClassP; fn_params ≔ P, TAtom"v0"; fn_blocks ≔ b_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ CallCResultTAtom"v3" P GlobalTAtom"strchr" ArgP TmpTAtom"v0"; ArgW Const108; b_jump ≔ JRetTmpTAtom"v3"; IFuncfn_name ≔ TAtom"count_l"; fn_linkage ≔ TAtom"export"; fn_ret ≔ RClassW; fn_params ≔ P, TAtom"v0"; fn_blocks ≔ b_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ CallCResultTAtom"v5" P GlobalTAtom"next_l" ArgP TmpTAtom"v0"; b_jump ≔ JGotoToTAtom"L6"; b_label ≔ TAtom"L6"; b_phis ≔ PhiTAtom"pr.2" P TAtom"L7", TmpTAtom"v21"; TAtom"start", TmpTAtom"v5"; PhiTAtom"pr.1" W TAtom"L7", TmpTAtom"v18"; TAtom"start", Const0; b_insts ≔ LetTAtom"v11" L Ptoi TmpTAtom"pr.2"; LetTAtom"v12" W CmpNe L TmpTAtom"v11"; Const0; b_jump ≔ JBranchTmpTAtom"v12" ToTAtom"L7" ToTAtom"L9"; b_label ≔ TAtom"L7"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"chk0" A Check0 1 Read 1 TmpTAtom"pr.2"; LetTAtom"v16" W RawLoadLdNarrowSb 0 TmpTAtom"chk0"; LetTAtom"v17" W CmpEq W TmpTAtom"v16"; Const108; LetTAtom"v18" W Add TmpTAtom"pr.1"; TmpTAtom"v17"; FlightTAtom"v20" Add FAddressTmpTAtom"pr.2"; FValueConst1 LowerOfTmpTAtom"pr.2"; CallCResultTAtom"v21" P GlobalTAtom"next_l" ArgP TmpTAtom"v20"; b_jump ≔ JGotoPollTAtom"L6"; b_label ≔ TAtom"L9"; b_phis ≔ [ ]; b_insts ≔ [ ]; b_jump ≔ JRetTmpTAtom"pr.1" = SomeIFuncfn_name ≔ TAtom"next_l"; fn_linkage ≔ TAtom"export"; fn_ret ≔ RClassP; fn_params ≔ P, TAtom"v0"; fn_blocks ≔ b_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ CallCResultTAtom"v3" P GlobalTAtom"strchr" ArgP TmpTAtom"v0"; ArgW Const108; b_jump ≔ JRetTmpTAtom"v3"; IFuncfn_name ≔ TAtom"count_l"; fn_linkage ≔ TAtom"export"; fn_ret ≔ RClassW; fn_params ≔ P, TAtom"v0"; fn_blocks ≔ b_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ CallCResultTAtom"v5" P GlobalTAtom"next_l" ArgP TmpTAtom"v0"; b_jump ≔ JGotoToTAtom"L6"; b_label ≔ TAtom"L6"; b_phis ≔ PhiTAtom"pr.2" P TAtom"L7", TmpTAtom"v21"; TAtom"start", TmpTAtom"v5"; PhiTAtom"pr.1" W TAtom"L7", TmpTAtom"v18"; TAtom"start", Const0; b_insts ≔ LetTAtom"v11" L Ptoi TmpTAtom"pr.2"; LetTAtom"v12" W CmpNe L TmpTAtom"v11"; Const0; b_jump ≔ JBranchTmpTAtom"v12" ToTAtom"L7" ToTAtom"L9"; b_label ≔ TAtom"L7"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"chk0" A Check0 1 Read 1 TmpTAtom"pr.2"; LetTAtom"v16" W RawLoadLdNarrowSb 0 TmpTAtom"chk0"; LetTAtom"v17" W CmpEq W TmpTAtom"v16"; Const108; LetTAtom"v18" W Add TmpTAtom"pr.1"; TmpTAtom"v17"; FlightTAtom"v20" Add FAddressTmpTAtom"pr.2"; FValueConst1 LowerOfTmpTAtom"pr.2"; CallCResultTAtom"v21" P GlobalTAtom"next_l" ArgP TmpTAtom"v20"; b_jump ≔ JGotoPollTAtom"L6"; b_label ≔ TAtom"L9"; b_phis ≔ [ ]; b_insts ≔ [ ]; b_jump ≔ JRetTmpTAtom"pr.1"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

The module's i-th function, or an empty one.

50Definition count_nthi : nat : func ≔
match nth_errorcount_module i with
SomeIFuncf
⇒
f
_
⇒
mkFuncTAtom"none" TAtom"export" RVoid [ ] [ ]

next_l: strchr for l.

57Definition next_l_fn: func ≔
Eval vm_compute in count_nth0

count_l: the loop.

59Definition count_fn: func ≔
Eval vm_compute in count_nth1

The module's symbols.

62Definition count_globals: listname × ptr ≔
TAtom"count_l", mkPtr65552 FnTAtom"count_l"; TAtom"next_l", mkPtr65536 FnTAtom"next_l"

Laying out the module gives count_globals.

67Lemma count_layout
Explore proof 2 tactics

Initial goal

vm_compute

⊢
SomeTAtom"count_l", ptr_addr ≔ 65552; ptr_cap ≔ FnTAtom"count_l"; TAtom"next_l", ptr_addr ≔ 65536; ptr_cap ≔ FnTAtom"next_l" = SomeTAtom"count_l", ptr_addr ≔ 65552; ptr_cap ≔ FnTAtom"count_l"; TAtom"next_l", ptr_addr ≔ 65536; ptr_cap ≔ FnTAtom"next_l"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

Block l of f, or an empty one.

71Definition cblkf : func l : String.string : block ≔
Someb
⇒
b
None
⇒

next_l's one block: strchr, then return its result.

78Definition n_start: block ≔
Eval vm_compute in cblknext_l_fn "start"

count_l's entry: the first call of next_l.

80Definition c_start: block ≔
Eval vm_compute in cblkcount_fn "start"

The loop's head: is the pointer null?

82Definition c_L6: block ≔
Eval vm_compute in cblkcount_fn "L6"

The loop's body: read the byte, count it, call next_l past it.

84Definition c_L7: block ≔
Eval vm_compute in cblkcount_fn "L7"

The exit: return the count.

86Definition c_L9: block ≔
Eval vm_compute in cblkcount_fn "L9"

next_l has its block.

89Lemma find_n_start
Explore proof 2 tactics

Initial goal

vm_compute

⊢
Someb_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ CallCResultTAtom"v3" P GlobalTAtom"strchr" ArgP TmpTAtom"v0"; ArgW Const108; b_jump ≔ JRetTmpTAtom"v3" = Someb_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ CallCResultTAtom"v3" P GlobalTAtom"strchr" ArgP TmpTAtom"v0"; ArgW Const108; b_jump ≔ JRetTmpTAtom"v3"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

count_l has its entry.

92Lemma find_c_start
Explore proof 2 tactics

Initial goal

vm_compute

⊢
Someb_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ CallCResultTAtom"v5" P GlobalTAtom"next_l" ArgP TmpTAtom"v0"; b_jump ≔ JGotoToTAtom"L6" = Someb_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ CallCResultTAtom"v5" P GlobalTAtom"next_l" ArgP TmpTAtom"v0"; b_jump ≔ JGotoToTAtom"L6"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

count_l has the loop's head.

95Lemma find_c_L6
Explore proof 2 tactics

Initial goal

vm_compute

⊢
Someb_label ≔ TAtom"L6"; b_phis ≔ PhiTAtom"pr.2" P TAtom"L7", TmpTAtom"v21"; TAtom"start", TmpTAtom"v5"; PhiTAtom"pr.1" W TAtom"L7", TmpTAtom"v18"; TAtom"start", Const0; b_insts ≔ LetTAtom"v11" L Ptoi TmpTAtom"pr.2"; LetTAtom"v12" W CmpNe L TmpTAtom"v11"; Const0; b_jump ≔ JBranchTmpTAtom"v12" ToTAtom"L7" ToTAtom"L9" = Someb_label ≔ TAtom"L6"; b_phis ≔ PhiTAtom"pr.2" P TAtom"L7", TmpTAtom"v21"; TAtom"start", TmpTAtom"v5"; PhiTAtom"pr.1" W TAtom"L7", TmpTAtom"v18"; TAtom"start", Const0; b_insts ≔ LetTAtom"v11" L Ptoi TmpTAtom"pr.2"; LetTAtom"v12" W CmpNe L TmpTAtom"v11"; Const0; b_jump ≔ JBranchTmpTAtom"v12" ToTAtom"L7" ToTAtom"L9"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

count_l has the loop's body.

98Lemma find_c_L7
Explore proof 2 tactics

Initial goal

vm_compute

⊢
Someb_label ≔ TAtom"L7"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"chk0" A Check0 1 Read 1 TmpTAtom"pr.2"; LetTAtom"v16" W RawLoadLdNarrowSb 0 TmpTAtom"chk0"; LetTAtom"v17" W CmpEq W TmpTAtom"v16"; Const108; LetTAtom"v18" W Add TmpTAtom"pr.1"; TmpTAtom"v17"; FlightTAtom"v20" Add FAddressTmpTAtom"pr.2"; FValueConst1 LowerOfTmpTAtom"pr.2"; CallCResultTAtom"v21" P GlobalTAtom"next_l" ArgP TmpTAtom"v20"; b_jump ≔ JGotoPollTAtom"L6" = Someb_label ≔ TAtom"L7"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"chk0" A Check0 1 Read 1 TmpTAtom"pr.2"; LetTAtom"v16" W RawLoadLdNarrowSb 0 TmpTAtom"chk0"; LetTAtom"v17" W CmpEq W TmpTAtom"v16"; Const108; LetTAtom"v18" W Add TmpTAtom"pr.1"; TmpTAtom"v17"; FlightTAtom"v20" Add FAddressTmpTAtom"pr.2"; FValueConst1 LowerOfTmpTAtom"pr.2"; CallCResultTAtom"v21" P GlobalTAtom"next_l" ArgP TmpTAtom"v20"; b_jump ≔ JGotoPollTAtom"L6"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

count_l has the exit.

101Lemma find_c_L9
Explore proof 2 tactics

Initial goal

vm_compute

⊢
Someb_label ≔ TAtom"L9"; b_phis ≔ [ ]; b_insts ≔ [ ]; b_jump ≔ JRetTmpTAtom"pr.1" = Someb_label ≔ TAtom"L9"; b_phis ≔ [ ]; b_insts ≔ [ ]; b_jump ≔ JRetTmpTAtom"pr.1"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

A function called with the pointer p, at its entry.

105Definition entryf : func p : ptr : frame ≔
mkFramef TAtom"v0", WPtrp [ ] None EnterTAtom"start" None

count_l's contracts: strchr's alone, over no world.

109Definition count_registrysymbol : name : optioncontractunit ≔
name_eqbsymbol TAtom"strchr"
→
else
None

What the loop holds

The pointer q, for the string p with contents bytes, is null or points into it before its NUL, with its capability.

116Definition found_fromp : ptr bytes : listZ q : ptr : Prop ≔
q = mkPtr0 CNone ∨ ∃j, j < lengthbytes%nat ∧ q = mkPtrptr_addrp + Z.of_natj ptr_capp

Prove an address premise: drop the wraps of raw_address and of a flight's sum where arithmetic shows them the identity, then arithmetic.

123Ltac addr_premise  ≔

Prove a premise that names words: by computation, with the environment's facts.

127Ltac word_premise  ≔
first reflexivity | compute_premise

count.c over any runtime R.

130Module CountLogic R : Runtime
131Module SL ≔ StringLogic R
132Module LG ≔ SL.LG
133Module L ≔ LG.L
Import L LG SL

What strchr finds of a nonzero byte is null or before the NUL.

137Lemma found_first
∀ p bytes c q
strchr_foundp bytes c q
found_fromp bytes q
Explore proof 3 tactics

Initial goal

p :
bytes :
listZ
c :
Z
q :
⊢
strchr_foundp bytes c q → found_fromp bytes q

intros i & x & Hx & _ & _ & → | _ & → ; right | left ; reflexivity

p :
bytes :
listZ
c :
Z
i :
nat
x :
Z
Hx :
bytes !! i = Somex
⊢
∃j : nat, j < lengthbytes%nat ∧ ptr_addr ≔ ptr_addrp + i; ptr_cap ≔ ptr_capp = ptr_addr ≔ ptr_addrp + j; ptr_cap ≔ ptr_capp

exists i

p :
bytes :
listZ
c :
Z
i :
nat
x :
Z
Hx :
bytes !! i = Somex
⊢
i < lengthbytes%nat ∧ ptr_addr ≔ ptr_addrp + i; ptr_cap ≔ ptr_capp = ptr_addr ≔ ptr_addrp + i; ptr_cap ≔ ptr_capp

split ; exact lookup_lt_Some_ _ _ Hx | reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros i & x & Hx & _ & _ & → | _ & → ; right | left ; reflexivity
exists i
split ; exact lookup_lt_Some_ _ _ Hx | reflexivity

What strchr finds in the suffix just past the j-th byte of the string, before its NUL, is null or before the string's NUL.

145Lemma found_next
∀ p bytes c q j
j < lengthbytes%nat
strchr_foundmkPtrptr_addrp + Z.of_natSj ptr_capp dropSj bytes c q
found_fromp bytes q
Explore proof 7 tactics

Initial goal

p :
bytes :
listZ
c :
Z
q :
j :
nat
⊢
j < lengthbytes%nat → strchr_foundptr_addr ≔ ptr_addrp + Sj; ptr_cap ≔ ptr_capp dropSj bytes c q → found_fromp bytes q

intros Hj i & x & Hx & _ & _ & → | _ & → ; right | left ; reflexivity

p :
bytes :
listZ
c :
Z
j :
nat
Hj :
j < lengthbytes%nat
i :
nat
x :
Z
Hx :
dropSj bytes !! i = Somex
⊢
∃j0 : nat, j0 < lengthbytes%nat ∧ ptr_addr ≔ ptr_addrptr_addr ≔ ptr_addrp + Sj; ptr_cap ≔ ptr_capp + i; ptr_cap ≔ ptr_capptr_addr ≔ ptr_addrp + Sj; ptr_cap ≔ ptr_capp = ptr_addr ≔ ptr_addrp + j0; ptr_cap ≔ ptr_capp

rewrite lookup_drop in Hx

p :
bytes :
listZ
c :
Z
j :
nat
Hj :
j < lengthbytes%nat
i :
nat
x :
Z
Hx :
bytes !! Sj + i%nat = Somex
⊢
∃j0 : nat, j0 < lengthbytes%nat ∧ ptr_addr ≔ ptr_addrptr_addr ≔ ptr_addrp + Sj; ptr_cap ≔ ptr_capp + i; ptr_cap ≔ ptr_capptr_addr ≔ ptr_addrp + Sj; ptr_cap ≔ ptr_capp = ptr_addr ≔ ptr_addrp + j0; ptr_cap ≔ ptr_capp

exists Sj + i%nat

p :
bytes :
listZ
c :
Z
j :
nat
Hj :
j < lengthbytes%nat
i :
nat
x :
Z
Hx :
bytes !! Sj + i%nat = Somex
⊢
Sj + i < lengthbytes%nat ∧ ptr_addr ≔ ptr_addrptr_addr ≔ ptr_addrp + Sj; ptr_cap ≔ ptr_capp + i; ptr_cap ≔ ptr_capptr_addr ≔ ptr_addrp + Sj; ptr_cap ≔ ptr_capp = ptr_addr ≔ ptr_addrp + Sj + i%nat; ptr_cap ≔ ptr_capp

split ; exact lookup_lt_Some_ _ _ Hx |

p :
bytes :
listZ
c :
Z
j :
nat
Hj :
j < lengthbytes%nat
i :
nat
x :
Z
Hx :
bytes !! Sj + i%nat = Somex
⊢
ptr_addr ≔ ptr_addrptr_addr ≔ ptr_addrp + Sj; ptr_cap ≔ ptr_capp + i; ptr_cap ≔ ptr_capptr_addr ≔ ptr_addrp + Sj; ptr_cap ≔ ptr_capp = ptr_addr ≔ ptr_addrp + Sj + i%nat; ptr_cap ≔ ptr_capp

cbn [ ptr_addr ptr_cap ]

p :
bytes :
listZ
c :
Z
j :
nat
Hj :
j < lengthbytes%nat
i :
nat
x :
Z
Hx :
bytes !! Sj + i%nat = Somex
⊢
ptr_addr ≔ ptr_addrp + Sj + i; ptr_cap ≔ ptr_capp = ptr_addr ≔ ptr_addrp + Sj + i%nat; ptr_cap ≔ ptr_capp

f_equal

p :
bytes :
listZ
c :
Z
j :
nat
Hj :
j < lengthbytes%nat
i :
nat
x :
Z
Hx :
bytes !! Sj + i%nat = Somex
⊢
ptr_addrp + Sj + i = ptr_addrp + Sj + i%nat

lia

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros Hj i & x & Hx & _ & _ & → | _ & → ; right | left ; reflexivity
rewrite lookup_drop in Hx
exists Sj + i%nat
split ; exact lookup_lt_Some_ _ _ Hx |
f_equal
lia

The linked genv: the module, its symbols, R's free.

155Definition count_ge: genv ≔

next_l is a function of the module.

158Lemma find_next_l
Explore proof 2 tactics

Initial goal

vm_compute

⊢
SomeDefinedfn_name ≔ TAtom"next_l"; fn_linkage ≔ TAtom"export"; fn_ret ≔ RClassP; fn_params ≔ P, TAtom"v0"; fn_blocks ≔ b_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ CallCResultTAtom"v3" P GlobalTAtom"strchr" ArgP TmpTAtom"v0"; ArgW Const108; b_jump ≔ JRetTmpTAtom"v3" = SomeDefinedfn_name ≔ TAtom"next_l"; fn_linkage ≔ TAtom"export"; fn_ret ≔ RClassP; fn_params ≔ P, TAtom"v0"; fn_blocks ≔ b_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ CallCResultTAtom"v3" P GlobalTAtom"strchr" ArgP TmpTAtom"v0"; ArgW Const108; b_jump ≔ JRetTmpTAtom"v3"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity
161Section wp
162Context `{!invGS_genhlc Σ, !gen_heapGSpiece pval Σ}

The Iris instance of count.c: strchr's contract, no world.

165Instance count_irisGS: irisGS_genhlc nanofil_langcount_registry count_ge Σ ≔

The expressions of count.c's language.

169Notation cexpr ≔ language.exprnanofil_langcount_registry count_ge

next_l's triple: owning the string at p, it returns what strchr finds of l, and hands the string back.

173Lemma next_l_spec
∀ p b reg bytes Φ
stringp b reg bytes −∗ ▷∀q, ⌜strchr_foundp bytes 108 q⌝ −∗ stringp b reg bytes −∗ ΦRetWPtrq −∗ WPERunentrynext_l_fn p : cexpr {Φ}
Explore proof 11 tactics

Initial goal

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
Φ :
outcome → iPropIΣ
⊢
stringp b reg bytes −∗ ▷∀q : ptr, ⌜strchr_foundp bytes 108 q⌝ −∗ stringp b reg bytes −∗ ΦRetWPtrq −∗ WPERunentrynext_l_fn p : cexpr {v. Φv}

iIntros Hs HΦ

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
Φ :
outcome → iPropIΣ
Hs :
stringp b reg bytes
HΦ :
▷∀q : ptr, ⌜strchr_foundp bytes 108 q⌝ −∗ stringp b reg bytes −∗ ΦRetWPtrq
∗
WPERunentrynext_l_fn p {v. Φv}

iApply wp_enter ; exact find_n_start | reflexivity |

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
Φ :
outcome → iPropIΣ
Hs :
stringp b reg bytes
HΦ :
▷∀q : ptr, ⌜strchr_foundp bytes 108 q⌝ −∗ stringp b reg bytes −∗ ΦRetWPtrq
∗
▷WPCountLogic.LG.L.ERunfr_fn ≔ next_l_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" b_instsn_start b_jumpn_start {v. Φv}

iNext

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
Φ :
outcome → iPropIΣ
Hs :
stringp b reg bytes
HΦ :
∀q : ptr, ⌜strchr_foundp bytes 108 q⌝ −∗ stringp b reg bytes −∗ ΦRetWPtrq
∗
WPCountLogic.LG.L.ERunfr_fn ≔ next_l_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" b_instsn_start b_jumpn_start {v. Φv}

cbn [ b_insts b_jump n_start ]

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
Φ :
outcome → iPropIΣ
Hs :
stringp b reg bytes
HΦ :
∀q : ptr, ⌜strchr_foundp bytes 108 q⌝ −∗ stringp b reg bytes −∗ ΦRetWPtrq
∗
WPCountLogic.LG.L.ERunfr_fn ≔ next_l_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" CallCResultTAtom"v3" P GlobalTAtom"strchr" ArgP TmpTAtom"v0"; ArgW Const108 JRetTmpTAtom"v3" {v. Φv}

iApply wp_strchr with Hs ; reflexivity | reflexivity | reflexivity | reflexivity | reflexivity | vm_compute ; intuition congruence | vm_compute ; intuition congruence |

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
Φ :
outcome → iPropIΣ
HΦ :
∀q : ptr, ⌜strchr_foundp bytes 108 q⌝ −∗ stringp b reg bytes −∗ ΦRetWPtrq
∗
▷∀q : ptr, ⌜strchr_foundp bytes 108 mod 2 ^ 32 q⌝ −∗ stringp b reg bytes −∗ WPL.ERunfr_fn ≔ next_l_fn; fr_env ≔ putTAtom"v3" WPtrq TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JRetTmpTAtom"v3" {v. Φv}

iNext

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
Φ :
outcome → iPropIΣ
HΦ :
∀q : ptr, ⌜strchr_foundp bytes 108 q⌝ −∗ stringp b reg bytes −∗ ΦRetWPtrq
∗
∀q : ptr, ⌜strchr_foundp bytes 108 mod 2 ^ 32 q⌝ −∗ stringp b reg bytes −∗ WPL.ERunfr_fn ≔ next_l_fn; fr_env ≔ putTAtom"v3" WPtrq TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JRetTmpTAtom"v3" {v. Φv}

iIntros q Hq Hs

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
Φ :
outcome → iPropIΣ
q :
Hq :
strchr_foundp bytes 108 mod 2 ^ 32 q
HΦ :
∀q0 : ptr, ⌜strchr_foundp bytes 108 q0⌝ −∗ stringp b reg bytes −∗ ΦRetWPtrq0
Hs :
stringp b reg bytes
∗
WPL.ERunfr_fn ≔ next_l_fn; fr_env ≔ putTAtom"v3" WPtrq TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JRetTmpTAtom"v3" {v. Φv}

iApply wp_ret ; reflexivity | reflexivity |

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
Φ :
outcome → iPropIΣ
q :
Hq :
strchr_foundp bytes 108 mod 2 ^ 32 q
HΦ :
∀q0 : ptr, ⌜strchr_foundp bytes 108 q0⌝ −∗ stringp b reg bytes −∗ ΦRetWPtrq0
Hs :
stringp b reg bytes
∗
▷ΦRetWPtrq

iNext

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
Φ :
outcome → iPropIΣ
q :
Hq :
strchr_foundp bytes 108 mod 2 ^ 32 q
HΦ :
∀q0 : ptr, ⌜strchr_foundp bytes 108 q0⌝ −∗ stringp b reg bytes −∗ ΦRetWPtrq0
Hs :
stringp b reg bytes
∗

iApply HΦ with [%] Hs

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
Φ :
outcome → iPropIΣ
q :
Hq :
strchr_foundp bytes 108 mod 2 ^ 32 q
⊢
strchr_foundp bytes 108 q

exact Hq

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
iIntros Hs HΦ
iApply wp_enter ; exact find_n_start | reflexivity |
iNext
iApply wp_strchr with Hs ; reflexivity | reflexivity | reflexivity | reflexivity | reflexivity | vm_compute ; intuition congruence | vm_compute ; intuition congruence |
iNext
iIntros q Hq Hs
iApply wp_ret ; reflexivity | reflexivity |
iNext
iApply HΦ with [%] Hs
exact Hq

The loop, from the point after its head's phis: with pr.2 a pointer null or before the NUL of the string at p, which it owns, and pr.1 an int, the run is safe and returns an int. By Löb induction; each iteration reads the byte at the pointer and calls next_l on the suffix past it.

192Lemma count_loop
∀ p b reg bytes
⊢ ∀e q n, ⌜lookupTAtom"pr.2" e = SomeWPtrq ∧ lookupTAtom"pr.1" e = SomeWIntn ∧ found_fromp bytes q⌝ −∗ stringp b reg bytes −∗ WPERunmkFramecount_fn e [ ] None ExecTAtom"L6" b_instsc_L6 b_jumpc_L6 : cexpr {o. ⌜∃k, o = RetWIntk⌝}
Proof 76 steps Qed
iLöb as IH
iIntros e q n Hq & Hn & Hf Hs
iDestruct Hs as [%Hok Hps]
iAssert stringp b reg bytes with [$Hps] as Hs ; done |
pose proof Hok as Hc & Hb0 & Hb1 & Hb2 & Hb3 & _
destruct Hf as → | j & Hj & →

Null: the loop ends and returns the count.

–iApply wp_let ; reflexivity | reflexivity | word_premise | intros m ; word_premise |
iNext
iApply wp_let ; reflexivity | reflexivity | word_premise | intros m ; word_premise |
iNext
iApply wp_branch_ _ _ _ _ _ _ _ _ _ 0 ; word_premise |
iNext
iApply wp_enter ; exact find_c_L9 | reflexivity |
iNext
iApply wp_ret ; reflexivity | word_premise |
iNext
iPureIntro
eexists
reflexivity

A hit at j: read its byte, count it, and call next_l past it.

–iApply wp_let ; reflexivity | reflexivity | word_premise | intros m ; word_premise |
iNext
iApply wp_let ; reflexivity | reflexivity | word_premise | intros m ; word_premise |
iNext
iApply wp_branch_ _ _ _ _ _ _ _ _ _ 1 ; word_premise |
iNext
iApply wp_enter ; exact find_c_L7 | reflexivity |
iNext
destruct lookup_lt_is_Some_2bytes j Hj as x Hx
iDestruct string_byte_ _ _ _ j x with Hs as (_ & Hl & Hb & Hk) ; by apply lookup_app_l_Some |
iApply wp_check_read with Hl ; reflexivity | word_premise | exact Hc | addr_premise | addr_premise | apply Z.mod_1_r |
iNext
iIntros Hl
iApply wp_raw_load_byte with Hl Hb ; reflexivity | word_premise | reflexivity | reflexivity | exact Hc | addr_premise |
iNext
iIntros Hl Hb
iDestruct Hk with Hl Hb as Hs
iApply wp_let ; reflexivity | reflexivity | word_premise | intros m ; word_premise |
iNext
iApply wp_let ; reflexivity | reflexivity | word_premise | intros m ; word_premise |
iNext
iApply wp_flight_ _ _ _ _ _ _ _ _ _ _ _ _ _ ptr_addrp + Z.of_natSj ; word_premise | cbn ; f_equal ; f_equal ; addr_premise | word_premise |
iNext
iApply wp_call_bind ; word_premise | exact find_next_l | reflexivity |
iNext
iDestruct string_suffix_ _ _ _ Sj with Hs as [Hs Hback] ; lia |
iApply next_l_spec with Hs
iNext
iIntros q′ Hq′ Hs
iDestruct Hback with Hs as Hs
iExists _
iSplit ; iPureIntro ; reflexivity |
iNext
iApply wp_goto
iNext
iApply wp_enter ; exact find_c_L6 | word_premise |
iNext
iApply IH with [%] Hs
split ; reflexivity |
split ; reflexivity |
exact found_nextp bytes 108 q' j Hj Hq'

count_l, owning the string at p, is safe and returns an int: it calls next_l on the whole string and enters the loop.

241Lemma count_spec
∀ p b reg bytes
stringp b reg bytes −∗ WPERunentrycount_fn p : cexpr {o. ⌜∃k, o = RetWIntk⌝}
Explore proof 21 tactics

Initial goal

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
⊢
stringp b reg bytes −∗ WPERunentrycount_fn p : cexpr {o. ⌜∃k : Z, o = RetWIntk⌝}

iIntros Hs

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
Hs :
stringp b reg bytes
∗
WPERunentrycount_fn p {o. ⌜∃k : Z, o = RetWIntk⌝}

iApply wp_enter ; exact find_c_start | reflexivity |

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
Hs :
stringp b reg bytes
∗
▷WPCountLogic.LG.L.ERunfr_fn ≔ count_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" b_instsc_start b_jumpc_start {o. ⌜∃k : Z, o = RetWIntk⌝}

iNext

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
Hs :
stringp b reg bytes
∗
WPCountLogic.LG.L.ERunfr_fn ≔ count_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" b_instsc_start b_jumpc_start {o. ⌜∃k : Z, o = RetWIntk⌝}

cbn [ b_insts b_jump c_start ]

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
Hs :
stringp b reg bytes
∗
WPCountLogic.LG.L.ERunfr_fn ≔ count_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" CallCResultTAtom"v5" P GlobalTAtom"next_l" ArgP TmpTAtom"v0" JGotoToTAtom"L6" {o. ⌜∃k : Z, o = RetWIntk⌝}

iApply wp_call_bind ; reflexivity | exact find_next_l | reflexivity |

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
Hs :
stringp b reg bytes
∗
▷WPCountLogic.LG.L.ERunfr_fn ≔ next_l_fn; fr_env ≔ fold_leftλe : listname × word px : class × name × word ⇒ putpx.1.2 px.2 e combinefn_paramsnext_l_fn takelengthfn_paramsnext_l_fn WPtrp [ ]; fr_locals ≔ mapλxs : name × Z ⇒ xs.1, None local_objectsnext_l_fn; fr_doomed ≔ None; fr_at ≔ if variadic_funcnext_l_fn then SnapshotWPtrp b_labelb_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ CallCResultTAtom"v3" P GlobalTAtom"strchr" ArgP TmpTAtom"v0"; ArgW Const108; b_jump ≔ JRetTmpTAtom"v3" else Enterb_labelb_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ CallCResultTAtom"v3" P GlobalTAtom"strchr" ArgP TmpTAtom"v0"; ArgW Const108; b_jump ≔ JRetTmpTAtom"v3" None {o. ∃cf′ : frame, ⌜CountLogic.LG.L.resumefr_fn ≔ count_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6" pd_res ≔ CResultTAtom"v5" P; pd_conv ≔ None o = Somecf′⌝ ∗ ▷WPCountLogic.LG.L.ERuncf′ {o0. ⌜∃k : Z, o0 = RetWIntk⌝}}

iNext

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
Hs :
stringp b reg bytes
∗
WPCountLogic.LG.L.ERunfr_fn ≔ next_l_fn; fr_env ≔ fold_leftλe : listname × word px : class × name × word ⇒ putpx.1.2 px.2 e combinefn_paramsnext_l_fn takelengthfn_paramsnext_l_fn WPtrp [ ]; fr_locals ≔ mapλxs : name × Z ⇒ xs.1, None local_objectsnext_l_fn; fr_doomed ≔ None; fr_at ≔ if variadic_funcnext_l_fn then SnapshotWPtrp b_labelb_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ CallCResultTAtom"v3" P GlobalTAtom"strchr" ArgP TmpTAtom"v0"; ArgW Const108; b_jump ≔ JRetTmpTAtom"v3" else Enterb_labelb_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ CallCResultTAtom"v3" P GlobalTAtom"strchr" ArgP TmpTAtom"v0"; ArgW Const108; b_jump ≔ JRetTmpTAtom"v3" None {o. ∃cf′ : frame, ⌜CountLogic.LG.L.resumefr_fn ≔ count_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6" pd_res ≔ CResultTAtom"v5" P; pd_conv ≔ None o = Somecf′⌝ ∗ ▷WPCountLogic.LG.L.ERuncf′ {o0. ⌜∃k : Z, o0 = RetWIntk⌝}}

iApply next_l_spec with Hs

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
∗
▷∀q : ptr, ⌜strchr_foundp bytes 108 q⌝ −∗ stringp b reg bytes −∗ ∃cf′ : frame, ⌜CountLogic.LG.L.resumefr_fn ≔ count_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6" pd_res ≔ CResultTAtom"v5" P; pd_conv ≔ None RetWPtrq = Somecf′⌝ ∗ ▷WPCountLogic.LG.L.ERuncf′ {o. ⌜∃k : Z, o = RetWIntk⌝}

iNext

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
∗
∀q : ptr, ⌜strchr_foundp bytes 108 q⌝ −∗ stringp b reg bytes −∗ ∃cf′ : frame, ⌜CountLogic.LG.L.resumefr_fn ≔ count_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6" pd_res ≔ CResultTAtom"v5" P; pd_conv ≔ None RetWPtrq = Somecf′⌝ ∗ ▷WPCountLogic.LG.L.ERuncf′ {o. ⌜∃k : Z, o = RetWIntk⌝}

iIntros q Hq Hs

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
q :
Hq :
strchr_foundp bytes 108 q
Hs :
stringp b reg bytes
∗
∃cf′ : frame, ⌜CountLogic.LG.L.resumefr_fn ≔ count_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6" pd_res ≔ CResultTAtom"v5" P; pd_conv ≔ None RetWPtrq = Somecf′⌝ ∗ ▷WPCountLogic.LG.L.ERuncf′ {o. ⌜∃k : Z, o = RetWIntk⌝}

iExists _

2 open

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
q :
Hq :
strchr_foundp bytes 108 q
Hs :
stringp b reg bytes
∗
⌜CountLogic.LG.L.resumefr_fn ≔ count_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6" pd_res ≔ CResultTAtom"v5" P; pd_conv ≔ None RetWPtrq = Some?f⌝ ∗ ▷WPCountLogic.LG.L.ERun?f {o. ⌜∃k : Z, o = RetWIntk⌝}
shelved goal
hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
q :
Hq :
strchr_foundp bytes 108 q

iSplit ; iPureIntro ; reflexivity |

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
q :
Hq :
strchr_foundp bytes 108 q
Hs :
stringp b reg bytes
∗
▷WPCountLogic.LG.L.ERunfr_fn ≔ fr_fnfr_fn ≔ count_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6"; fr_env ≔ putTAtom"v5" WPtrq fr_envfr_fn ≔ count_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6"; fr_locals ≔ fr_localsfr_fn ≔ count_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6"; fr_doomed ≔ fr_doomedfr_fn ≔ count_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6"; fr_at ≔ fr_atfr_fn ≔ count_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6" {o. ⌜∃k : Z, o = RetWIntk⌝}

iNext

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
q :
Hq :
strchr_foundp bytes 108 q
Hs :
stringp b reg bytes
∗
WPCountLogic.LG.L.ERunfr_fn ≔ fr_fnfr_fn ≔ count_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6"; fr_env ≔ putTAtom"v5" WPtrq fr_envfr_fn ≔ count_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6"; fr_locals ≔ fr_localsfr_fn ≔ count_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6"; fr_doomed ≔ fr_doomedfr_fn ≔ count_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6"; fr_at ≔ fr_atfr_fn ≔ count_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6" {o. ⌜∃k : Z, o = RetWIntk⌝}

cbn [ fr_fn fr_env fr_locals fr_doomed fr_at ]

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
q :
Hq :
strchr_foundp bytes 108 q
Hs :
stringp b reg bytes
∗
WPCountLogic.LG.L.ERunfr_fn ≔ count_fn; fr_env ≔ putTAtom"v5" WPtrq TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ ExecTAtom"start" [ ] JGotoToTAtom"L6" {o. ⌜∃k : Z, o = RetWIntk⌝}

iApply wp_goto

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
q :
Hq :
strchr_foundp bytes 108 q
Hs :
stringp b reg bytes
∗
▷WPCountLogic.LG.L.ERunfr_fn ≔ count_fn; fr_env ≔ putTAtom"v5" WPtrq TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ Enteredge_labelToTAtom"L6" SomeTAtom"start" {o. ⌜∃k : Z, o = RetWIntk⌝}

iNext

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
q :
Hq :
strchr_foundp bytes 108 q
Hs :
stringp b reg bytes
∗
WPCountLogic.LG.L.ERunfr_fn ≔ count_fn; fr_env ≔ putTAtom"v5" WPtrq TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ Enteredge_labelToTAtom"L6" SomeTAtom"start" {o. ⌜∃k : Z, o = RetWIntk⌝}

iApply wp_enter ; exact find_c_L6 | reflexivity |

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
q :
Hq :
strchr_foundp bytes 108 q
Hs :
stringp b reg bytes
∗
▷WPCountLogic.LG.L.ERunfr_fn ≔ count_fn; fr_env ≔ putTAtom"pr.1" WInt0 mod 2 ^ 32 putTAtom"pr.2" WPtrq putTAtom"v5" WPtrq TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ Execedge_labelToTAtom"L6" b_instsc_L6 b_jumpc_L6 {o. ⌜∃k : Z, o = RetWIntk⌝}

iNext

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
q :
Hq :
strchr_foundp bytes 108 q
Hs :
stringp b reg bytes
∗
WPCountLogic.LG.L.ERunfr_fn ≔ count_fn; fr_env ≔ putTAtom"pr.1" WInt0 mod 2 ^ 32 putTAtom"pr.2" WPtrq putTAtom"v5" WPtrq TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ Execedge_labelToTAtom"L6" b_instsc_L6 b_jumpc_L6 {o. ⌜∃k : Z, o = RetWIntk⌝}

iApply count_loopp b reg bytes with [%] Hs

3 open

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
q :
Hq :
strchr_foundp bytes 108 q
⊢
lookupTAtom"pr.2" putTAtom"pr.1" WInt0 mod 2 ^ 32 putTAtom"pr.2" WPtrq putTAtom"v5" WPtrq TAtom"v0", WPtrp = SomeWPtr?x ∧ lookupTAtom"pr.1" putTAtom"pr.1" WInt0 mod 2 ^ 32 putTAtom"pr.2" WPtrq putTAtom"v5" WPtrq TAtom"v0", WPtrp = SomeWInt?x0 ∧ found_fromp bytes ?x
shelved goal
hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
q :
Hq :
strchr_foundp bytes 108 q
⊢
shelved goal
hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
q :
Hq :
strchr_foundp bytes 108 q
⊢
Z

split ; reflexivity |

2 open

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
q :
Hq :
strchr_foundp bytes 108 q
⊢
lookupTAtom"pr.1" putTAtom"pr.1" WInt0 mod 2 ^ 32 putTAtom"pr.2" WPtrq putTAtom"v5" WPtrq TAtom"v0", WPtrp = SomeWInt?x ∧ found_fromp bytes q
shelved goal
hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
q :
Hq :
strchr_foundp bytes 108 q
⊢
Z

split ; reflexivity |

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
p :
b :
Z
reg :
bytes :
listZ
q :
Hq :
strchr_foundp bytes 108 q
⊢
found_fromp bytes q

exact found_firstp bytes 108 q Hq

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
iIntros Hs
iApply wp_enter ; exact find_c_start | reflexivity |
iNext
iApply wp_call_bind ; reflexivity | exact find_next_l | reflexivity |
iNext
iApply next_l_spec with Hs
iNext
iIntros q Hq Hs
iExists _
iSplit ; iPureIntro ; reflexivity |
iNext
iApply wp_goto
iNext
iApply wp_enter ; exact find_c_L6 | reflexivity |
iNext
iApply count_loopp b reg bytes with [%] Hs
split ; reflexivity |
split ; reflexivity |
exact found_firstp bytes 108 q Hq

count_l is safe: from a ready runtime, live objects apart, and a string at p, with any fuel, no labelled run stops with a failure_ending, and a run that returns returns an int. By heap_labelled_safe from count_spec, the ghost heap starting with the string's pieces.

263Theorem count_logic_safe
∀ Σ HinvP : invGpreSΣ HheapP : gen_heapGpreSpiece pval Σ m s fuel p b reg bytes
R.readys m
string_okp b reg bytes
all_agreem string_psp b reg bytes
labelled_safecount_registry count_ge entrycount_fn p m s tt fuel λo ⇒ ∃k, o = RetWIntk
Explore proof 12 tactics

Initial goal

Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
⊢
R.readys m → live_disjointm → string_okp b reg bytes → all_agreem string_psp b reg bytes → labelled_safecount_registry count_ge entrycount_fn p m s () fuel λo : outcome ⇒ ∃k : Z, o = RetWIntk

intros Hr Hd Hok Ha

Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
⊢
labelled_safecount_registry count_ge entrycount_fn p m s () fuel λo : outcome ⇒ ∃k : Z, o = RetWIntk

apply heap_labelled_safeΣ count_registry no_world count_ge entrycount_fn p m s tt list_to_mapstring_psp b reg bytes

5 open

Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
⊢
R.readys m
focused goal
Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
focused goal
Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
⊢
agreesm list_to_mapstring_psp b reg bytes
focused goal
Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
⊢
no_worldm () list_to_mapstring_psp b reg bytes
focused goal
Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
⊢
∀ HinvG : invGS_genHasNoLc Σ HheapG : gen_heapGSpiece pval Σ  ,
∗l↦v∈list_to_mapstring_psp b reg bytespointstol DfracOwn1 v
⊢
let H ≔ nanofil_irisGScount_registry no_world count_ge in
WPCountLogic.LG.L.ERunentrycount_fn p {o. ⌜∃k : Z, o = RetWIntk⌝}

–exact Hr

4 open

deferred goal
Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
deferred goal
Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
⊢
agreesm list_to_mapstring_psp b reg bytes
deferred goal
Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
⊢
no_worldm () list_to_mapstring_psp b reg bytes
deferred goal
Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
⊢
∀ HinvG : invGS_genHasNoLc Σ HheapG : gen_heapGSpiece pval Σ  ,
∗l↦v∈list_to_mapstring_psp b reg bytespointstol DfracOwn1 v
⊢
let H ≔ nanofil_irisGScount_registry no_world count_ge in
WPCountLogic.LG.L.ERunentrycount_fn p {o. ⌜∃k : Z, o = RetWIntk⌝}

–exact Hd

3 open

deferred goal
Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
⊢
agreesm list_to_mapstring_psp b reg bytes
deferred goal
Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
⊢
no_worldm () list_to_mapstring_psp b reg bytes
deferred goal
Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
⊢
∀ HinvG : invGS_genHasNoLc Σ HheapG : gen_heapGSpiece pval Σ  ,
∗l↦v∈list_to_mapstring_psp b reg bytespointstol DfracOwn1 v
⊢
let H ≔ nanofil_irisGScount_registry no_world count_ge in
WPCountLogic.LG.L.ERunentrycount_fn p {o. ⌜∃k : Z, o = RetWIntk⌝}

–intros l v Hl

3 open

Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
v :
Hl :
list_to_mapstring_psp b reg bytes !! l = Somev
⊢
deferred goal
Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
⊢
no_worldm () list_to_mapstring_psp b reg bytes
deferred goal
Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
⊢
∀ HinvG : invGS_genHasNoLc Σ HheapG : gen_heapGSpiece pval Σ  ,
∗l↦v∈list_to_mapstring_psp b reg bytespointstol DfracOwn1 v
⊢
let H ≔ nanofil_irisGScount_registry no_world count_ge in
WPCountLogic.LG.L.ERunentrycount_fn p {o. ⌜∃k : Z, o = RetWIntk⌝}

exact all_agree_elem_ _ _ _ Ha elem_of_list_to_map_2_ _ _ Hl

2 open

deferred goal
Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
⊢
no_worldm () list_to_mapstring_psp b reg bytes
deferred goal
Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
⊢
∀ HinvG : invGS_genHasNoLc Σ HheapG : gen_heapGSpiece pval Σ  ,
∗l↦v∈list_to_mapstring_psp b reg bytespointstol DfracOwn1 v
⊢
let H ≔ nanofil_irisGScount_registry no_world count_ge in
WPCountLogic.LG.L.ERunentrycount_fn p {o. ⌜∃k : Z, o = RetWIntk⌝}

–exact I

deferred goal
Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
⊢
∀ HinvG : invGS_genHasNoLc Σ HheapG : gen_heapGSpiece pval Σ  ,
∗l↦v∈list_to_mapstring_psp b reg bytespointstol DfracOwn1 v
⊢
let H ≔ nanofil_irisGScount_registry no_world count_ge in
WPCountLogic.LG.L.ERunentrycount_fn p {o. ⌜∃k : Z, o = RetWIntk⌝}

–intros HinvG HheapG

Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
HinvG :
invGS_genHasNoLc Σ
HheapG :
gen_heapGSpiece pval Σ
⊢
∗l↦v∈list_to_mapstring_psp b reg bytespointstol DfracOwn1 v
⊢
let H ≔ nanofil_irisGScount_registry no_world count_ge in
WPCountLogic.LG.L.ERunentrycount_fn p {o. ⌜∃k : Z, o = RetWIntk⌝}

rewrite big_sepM_list_to_map ; | exact string_ps_nodupp b reg bytes

Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
HinvG :
invGS_genHasNoLc Σ
HheapG :
gen_heapGSpiece pval Σ
⊢
∗xk∈string_psp b reg bytespointstoxk.1 DfracOwn1 xk.2
⊢
let H ≔ nanofil_irisGScount_registry no_world count_ge in
WPCountLogic.LG.L.ERunentrycount_fn p {o. ⌜∃k : Z, o = RetWIntk⌝}

iIntros Hs

Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
HinvG :
invGS_genHasNoLc Σ
HheapG :
gen_heapGSpiece pval Σ
Hs :
∗xk∈string_psp b reg bytespointstoxk.1 DfracOwn1 xk.2
∗
WPCountLogic.LG.L.ERunentrycount_fn p {o. ⌜∃k : Z, o = RetWIntk⌝}

iApply count_specp b reg bytes with [$Hs]

Σ :
gFunctors
HinvP :
invGpreSΣ
HheapP :
gen_heapGpreSpiece pval Σ
m :
s :
R.state
fuel :
Z
p :
b :
Z
reg :
bytes :
listZ
Hr :
R.readys m
Hok :
string_okp b reg bytes
Ha :
all_agreem string_psp b reg bytes
HinvG :
invGS_genHasNoLc Σ
HheapG :
gen_heapGSpiece pval Σ
∗
⌜string_okp b reg bytes⌝

done

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros Hr Hd Hok Ha
–exact Hr
–exact Hd
–intros l v Hl
exact all_agree_elem_ _ _ _ Ha elem_of_list_to_map_2_ _ _ Hl
–exact I
–intros HinvG HheapG
rewrite big_sepM_list_to_map ; | exact string_ps_nodupp b reg bytes
iIntros Hs
iApply count_specp b reg bytes with [$Hs]
done

The interpreter's runtime

count.c over the interpreter's runtime.

285Module InterpCountLogic ≔ CountLogic InterpRuntime

count_l is safe under the interpreter's runtime, called with Hi.v's literal "hello" in Hi.v's fixture memory.

Explore proof 9 tactics

Initial goal

intros fuel

destruct HiChecks.entry_pre as _ & _ & Hv

apply InterpCountLogic.count_logic_safehiΣ _ _ _ _ 65552 lit_reg hello_bytes

4 open

focused goal
focused goal
focused goal

–exact hi_memory_ready

3 open

deferred goal
deferred goal
deferred goal

–exact hi_memory_disjoint

2 open

deferred goal
deferred goal

–exact lit_ok

deferred goal

–apply all_agree_intro

intros l v Hl

exact InterpHiLogic.lit_valid_agrees_ Hv l v Hl

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros fuel
destruct HiChecks.entry_pre as _ & _ & Hv
–exact lit_ok
intros l v Hl