Fil-C on Nix

Filnix wiki

the formal campaign

rocq/theories/HelloName.v

GNU Hello's set_program_name through the program logic of Logic.v (docs/logic.md, "GNU Hello through the logic", milestone 2).

gnulib's progname.c: the first thing main does. It finds the last / of argv0 (wp_strrchr); if seven bytes precede the base name, it compares them with "/.libs/" (memeq, by memeq_spec); if they match, it compares the base name with "lt-" (wp_strncmp) and skips it on a match. Then it stores the chosen pointers into three cells: Hello's program_name and libc's program_invocation_name and program_invocation_short_name.

The compiled function has no check that argv0 is not null: gnulib declares the parameter nonnull, so clang drops its abort branch, and strrchr of a null pointer would break its contract. set_program_name_spec therefore owns argv0 as a string.

Every path is safe whatever the comparisons return; the triple only says that each cell ends up holding a pointer with argv0's capability. The proof follows the blocks: spn_start to the strrchr hit, spn_L8 from the base name, spn_L16 for "lt-" and spn_L18 for the stores.

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 StepRules Symbolic ExternalCalls ExternalMachine Pieces Heap ContractFrame Language Logic StringLogic MemLogic HelloModule HelloLeaf
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 function and its data

set_program_name(argv0).

43Definition set_program_name_fn: func ≔
Eval vm_compute in hello_fn"set_program_name"

strrchr for /, then is there a slash?

46Definition s_start: block ≔
Eval vm_compute in hblkset_program_name_fn "start"

The base name starts after the slash.

48Definition s_L6: block ≔
Eval vm_compute in hblkset_program_name_fn "L6"

Do seven bytes precede the base name?

50Definition s_L8: block ≔
Eval vm_compute in hblkset_program_name_fn "L8"

Are they "/.libs/"?

52Definition s_L25: block ≔
Eval vm_compute in hblkset_program_name_fn "L25"

Branch on that answer.

54Definition s_L26: block ≔
Eval vm_compute in hblkset_program_name_fn "L26"

Does the base name start with "lt-"?

56Definition s_L16: block ≔
Eval vm_compute in hblkset_program_name_fn "L16"

Skip "lt-".

58Definition s_L35: block ≔
Eval vm_compute in hblkset_program_name_fn "L35"

Store the three names.

60Definition s_L18: block ≔
Eval vm_compute in hblkset_program_name_fn "L18"

set_program_name has its entry.

Explore proof 2 tactics

Initial goal

vm_compute

⊢
Someb_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ CallCResultTAtom"v4" P GlobalTAtom"strrchr" ArgP TmpTAtom"v0"; ArgW Const47; LetTAtom"v10" L Ptoi TmpTAtom"v4"; LetTAtom"v11" W CmpNe L TmpTAtom"v10"; Const0; b_jump ≔ JBranchTmpTAtom"v11" ToTAtom"L6" ToTAtom"L8" = Someb_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ CallCResultTAtom"v4" P GlobalTAtom"strrchr" ArgP TmpTAtom"v0"; ArgW Const47; LetTAtom"v10" L Ptoi TmpTAtom"v4"; LetTAtom"v11" W CmpNe L TmpTAtom"v10"; Const0; b_jump ≔ JBranchTmpTAtom"v11" ToTAtom"L6" ToTAtom"L8"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

set_program_name has L6.

Explore proof 2 tactics

Initial goal

vm_compute

⊢
Someb_label ≔ TAtom"L6"; b_phis ≔ [ ]; b_insts ≔ FlightTAtom"v13" Add FAddressTmpTAtom"v4"; FValueConst1 LowerOfTmpTAtom"v4"; b_jump ≔ JGotoToTAtom"L8" = Someb_label ≔ TAtom"L6"; b_phis ≔ [ ]; b_insts ≔ FlightTAtom"v13" Add FAddressTmpTAtom"v4"; FValueConst1 LowerOfTmpTAtom"v4"; b_jump ≔ JGotoToTAtom"L8"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

set_program_name has L8.

Explore proof 2 tactics

Initial goal

vm_compute

⊢
Someb_label ≔ TAtom"L8"; b_phis ≔ PhiTAtom"v15" P TAtom"L6", TmpTAtom"v13"; TAtom"start", TmpTAtom"v0"; b_insts ≔ LetTAtom"v21" L Ptoi TmpTAtom"v15"; LetTAtom"v22" L Ptoi TmpTAtom"v0"; LetTAtom"v23" L Sub TmpTAtom"v21"; TmpTAtom"v22"; LetTAtom"v24" W CmpSge L TmpTAtom"v23"; Const7; b_jump ≔ JBranchTmpTAtom"v24" ToTAtom"L25" ToTAtom"L26" = Someb_label ≔ TAtom"L8"; b_phis ≔ PhiTAtom"v15" P TAtom"L6", TmpTAtom"v13"; TAtom"start", TmpTAtom"v0"; b_insts ≔ LetTAtom"v21" L Ptoi TmpTAtom"v15"; LetTAtom"v22" L Ptoi TmpTAtom"v0"; LetTAtom"v23" L Sub TmpTAtom"v21"; TmpTAtom"v22"; LetTAtom"v24" W CmpSge L TmpTAtom"v23"; Const7; b_jump ≔ JBranchTmpTAtom"v24" ToTAtom"L25" ToTAtom"L26"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

set_program_name has L25.

Explore proof 2 tactics

Initial goal

vm_compute

⊢
Someb_label ≔ TAtom"L25"; b_phis ≔ [ ]; b_insts ≔ FlightTAtom"v28" Sub FAddressTmpTAtom"v15"; FValueConst7 LowerOfTmpTAtom"v15"; LetTAtom"v29" P Copy GlobalTAtom"progname#str.3"; CallCResultTAtom"v30" W GlobalTAtom"memeq" ArgP TmpTAtom"v28"; ArgP TmpTAtom"v29"; ArgL Const7; LetTAtom"v31" W ExtUb TmpTAtom"v30"; LetTAtom"v32" W CmpNe W TmpTAtom"v31"; Const0; b_jump ≔ JGotoToTAtom"L26" = Someb_label ≔ TAtom"L25"; b_phis ≔ [ ]; b_insts ≔ FlightTAtom"v28" Sub FAddressTmpTAtom"v15"; FValueConst7 LowerOfTmpTAtom"v15"; LetTAtom"v29" P Copy GlobalTAtom"progname#str.3"; CallCResultTAtom"v30" W GlobalTAtom"memeq" ArgP TmpTAtom"v28"; ArgP TmpTAtom"v29"; ArgL Const7; LetTAtom"v31" W ExtUb TmpTAtom"v30"; LetTAtom"v32" W CmpNe W TmpTAtom"v31"; Const0; b_jump ≔ JGotoToTAtom"L26"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

set_program_name has L26.

Explore proof 2 tactics

Initial goal

vm_compute

⊢
Someb_label ≔ TAtom"L26"; b_phis ≔ PhiTAtom"v33" W TAtom"L8", Const0; TAtom"L25", TmpTAtom"v32"; b_insts ≔ [ ]; b_jump ≔ JBranchTmpTAtom"v33" ToTAtom"L16" ToTAtom"L18" = Someb_label ≔ TAtom"L26"; b_phis ≔ PhiTAtom"v33" W TAtom"L8", Const0; TAtom"L25", TmpTAtom"v32"; b_insts ≔ [ ]; b_jump ≔ JBranchTmpTAtom"v33" ToTAtom"L16" ToTAtom"L18"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

set_program_name has L16.

Explore proof 2 tactics

Initial goal

vm_compute

⊢
Someb_label ≔ TAtom"L16"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"v39" P Copy GlobalTAtom"progname#str.4"; CallCResultTAtom"v40" W GlobalTAtom"strncmp" ArgP TmpTAtom"v15"; ArgP TmpTAtom"v39"; ArgL Const3; LetTAtom"v41" W CmpEq W TmpTAtom"v40"; Const0; b_jump ≔ JBranchTmpTAtom"v41" ToTAtom"L35" ToTAtom"L18" = Someb_label ≔ TAtom"L16"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"v39" P Copy GlobalTAtom"progname#str.4"; CallCResultTAtom"v40" W GlobalTAtom"strncmp" ArgP TmpTAtom"v15"; ArgP TmpTAtom"v39"; ArgL Const3; LetTAtom"v41" W CmpEq W TmpTAtom"v40"; Const0; b_jump ≔ JBranchTmpTAtom"v41" ToTAtom"L35" ToTAtom"L18"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

set_program_name has L35.

Explore proof 2 tactics

Initial goal

vm_compute

⊢
Someb_label ≔ TAtom"L35"; b_phis ≔ [ ]; b_insts ≔ FlightTAtom"v43" Add FAddressTmpTAtom"v15"; FValueConst3 LowerOfTmpTAtom"v15"; b_jump ≔ JGotoToTAtom"L18" = Someb_label ≔ TAtom"L35"; b_phis ≔ [ ]; b_insts ≔ FlightTAtom"v43" Add FAddressTmpTAtom"v15"; FValueConst3 LowerOfTmpTAtom"v15"; b_jump ≔ JGotoToTAtom"L18"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

set_program_name has L18.

Explore proof 2 tactics

Initial goal

vm_compute

⊢
Someb_label ≔ TAtom"L18"; b_phis ≔ PhiTAtom"pr.3" P TAtom"L35", TmpTAtom"v43"; TAtom"L16", TmpTAtom"v15"; TAtom"L26", TmpTAtom"v15"; PhiTAtom"pr.1" P TAtom"L35", TmpTAtom"v43"; TAtom"L16", TmpTAtom"v15"; TAtom"L26", TmpTAtom"v0"; b_insts ≔ LetTAtom"v45" P Copy GlobalTAtom"program_name"; LetTAtom"chk0" A Check0 8 Write 8 TmpTAtom"v45"; RawStorePointer0 TmpTAtom"pr.1" TmpTAtom"chk0" AuxEnsure; LowerBarrier; RootedReload; LowerWrite; AddressWrite; LetTAtom"v47" P Copy GlobalTAtom"program_invocation_name"; LetTAtom"chk1" A Check0 8 Write 8 TmpTAtom"v47"; RawStorePointer0 TmpTAtom"pr.1" TmpTAtom"chk1" AuxEnsure; LowerBarrier; RootedReload; LowerWrite; AddressWrite; LetTAtom"v49" P Copy GlobalTAtom"program_invocation_short_name"; LetTAtom"chk2" A Check0 8 Write 8 TmpTAtom"v49"; RawStorePointer0 TmpTAtom"pr.3" TmpTAtom"chk2" AuxEnsure; LowerBarrier; RootedReload; LowerWrite; AddressWrite; b_jump ≔ JRetVoid = Someb_label ≔ TAtom"L18"; b_phis ≔ PhiTAtom"pr.3" P TAtom"L35", TmpTAtom"v43"; TAtom"L16", TmpTAtom"v15"; TAtom"L26", TmpTAtom"v15"; PhiTAtom"pr.1" P TAtom"L35", TmpTAtom"v43"; TAtom"L16", TmpTAtom"v15"; TAtom"L26", TmpTAtom"v0"; b_insts ≔ LetTAtom"v45" P Copy GlobalTAtom"program_name"; LetTAtom"chk0" A Check0 8 Write 8 TmpTAtom"v45"; RawStorePointer0 TmpTAtom"pr.1" TmpTAtom"chk0" AuxEnsure; LowerBarrier; RootedReload; LowerWrite; AddressWrite; LetTAtom"v47" P Copy GlobalTAtom"program_invocation_name"; LetTAtom"chk1" A Check0 8 Write 8 TmpTAtom"v47"; RawStorePointer0 TmpTAtom"pr.1" TmpTAtom"chk1" AuxEnsure; LowerBarrier; RootedReload; LowerWrite; AddressWrite; LetTAtom"v49" P Copy GlobalTAtom"program_invocation_short_name"; LetTAtom"chk2" A Check0 8 Write 8 TmpTAtom"v49"; RawStorePointer0 TmpTAtom"pr.3" TmpTAtom"chk2" AuxEnsure; LowerBarrier; RootedReload; LowerWrite; AddressWrite; b_jump ≔ JRetVoid

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

set_program_name's entry binds argv0.

88Lemma set_program_name_entry
Explore proof 1 tactics

Initial goal

p :
⊢
invocationset_program_name_fn WPtrp = fr_fn ≔ set_program_name_fn; fr_env ≔ TAtom"v0", WPtrp; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ EnterTAtom"start" None

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
reflexivity

memeq is a function of a genv with Hello's module.

94Lemma find_memeq
Explore proof 5 tactics

Initial goal

ge :
⊢

intros Hm

⊢
find_fnge TAtom"memeq" = SomeDefinedmemeq_fn

unfold find_fn

⊢
match find_directTAtom"memeq" ge_modulege with
Somed
⇒
Somed
None
⇒
=

rewrite Hm

⊢
match find_directTAtom"memeq" hello_module with
Somed
⇒
Somed
=

vm_compute

⊢
SomeDefinedfn_name ≔ TAtom"memeq"; fn_linkage ≔ TAtom"export"; fn_ret ≔ RClassW; fn_params ≔ P, TAtom"v0"; P, TAtom"v2"; L, TAtom"v4"; fn_blocks ≔ b_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ CallCResultTAtom"v9" W GlobalTAtom"memcmp" ArgP TmpTAtom"v0"; ArgP TmpTAtom"v2"; ArgL TmpTAtom"v4"; LetTAtom"v10" W CmpEq W TmpTAtom"v9"; Const0; b_jump ≔ JRetTmpTAtom"v10" = SomeDefinedfn_name ≔ TAtom"memeq"; fn_linkage ≔ TAtom"export"; fn_ret ≔ RClassW; fn_params ≔ P, TAtom"v0"; P, TAtom"v2"; L, TAtom"v4"; fn_blocks ≔ b_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ CallCResultTAtom"v9" W GlobalTAtom"memcmp" ArgP TmpTAtom"v0"; ArgP TmpTAtom"v2"; ArgL TmpTAtom"v4"; LetTAtom"v10" W CmpEq W TmpTAtom"v9"; Const0; b_jump ≔ JRetTmpTAtom"v10"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros Hm
unfold find_fn
rewrite Hm
vm_compute
reflexivity

Hello's program_name: an 8-byte cell at 66080.

98Definition program_name_b: Z ≔
66080

The literal "/.libs/" of progname.c, read-only at 66112.

100Definition libs_ptr: ptr ≔
mkPtr66112 Ro66112

Its bytes.

102Definition libs_bytes: listZ ≔
47; 46; 108; 105; 98; 115; 47

The literal "lt-" of progname.c, read-only at 66144.

104Definition lt_ptr: ptr ≔
mkPtr66144 Ro66144

Its bytes.

106Definition lt_bytes: listZ ≔
108; 116; 45

Hello's symbols put program_name and the two literals there.

109Lemma progname_globals
lookupTAtom"program_name" hello_globals = SomemkPtrprogram_name_b Objprogram_name_b ∧ lookupTAtom"progname#str.3" hello_globals = Somelibs_ptr ∧ lookupTAtom"progname#str.4" hello_globals = Somelt_ptr
Explore proof 2 tactics

Initial goal

⊢
lookupTAtom"program_name" hello_globals = Someptr_addr ≔ program_name_b; ptr_cap ≔ Objprogram_name_b ∧ lookupTAtom"progname#str.3" hello_globals = Somelibs_ptr ∧ lookupTAtom"progname#str.4" hello_globals = Somelt_ptr

vm_compute

⊢
Someptr_addr ≔ 66080; ptr_cap ≔ Obj66080 = Someptr_addr ≔ 66080; ptr_cap ≔ Obj66080 ∧ Someptr_addr ≔ 66112; ptr_cap ≔ Ro66112 = Someptr_addr ≔ 66112; ptr_cap ≔ Ro66112 ∧ Someptr_addr ≔ 66144; ptr_cap ≔ Ro66144 = Someptr_addr ≔ 66144; ptr_cap ≔ Ro66144

auto

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
auto

set_program_name over any runtime R.

116Module HelloNameOn R : Runtime LG0 : LogicSigR
117Module HL ≔ HelloLeafOn R LG0
118Module ML ≔ HL.ML
119Module SL ≔ ML.SL
120Module LG ≔ ML.LG
121Module L ≔ LG.L
Import L LG SL ML HL
124Section name
125Context `{!invGS_genhlc Σ, !gen_heapGSpiece pval Σ}
126Context world : Type registry : name → optioncontractworld wi : mem → world → gmappiece pval → Prop `{!SafepointStablewi} ge : genv

The genv links Hello, with the contracts the function calls.

130Context Hlinked : hello_linkedge
130Context Hstrrchr : registryTAtom"strrchr" = Somestrrchr_contractworld
130Context Hmemcmp : registryTAtom"memcmp" = Somememcmp_contractworld
130Context Hstrncmp : registryTAtom"strncmp" = Somestrncmp_contractworld

A pointer store into the cell at offset 0 of the object b, with the region reg, keeps the world interpretation, whatever it held and whatever it now holds (wp_raw_store_pointer's premise).

138Definition store_keepsb : Z reg : region : Prop ≔
∀x xp m wd h, ∀l v, l, v ∈ PLiveb, VLivereg ++ PAuxb 0, VAuxptr_capx :: cellb 0 ptr_addrx → h !! l = Somev → wim wd h → wistore_bytesstore_auxm b + 0 ptr_capxp b + 0 8 ptr_addrxp wd overwritePLiveb, VLivereg ++ PAuxb 0, VAuxptr_capxp :: cellb 0 ptr_addrxp h

The three cells: program_name in the object 66080 with the region pn, libc's program_invocation_name in the object nb with nreg, and program_invocation_short_name in sb with sreg, each its own object, as each Fil-C global is.

150Context pn nreg sreg : region
150Context nb sb : Z
150Context Hnb : lookupTAtom"program_invocation_name" ge_globalsge = SomemkPtrnb Objnb
150Context Hsb : lookupTAtom"program_invocation_short_name" ge_globalsge = SomemkPtrsb Objsb
150Context Hpn_end : program_name_b + 8 ≤ r_endpn
150Context Hnb_cell : 0 ≤ nb ∧ nb mod 8 = 0 ∧ nb + 8 ≤ r_endnreg ∧ r_endnreg ≤ 2 ^ 48
150Context Hsb_cell : 0 ≤ sb ∧ sb mod 8 = 0 ∧ sb + 8 ≤ r_endsreg ∧ r_endsreg ≤ 2 ^ 48
150Context Knb : store_keepsnb nreg
150Context Ksb : store_keepssb sreg

The Iris instance of the registry and wi.

159Instance name_irisGS: irisGS_genhlc nanofil_langregistry ge Σ ≔
nanofil_irisGSregistry wi ge

The expressions of the language.

163Notation nexpr ≔ language.exprnanofil_langregistry ge

The three cells, holding x, x and y.

166Definition name_cellsx0 x1 y : ptr : iPropΣ ≔

The two literals, as strings.

171Definition literalsr3 r4 : region : iPropΣ ≔

The genv's program_name and literals are Hello's.

175Lemma name_lookups
lookupTAtom"program_name" ge_globalsge = SomemkPtrprogram_name_b Objprogram_name_b ∧ lookupTAtom"progname#str.3" ge_globalsge = Somelibs_ptr ∧ lookupTAtom"progname#str.4" ge_globalsge = Somelt_ptr
Explore proof 4 tactics

Initial goal

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
world :
Type
registry :
name → optioncontractworld
wi :
mem → world → gmappiece pval → Prop
SafepointStable0 :
ge :
Hlinked :
Hstrrchr :
registryTAtom"strrchr" = Somestrrchr_contractworld
Hmemcmp :
registryTAtom"memcmp" = Somememcmp_contractworld
Hstrncmp :
registryTAtom"strncmp" = Somestrncmp_contractworld
pn, nreg, sreg :
nb, sb :
Z
Hnb :
lookupTAtom"program_invocation_name" ge_globalsge = Someptr_addr ≔ nb; ptr_cap ≔ Objnb
Hsb :
lookupTAtom"program_invocation_short_name" ge_globalsge = Someptr_addr ≔ sb; ptr_cap ≔ Objsb
Hpn_end :
program_name_b + 8 ≤ r_endpn
Hnb_cell :
0 ≤ nb ∧ nb mod 8 = 0 ∧ nb + 8 ≤ r_endnreg ≤ 2 ^ 48
Hsb_cell :
0 ≤ sb ∧ sb mod 8 = 0 ∧ sb + 8 ≤ r_endsreg ≤ 2 ^ 48
Knb :
Ksb :
⊢
lookupTAtom"program_name" ge_globalsge = Someptr_addr ≔ program_name_b; ptr_cap ≔ Objprogram_name_b ∧ lookupTAtom"progname#str.3" ge_globalsge = Somelibs_ptr ∧ lookupTAtom"progname#str.4" ge_globalsge = Somelt_ptr

destruct progname_globals as H1 & H2 & H3

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
world :
Type
registry :
name → optioncontractworld
wi :
mem → world → gmappiece pval → Prop
SafepointStable0 :
ge :
Hlinked :
Hstrrchr :
registryTAtom"strrchr" = Somestrrchr_contractworld
Hmemcmp :
registryTAtom"memcmp" = Somememcmp_contractworld
Hstrncmp :
registryTAtom"strncmp" = Somestrncmp_contractworld
pn, nreg, sreg :
nb, sb :
Z
Hnb :
lookupTAtom"program_invocation_name" ge_globalsge = Someptr_addr ≔ nb; ptr_cap ≔ Objnb
Hsb :
lookupTAtom"program_invocation_short_name" ge_globalsge = Someptr_addr ≔ sb; ptr_cap ≔ Objsb
Hpn_end :
program_name_b + 8 ≤ r_endpn
Hnb_cell :
0 ≤ nb ∧ nb mod 8 = 0 ∧ nb + 8 ≤ r_endnreg ≤ 2 ^ 48
Hsb_cell :
0 ≤ sb ∧ sb mod 8 = 0 ∧ sb + 8 ≤ r_endsreg ≤ 2 ^ 48
Knb :
Ksb :
H2 :
lookupTAtom"progname#str.3" hello_globals = Somelibs_ptr
H3 :
lookupTAtom"progname#str.4" hello_globals = Somelt_ptr
⊢
lookupTAtom"program_name" ge_globalsge = Someptr_addr ≔ program_name_b; ptr_cap ≔ Objprogram_name_b ∧ lookupTAtom"progname#str.3" ge_globalsge = Somelibs_ptr ∧ lookupTAtom"progname#str.4" ge_globalsge = Somelt_ptr

destruct Hlinked as _ & Hg & _

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
world :
Type
registry :
name → optioncontractworld
wi :
mem → world → gmappiece pval → Prop
SafepointStable0 :
ge :
Hlinked :
Hstrrchr :
registryTAtom"strrchr" = Somestrrchr_contractworld
Hmemcmp :
registryTAtom"memcmp" = Somememcmp_contractworld
Hstrncmp :
registryTAtom"strncmp" = Somestrncmp_contractworld
pn, nreg, sreg :
nb, sb :
Z
Hnb :
lookupTAtom"program_invocation_name" ge_globalsge = Someptr_addr ≔ nb; ptr_cap ≔ Objnb
Hsb :
lookupTAtom"program_invocation_short_name" ge_globalsge = Someptr_addr ≔ sb; ptr_cap ≔ Objsb
Hpn_end :
program_name_b + 8 ≤ r_endpn
Hnb_cell :
0 ≤ nb ∧ nb mod 8 = 0 ∧ nb + 8 ≤ r_endnreg ≤ 2 ^ 48
Hsb_cell :
0 ≤ sb ∧ sb mod 8 = 0 ∧ sb + 8 ≤ r_endsreg ≤ 2 ^ 48
Knb :
Ksb :
H2 :
lookupTAtom"progname#str.3" hello_globals = Somelibs_ptr
H3 :
lookupTAtom"progname#str.4" hello_globals = Somelt_ptr
Hg :
∀n : name p : ptr, lookupn hello_globals = Somep → lookupn ge_globalsge = Somep
⊢
lookupTAtom"program_name" ge_globalsge = Someptr_addr ≔ program_name_b; ptr_cap ≔ Objprogram_name_b ∧ lookupTAtom"progname#str.3" ge_globalsge = Somelibs_ptr ∧ lookupTAtom"progname#str.4" ge_globalsge = Somelt_ptr

split ; exact Hg_ _ H1 |

hlc :
has_lc
Σ :
gFunctors
invGS_gen0 :
invGS_genhlc Σ
gen_heapGS0 :
gen_heapGSpiece pval Σ
world :
Type
registry :
name → optioncontractworld
wi :
mem → world → gmappiece pval → Prop
SafepointStable0 :
ge :
Hlinked :
Hstrrchr :
registryTAtom"strrchr" = Somestrrchr_contractworld
Hmemcmp :
registryTAtom"memcmp" = Somememcmp_contractworld
Hstrncmp :
registryTAtom"strncmp" = Somestrncmp_contractworld
pn, nreg, sreg :
nb, sb :
Z
Hnb :
lookupTAtom"program_invocation_name" ge_globalsge = Someptr_addr ≔ nb; ptr_cap ≔ Objnb
Hsb :
lookupTAtom"program_invocation_short_name" ge_globalsge = Someptr_addr ≔ sb; ptr_cap ≔ Objsb
Hpn_end :
program_name_b + 8 ≤ r_endpn
Hnb_cell :
0 ≤ nb ∧ nb mod 8 = 0 ∧ nb + 8 ≤ r_endnreg ≤ 2 ^ 48
Hsb_cell :
0 ≤ sb ∧ sb mod 8 = 0 ∧ sb + 8 ≤ r_endsreg ≤ 2 ^ 48
Knb :
Ksb :
H2 :
lookupTAtom"progname#str.3" hello_globals = Somelibs_ptr
H3 :
lookupTAtom"progname#str.4" hello_globals = Somelt_ptr
Hg :
∀n : name p : ptr, lookupn hello_globals = Somep → lookupn ge_globalsge = Somep
⊢
lookupTAtom"progname#str.3" ge_globalsge = Somelibs_ptr ∧ lookupTAtom"progname#str.4" ge_globalsge = Somelt_ptr

split ; exact Hg_ _ H2 | exact Hg_ _ H3

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
destruct progname_globals as H1 & H2 & H3
destruct Hlinked as _ & Hg & _
split ; exact Hg_ _ H1 |
split ; exact Hg_ _ H2 | exact Hg_ _ H3

The stores, from L18 after its phis, where pr.1 reads as x and pr.3 as y: each cell's check passes and its store keeps the world interpretation.

187Lemma spn_L18
∀ e x y x0 x1 y0 Φ
lookupTAtom"pr.1" e = SomeWPtrx
lookupTAtom"pr.3" e = SomeWPtry
name_cellsx0 x1 y0 −∗ ▷name_cellsx x y −∗ ΦRetVoid −∗ WPERunmkFrameset_program_name_fn e [ ] None ExecTAtom"L18" b_instss_L18 b_jumps_L18 : nexpr {Φ}
Proof 38 steps Qed
intros Hx Hy
destruct name_lookups as Hpn & _ & _
destruct Hnb_cell as Hn0 & Hn8 & Hnend & Hn48
destruct Hsb_cell as Hs0 & Hs8 & Hsend & Hs48
iIntros (Hlp & Hcp & Hln & Hcn & Hls & Hcs) HΦ
unfold program_name_b in *
iApply wp_let ; reflexivity | reflexivity | word_premise | intros m ; word_premise |
iNext
iApply wp_check with Hlp ; reflexivity | word_premise | reflexivity | addr_premise | addr_premise | addr_premise |
iNext
iIntros Hlp
iApply wp_raw_store_pointer with Hlp Hcp ; word_premise | word_premise | reflexivity | addr_premise | reflexivity | apply Kpn |
iNext
iIntros Hlp Hcp
iApply wp_let ; reflexivity | reflexivity | word_premise | intros m ; word_premise |
iNext
iApply wp_check with Hln ; reflexivity | word_premise | reflexivity | addr_premise | addr_premise | addr_premise |
iNext
iIntros Hln
iApply wp_raw_store_pointer with Hln Hcn ; word_premise | word_premise | reflexivity | addr_premise | addr_premise | apply Knb |
iNext
iIntros Hln Hcn
iApply wp_let ; reflexivity | reflexivity | word_premise | intros m ; word_premise |
iNext
iApply wp_check with Hls ; reflexivity | word_premise | reflexivity | addr_premise | addr_premise | addr_premise |
iNext
iIntros Hls
iApply wp_raw_store_pointer with Hls Hcs ; word_premise | word_premise | reflexivity | addr_premise | addr_premise | apply Ksb |
iNext
iIntros Hls Hcs
iNext
iApply HΦ
iFrame

Take every branch of the goal's conditions: each path is safe.

222Ltac all_cases  ≔
repeat match goal with|- context [if ?t then _ else _]⇒destruct tend;cbn [ edge_label ]

The "lt-" test, from L16, with v15 reading as the base name, the suffix of argv0 from its j-th byte: strncmp of it and "lt-", and either answer goes on to the stores, past "lt-" or not.

228Lemma spn_L16
∀ e p b reg ys j r3 r4 x0 x1 y0 Φ
lookupTAtom"v15" e = SomeWPtrmkPtrptr_addrp + Z.of_natj ptr_capp
j ≤ lengthys%nat
stringp b reg ys −∗ literalsr3 r4 −∗ name_cellsx0 x1 y0 −∗ ▷∀x y, ⌜ptr_capx = ptr_capp ∧ ptr_capy = ptr_capp⌝ −∗ stringp b reg ys −∗ literalsr3 r4 −∗ name_cellsx x y −∗ ΦRetVoid −∗ WPERunmkFrameset_program_name_fn e [ ] None ExecTAtom"L16" b_instss_L16 b_jumps_L16 : nexpr {Φ}
Proof 44 steps Qed
intros Hv15 Hj
destruct name_lookups as _ & _ & Hlt
iIntros Hs [Hlibs Hlt] Hc HΦ
iDestruct Hs as [%Hok Hps]
iAssert stringp b reg ys with [$Hps] as Hs ; done |
pose proof Hok as Hcap & Hb0 & Hb1 & Hb2 & Hb3 & _
iApply wp_let ; reflexivity | reflexivity | word_premise | intros m ; word_premise |
iNext
iDestruct string_suffix_ _ _ _ j with Hs as [Hsuf Hback] ; exact Hj |
iApply wp_strncmp with Hsuf Hlt ; exact Hstrncmp | apply linked_outside ; exact Hlinked | reflexivity | apply linked_unbound ; exact Hlinked | reflexivity | word_premise | word_premise | word_premise | vm_compute ; intuition congruence |
iNext
iIntros bits Hsuf Hlt
iDestruct Hback with Hsuf as Hs
iApply wp_let ; reflexivity | reflexivity | word_premise | intros m ; word_premise |
iNext
iNext
–iApply wp_enter ; exact find_s_L18 | word_premise |
iNext
iApply spn_L18 with Hc ; reflexivity | reflexivity |
iNext
iIntros Hc
iApply HΦ with [%] Hs [$Hlibs $Hlt] Hc
split ; reflexivity
–iApply wp_enter ; exact find_s_L35 | reflexivity |
iNext
iApply wp_flight_ _ _ _ _ _ _ _ _ _ _ _ _ _ ptr_addrp + Z.of_natj + 3 ; word_premise | cbn ; f_equal ; f_equal ; addr_premise | word_premise |
iNext
iApply wp_goto
iNext
iApply wp_enter ; exact find_s_L18 | word_premise |
iNext
iApply spn_L18 with Hc ; reflexivity | reflexivity |
iNext
iIntros Hc
iApply HΦ with [%] Hs [$Hlibs $Hlt] Hc
split ; reflexivity

From L8, with v15 reading as the base name, the suffix of argv0 from its j-th byte, and v0 as argv0: if seven bytes precede the base name, memeq compares them with "/.libs/"; whatever it says, the run goes on to the "lt-" test or to the stores.

266Lemma spn_L8
∀ e p b reg ys j r3 r4 x0 x1 y0 Φ
lookupTAtom"v15" e = SomeWPtrmkPtrptr_addrp + Z.of_natj ptr_capp
lookupTAtom"v0" e = SomeWPtrp
j ≤ lengthys%nat
stringp b reg ys −∗ literalsr3 r4 −∗ name_cellsx0 x1 y0 −∗ ▷∀x y, ⌜ptr_capx = ptr_capp ∧ ptr_capy = ptr_capp⌝ −∗ stringp b reg ys −∗ literalsr3 r4 −∗ name_cellsx x y −∗ ΦRetVoid −∗ WPERunmkFrameset_program_name_fn e [ ] None ExecTAtom"L8" b_instss_L8 b_jumps_L8 : nexpr {Φ}
Proof 93 steps Qed
intros Hv15 Hv0 Hj
destruct name_lookups as _ & Hlibs & _
iIntros Hs [Hl3 Hl4] Hc HΦ
iDestruct Hs as [%Hok Hps]
iAssert stringp b reg ys with [$Hps] as Hs ; done |
pose proof Hok as Hcap & Hb0 & Hb1 & Hb2 & Hb3 & Hys
assert Hjz : Z.of_natj ≤ Z.of_natlengthys by lia
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_let ; reflexivity | reflexivity | word_premise | intros m ; word_premise |
iNext
iApply wp_let ; reflexivity | reflexivity | word_premise | intros m ; word_premise |
iNext
destruct Nat.lt_ge_casesj 7 as Hj7 | Hj7

Fewer than seven bytes precede the base name.

–assert Hz7 : Z.of_natj < 7 by lia
iApply wp_branch_ _ _ _ _ _ _ _ _ _ 0 ; word_premise |
iNext
iApply wp_enter ; exact find_s_L26 | reflexivity |
iNext
iApply wp_branch_ _ _ _ _ _ _ _ _ _ 0 ; word_premise |
iNext
iApply wp_enter ; exact find_s_L18 | word_premise |
iNext
iApply spn_L18 with Hc ; word_premise | word_premise |
iNext
iIntros Hc
iApply HΦ with [%] Hs [$Hl3 $Hl4] Hc
split ; reflexivity

Compare the seven bytes before it with "/.libs/".

–assert Hz7 : 7 ≤ Z.of_natj by lia
iApply wp_branch_ _ _ _ _ _ _ _ _ _ 1 ; word_premise |
iNext
iApply wp_enter ; exact find_s_L25 | reflexivity |
iNext
iApply wp_flight_ _ _ _ _ _ _ _ _ _ _ _ _ _ b + ptr_addrp − b + Z.of_natj − 7 ; word_premise | cbn ; f_equal ; f_equal ; addr_premise | word_premise |
iNext
iApply wp_let ; reflexivity | reflexivity | word_premise | intros m ; word_premise |
iNext
iDestruct string_window_ _ _ _ j − 7 7 with Hs as (_ & Hl & Hw & Hback) ; lia |
iDestruct string_window_ _ _ _ 0 7 with Hl3 as (%Hok3 & Hl3 & Hw3 & Hback3) ; cbn ; lia |
pose proof Hok3 as _ & _ & _ & H3end & _
iApply wp_call_bind_ _ _ _ _ _ _ _ _ _ _ _ _ memeq_fn invocationmemeq_fn WPtrmkPtrb + ptr_addrp − b + Z.of_natj − 7 ptr_capp; WPtrlibs_ptr; WInt7 ; word_premise | apply find_memeq ; exact proj1Hlinked | reflexivity |
iNext
iApply memeq_specregistry wi ge Hlinked b reg ptr_addrp − b + Z.of_natj − 7 _ ptr_capp 66112 r3 ptr_addrlibs_ptr − 66112 + Z.of_nat0 _ Ro66112 with Hl Hw Hl3 Hw3 ; exact Hmemcmp | rewrite length_take length_drop ; lia | exact Hcap | right ; reflexivity | rewrite ! length_take ! length_drop ; cbn [ length libs_bytes ] ; lia | lia | cbn ; lia | rewrite length_take length_drop ; lia | rewrite length_take length_drop ; cbn [ ptr_addr libs_ptr length libs_bytes ] in H3end |- * ; lia | rewrite length_take length_drop ; lia | apply Forall_take , Forall_drop ; eapply Forall_impl ; exact Hys | intros x Hx ; cbn in Hx ; lia | vm_compute ; repeat constructor ; discriminate |
iNext
iIntros k Hl Hw Hl3 Hw3
iDestruct Hback with Hl Hw as Hs
iDestruct Hback3 with Hl3 Hw3 as Hl3
iExists _
iSplit ; iPureIntro ; reflexivity |
iNext
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_goto
iNext
iApply wp_enter ; exact find_s_L26 | word_premise |
iNext
iNext
+iApply wp_enter ; exact find_s_L18 | word_premise |
iNext
iApply spn_L18 with Hc ; word_premise | word_premise |
iNext
iIntros Hc
iApply HΦ with [%] Hs [$Hl3 $Hl4] Hc
split ; reflexivity
+iApply wp_enter ; exact find_s_L16 | reflexivity |
iNext
iApply spn_L16 with Hs [$Hl3 $Hl4] Hc ; word_premise | exact Hj |
iExact HΦ

set_program_name's triple: owning argv0 as the string at p, the literals and the three cells, the call is safe and each cell ends up holding a pointer with p's capability: the first two the same one.

338Lemma set_program_name_spec
∀ p b reg ys r3 r4 x0 x1 y0 Φ
stringp b reg ys −∗ literalsr3 r4 −∗ name_cellsx0 x1 y0 −∗ ▷∀x y, ⌜ptr_capx = ptr_capp ∧ ptr_capy = ptr_capp⌝ −∗ stringp b reg ys −∗ literalsr3 r4 −∗ name_cellsx x y −∗ ΦRetVoid −∗ WPERuninvocationset_program_name_fn WPtrp : nexpr {Φ}
Proof 39 steps Qed
iIntros Hs Hlit Hc HΦ
iDestruct Hs as [%Hok Hps]
iAssert stringp b reg ys with [$Hps] as Hs ; done |
pose proof Hok as Hcap & Hb0 & Hb1 & Hb2 & Hb3 & _
iApply wp_enter ; exact find_s_start | reflexivity |
iNext
iApply wp_strrchr with Hs ; exact Hstrrchr | apply linked_outside ; exact Hlinked | reflexivity | apply linked_unbound ; exact Hlinked | reflexivity | reflexivity | reflexivity | vm_compute ; intuition congruence | vm_compute ; intuition congruence |
iNext
iIntros q Hq Hs
destruct Hq as → | i & Hi & →

No slash: the base name is argv0.

–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 ; reflexivity |
iNext
iApply wp_enter ; exact find_s_L8 | reflexivity |
iNext
iApply spn_L8_ _ _ _ _ 0 with Hs Hlit Hc HΦ ; destruct p ; cbn ; rewrite Z.add_0_r ; reflexivity | reflexivity | lia

A slash at i: the base name starts after 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_s_L6 | reflexivity |
iNext
iApply wp_flight_ _ _ _ _ _ _ _ _ _ _ _ _ _ ptr_addrp + Z.of_natSi ; word_premise | cbn ; f_equal ; f_equal ; addr_premise | word_premise |
iNext
iApply wp_goto
iNext
iApply wp_enter ; exact find_s_L8 | reflexivity |
iNext
iApply spn_L8_ _ _ _ _ Si with Hs Hlit Hc HΦ ; reflexivity | reflexivity | lia

HelloNameOn over a Logic instance of its own.

377Module HelloName R : Runtime
378Module LG0 ≔ Logic R
Include HelloNameOn R LG0