rocq/theories/Startup.v
The Fil-C launcher's entry contract, before libc calls main (milestone 3a).
The pinned filc_start_program.c copies argv and environ into fresh capability-bearing objects. Pointer arrays include a null sentinel; strings include an in-object first NUL. Lengths and contents are not restricted to the native probes. The launcher asserts argc >= 1.
These are concrete predicates on model memory, not new runtime axioms or a proof of the native launcher. Establishing the full entry image from startup allocations, including libc/TLS and finalizer roots, remains a separate obligation. Resource refusal before entry must not be confused with a malformed entry or deleted execution.
The eight-byte cell at address a of memory m holds pointer p: its bytes read as p's address and its aux entry is p's capability. A slot carries address bits AND the corresponding capability. Bounding the address below 2^64 prevents an integer outside the word range from standing for the same stored bytes.
The same address/aux store used by store_res constructs an actual decoded slot. No access or capability authority is inferred here; local_store_pointer supplies the separate footprint obligation.
Explore proof 10 tactics
Initial goal
intros m a p Hp
split ; exact Hp |
split
2 open–change load_bytesstore_bytesm a 8 ptr_addrp a 8 = ptr_addrp
2 openrewrite stored_bytes_value by lia
2 openapply Z.mod_small
2 openexact Hp
–simpl
rewrite Z.eqb_refl
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A byte store of size bytes at address a keeps a pointer_slot at b that it does not overlap.
Explore proof 12 tactics
Initial goal
intros m a size x b p Hsize Hdis Hp Hbytes Haux
split ; exact Hp |
split ; | exact Haux
rewrite <- Hbytes
apply load_bytes_agree ; lia |
intros i Hi
simpl
destruct a ≤? b + i && b + i <? a + size eqn: E ; | reflexivity
apply andb_true_iff in E as E1 E2
apply Z.leb_le in E1
apply Z.ltb_lt in E2
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A pointer store at address a keeps a pointer_slot at b eight or more bytes away.
Explore proof 8 tactics
Initial goal
intros m a p b q Hdis Hslot
destruct pointer_slot_bytes_disjointm a 8 ptr_addrp b q ltac:lia Hdis Hslot as Hq Hbytes Haux
split ; exact Hq |
split ; exact Hbytes |
simpl
assert b =? a = false as E by apply Z.eqb_neq ; lia
rewrite E
exact Haux
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
From address a on, memory m holds one pointer_slot per text, each pointing at a c_string with that text, then a null slot.
Pointer table points at a null-terminated array of C strings with the given texts, as argv and envp are. Check the entire pointer array, including its sentinel, with the array's capability and pointer alignment. A raw address whose aux metadata was lost does not satisfy the string slots.
Memory m is the launcher's entry image for main's arguments argc, argv and envp, with argument strings args and environment strings environment: argc is a positive int counting args, and argv and envp are string_vectors of them.
A libc-exposed pointer cell has its own writable object authority and decoded value. Authority to its pointee is not authority to change the cell, nor does this predicate establish FILE validity.
Distinct symbolic roles, not an assertion that their storage is disjoint. The program-name aliases may name the same native cells.
Symbol resolution reaches the cells themselves, not the FILE or character buffer stored in them. Module linking supplies this map.
Concrete exposed cells at a successful entry. Program names have independently readable NUL-terminated contents; they are not silently identified with the launcher's copied argv0. Program code may subsequently replace their pointer values. Stream object validity, libc/TLS state and separation remain separate premises.
The ordinary non-atomic pointer-load protocol recovers exactly the stored address AND capability, not an external/null surrogate.
Explore proof 5 tactics
Initial goal
intros m cell a c _ & _ & _ & _ & Hbytes & Haux
unfold pointer_load_effects , pointer_load_effect , aux_at
simpl
rewrite Hbytes , Haux
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The three words the launcher passes to main: argc, argv, envp.
Hello's two-parameter main binds the first two launcher words and ignores the extra environment word. This gives its actual fresh frame, without restricting the strings or resetting runtime state.
Explore proof 4 tactics
Initial goal
intros f b blocks an vn argc argv envp Hp Hb Hv
unfold call_frame
rewrite Hp , Hb , Hv
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The byte size of the launcher's argv copy, 8 * (argc + 1). The native expression argc + 1 is evaluated as int BEFORE the checked size multiplication. Readable entry and successful copying are distinct: INT_MAX is an ABI value but overflows that expression.
For argc from 1 below INT_MAX (2^31 - 1), argc + 1 does not overflow int and the copy size is a positive legal allocation size (max_allocation_size).
Explore proof 3 tactics
Initial goal
intros argc H
unfold argv_copy_size , max_allocation_size
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
If string_slots holds from a, the slot of the i-th text, at a + 8 * i, points at a C string with that text.
Explore proof 13 tactics
Initial goal
intros m texts
induction texts as | head rest IH ; intros a i text Hslots Hi
2 openfocused goal
–destruct i ; discriminate Hi
deferred goal
–destruct Hslots as p & Hp & Hs & Hrest
destruct i as | i
2 openfocused goal
+injection Hi as ←
2 opendeferred goal
replace a + 8 × Z.of_nat0 with a by lia
2 opendeferred goal
eauto
deferred goal
+simpl in Hi
destruct IH_ _ _ Hrest Hi as q & Hq & Htext
exists q
replace a + 8 × Z.of_natSi with a + 8 + 8 × Z.of_nati by lia
auto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
If string_slots holds from a, the slot after the last text is null.
Explore proof 10 tactics
Initial goal
intros m texts
induction texts as | text rest IH ; intros a H
2 openfocused goal
–replace a + 8 × Z.of_natlength[ ] with a by simpl ; lia
2 opendeferred goal
exact H
deferred goal
–destruct H as p & _ & _ & H
specialize IH_ H
change pointer_slotm a + 8 × Z.of_natSlengthrest mkPtr0 CNone
rewrite Nat2Z.inj_succ
replace a + 8 × Z.succZ.of_natlengthrest with a + 8 + 8 × Z.of_natlengthrest by lia
exact IH
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
In an entry image (startup_at), argv's i-th slot points at a C string with the i-th argument, for any finite arguments.
Explore proof 2 tactics
Initial goal
intros m argc argv envp args environment i text _ & _ & _ H & _ Hi
exact string_slots_nth_ _ _ _ _ H Hi
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Likewise, envp's i-th slot points at the i-th environment string.
Explore proof 2 tactics
Initial goal
intros m argc argv envp args environment i text _ & _ & _ & _ H Hi
exact string_slots_nth_ _ _ _ _ H Hi
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
In an entry image, argv's slot argc and envp's slot after the last environment string are null.
Explore proof 2 tactics
Initial goal
intros m argc argv envp args environment _ & → & _ Ha & _ He
split ; apply string_slots_sentinel ; assumption
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
For a function f with no parameters, a first block b and no variadic arguments, call_frame with the launcher's three words gives the same fresh frame as with none: C's main(void) ignores the launcher's extra arguments. Do not replace a general entry by a launcher with an empty argv.
Explore proof 4 tactics
Initial goal
intros f b blocks argc argv envp Hp Hb Hv
unfold call_frame
rewrite Hp , Hb , Hv
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The exit status the process reports for main's or exit's status: its low byte, not a second acceptance or flush event. This conversion will be used only AFTER shutdown.
A process status is a byte.
Explore proof 4 tactics
Initial goal
intros status
unfold process_status
apply Z.mod_pos_bound
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Constructing the launcher's copied strings
The source bytes here describe native argv/environ strings, before they enter the capability model. This is the memcpy suboperation, including the NUL. It never creates a pointer capability by copying raw bytes; only the actual allocator answer creates that identity.
Copy bytes to address a, then write one NUL; copy no capability.
Copying the bytes and NUL leaves every object's region unchanged.
Explore proof 1 tactics
Initial goal
induction bytes ; intros ; simpl ; reflexivity | rewrite IHbytes ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Byte copying changes no stored capabilities, even inside the copy.
Explore proof 1 tactics
Initial goal
induction bytes ; intros ; simpl ; reflexivity | rewrite IHbytes ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Bytes before the copy or at and beyond its end keep their old values.
Explore proof 18 tactics
Initial goal
induction bytes as | head rest IH ; intros m a b Hout
2 openfocused goal
–simpl
2 opendeferred goal
destruct a ≤? b && b <? a + 1 eqn: E ; | reflexivity
2 opendeferred goal
apply andb_true_iff in E as E1 E2
2 opendeferred goal
apply Z.leb_le in E1
2 opendeferred goal
apply Z.ltb_lt in E2
2 opendeferred goal
simpl in Hout
2 opendeferred goal
lia
deferred goal
–change m_bytescopy_c_bytesstore_bytesm a 1 head a + 1 rest b = m_bytesm b
change b < a ∨ a + Z.of_natSlengthrest + 1 ≤ b in Hout
rewrite Nat2Z.inj_succ in Hout
rewrite IH by lia
simpl
destruct a ≤? b && b <? a + 1 eqn: E ; | reflexivity
apply andb_true_iff in E as E1 E2
apply Z.leb_le in E1
apply Z.ltb_lt in E2
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Nonzero byte values are copied exactly, with the first NUL just after them.
Explore proof 22 tactics
Initial goal
induction bytes as | b rest IH ; intros m a Hbytes
2 openfocused goal
–simpl
2 opendeferred goal
rewrite Z.leb_refl
2 opendeferred goal
assert a <? a + 1 = true as E by apply Z.ltb_lt ; lia
2 opendeferred goal
rewrite E
2 opendeferred goal
replace a − a with 0 by lia
2 opendeferred goal
reflexivity
deferred goal
–inversion Hbytes as | head tail Hb Hrest ; subst
simpl
split ; exact Hb |
split
2 openfocused goal
+rewrite copy_c_bytes_outside by lia
2 opendeferred goal
pose proof stored_bytem a 1 b 0 ltac:lia as Hstored
2 opendeferred goal
replace a + 0 with a in Hstored by lia
2 opendeferred goal
rewrite Hstored
2 opendeferred goal
unfold byte_of
2 opendeferred goal
change b / 1 mod 256 = b
2 opendeferred goal
rewrite Z.div_1_r
2 opendeferred goal
apply Z.mod_small
2 opendeferred goal
lia
deferred goal
+apply IH
exact Hrest
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A copied fresh string cannot modify any old object, not just an enumerated set of startup roots. This frame will retain earlier strings while subsequent launcher allocations/copies take place.
Explore proof 7 tactics
Initial goal
intros m q base bytes a _ & _ & _ & _ & Hdis & _ Hsize old & reg & Hreg & Hrange
specialize Hdisold reg Hreg
split
2 openfocused goal
–rewrite copy_c_bytes_outside by lia
2 opendeferred goal
reflexivity
deferred goal
–rewrite copy_c_bytes_aux
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Startup keeps all old regions exactly and all old-object bytes and capabilities outside the pointer slots it is filling. New objects need not be unchanged; their contents are constructed separately.
Allocating and copying a fresh string frames every old object.
Explore proof 8 tactics
Initial goal
intros m q base bytes lo hi Hfresh Hsize
split
2 openfocused goal
–intros b reg H
2 opendeferred goal
rewrite copy_c_bytes_regions
2 opendeferred goal
eapply allocated_old_region ; | exact H
2 opendeferred goal
exact proj1proj2proj2proj2Hfresh
deferred goal
–intros a Hin _
eapply copied_string_old_object ; eauto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A startup frame transports old access checks without ending lifetimes.
Explore proof 4 tactics
Initial goal
intros m m′ lo hi a c size rights align Hr _ Ha
unfold access_res , cap_access_res in Ha
destruct c as | b | b | f | f ; try discriminate
2 openfocused goal
all: destruct object_regionb m_regionsm as reg | eqn: E ; try discriminate ; unfold access_res , cap_access_res ; rewrite Hr_ _ E ; exact Ha
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Framing an old object leaves it an object for later allocations.
Explore proof 3 tactics
Initial goal
intros m m′ lo hi a Hr _ b & reg & E & H
exists b, reg
auto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Consecutive construction steps may write in adjoining slot ranges.
Explore proof 12 tactics
Initial goal
intros m m1 m2 lo mid hi Hbounds Hr1 Hb1 Hr2 Hb2
split
2 openfocused goal
–intros b reg H
2 opendeferred goal
auto
deferred goal
–intros a Hin Hout
assert Hin1 : in_objectm1 a
2 openfocused goal
{destruct Hin as b & reg & E & H
2 opendeferred goal
exists b, reg
2 opendeferred goal
auto
deferred goal
destruct Hb2a Hin1 ltac:lia as Hbytes Haux
rewrite Hbytes , Haux
apply Hb1 ; auto ; lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A store writes the address bytes and the capability of a pointer.
A pointer store frames every old byte and capability outside its slot.
Explore proof 15 tactics
Initial goal
intros m a p
split ; intros ; assumption |
intros b Hin Hout
unfold startup_store
simpl
assert a ≤? b && b <? a + 8 = false as E
2 open{apply Bool.not_true_is_false
2 openintros H
2 openapply andb_true_iff in H as H1 H2
2 openapply Z.leb_le in H1
2 openapply Z.ltb_lt in H2
2 openlia
assert b =? a = false as E′ by apply Z.eqb_neq ; lia
rewrite E , E′
auto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
An old checked pointer slot survives a frame disjoint from its eight bytes.
Explore proof 9 tactics
Initial goal
intros m m′ lo hi a p _ Hb Ha Hdis Hp Hbytes Haux
split ; exact Hp |
split
2 openfocused goal
–rewrite <- Hbytes
2 opendeferred goal
apply load_bytes_agree ; lia |
2 opendeferred goal
intros i Hi
2 opendeferred goal
apply proj1Hba + i Haa + i ltac:lia Hdisa + i ltac:lia
deferred goal
–rewrite proj2Hba Haa ltac:lia Hdisa ltac:lia
exact Haux
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
C-string contents depend only on their payload bytes and final NUL.
Explore proof 15 tactics
Initial goal
induction bytes as | b rest IH ; intros m m′ a Hb Hs
2 open–simpl in *
2 openrewrite Hb by lia
2 openexact Hs
–destruct Hs as Hbyte Hhead Hrest
simpl
split ; exact Hbyte |
split
2 open+rewrite Hb ; exact Hhead | simpl ; lia
+apply IHm m′ ; | exact Hrest
intros x Hx
apply Hb
change a ≤ x < a + Z.of_natSlengthrest + 1
rewrite Nat2Z.inj_succ
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A frame disjoint from an old string preserves its complete checked NUL.
Explore proof 6 tactics
Initial goal
intros m m′ lo hi p bytes Hf Ha Hs Hdis
split
2 openfocused goal
–eapply startup_frame_access ; eauto
deferred goal
–eapply string_at_agree ; | exact Hs
intros a Hrange
apply proj1proj2Hf a ltac:eapply access_in ; exact Ha | lia Hdisa Hrange
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A construction that frames every old object retains old vectors too.
Explore proof 24 tactics
Initial goal
induction texts as | text rest IH ; intros m m′ a Hf Hin Hslots
2 openfocused goal
–eapply startup_frame_slot ; exact Hf | | intros ; lia | exact Hslots
2 opendeferred goal
intros b Hb
2 opendeferred goal
apply Hin
2 opendeferred goal
simpl
2 opendeferred goal
lia
deferred goal
–destruct Hslots as p & Hp & Hs & Hr
exists p
split
2 openfocused goal
+eapply startup_frame_slot ; exact Hf | | intros ; lia | exact Hp
2 opendeferred goal
intros b Hb
2 opendeferred goal
apply Hin
2 opendeferred goal
change a ≤ b < a + 8 × Z.of_natSlengthrest + 1
2 opendeferred goal
rewrite Nat2Z.inj_succ
2 opendeferred goal
lia
deferred goal
+split
2 openfocused goal
∗eapply startup_frame_string ; exact Hf | exact Hs |
2 opendeferred goal
intros ; lia
deferred goal
∗apply IHm m′ ; exact Hf | | exact Hr
intros b Hb
apply Hin
change a ≤ b < a + 8 × Z.of_natSlengthrest + 1
rewrite Nat2Z.inj_succ
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The readable pointer array and every pointed-to string survive later copies.
Explore proof 6 tactics
Initial goal
intros m m′ table texts Hf Ha Hslots
split
2 openfocused goal
–eapply startup_frame_access ; eauto
deferred goal
–eapply startup_frame_slots ; exact Hf | | exact Hslots
intros b Hb
eapply access_in ; exact Ha | exact Hb
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Launcher allocation/copying preserves each exposed old pointer cell, including its write authority, address bytes and capability.
Explore proof 16 tactics
Initial goal
intros m m′ cell value Hframe Hw & Hr & Hwr & Hslot
split
2 openfocused goal
–destruct Hw as Hn & b & reg & Hcap & Hreg & Hlive & Ha
2 opendeferred goal
split ; exact Hn |
2 opendeferred goal
exists b, reg
2 opendeferred goal
split ; exact Hcap |
2 opendeferred goal
split
3 openfocused goal
deferred goal
+apply proj1Hframe
3 opendeferred goal
deferred goal
exact Hreg
2 opendeferred goal
deferred goal
+split ; exact Hlive |
2 opendeferred goal
eapply startup_frame_access ; eauto
deferred goal
–split ; eapply startup_frame_access ; eauto |
split ; eapply startup_frame_access ; eauto |
eapply startup_frame_slot ; exact Hframe | | intros ; lia | exact Hslot
intros a Ha
eapply access_in ; exact Hr | exact Ha
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Exposed libc cells and their readable name payloads survive the two successful launcher-copy loops. This preserves module data; it does not construct or assume native FILE/TLS validity.
Explore proof 14 tactics
Initial goal
intros m m′ g out err full short Hf Ho & He & Hn & Hs & Hfull & Hshort
split ; eapply startup_frame_exposed_cell ; eauto |
split ; eapply startup_frame_exposed_cell ; eauto |
split ; eapply startup_frame_exposed_cell ; eauto |
split ; eapply startup_frame_exposed_cell ; eauto |
split
2 openfocused goal
–destruct Hfull as bytes H
2 opendeferred goal
exists bytes
2 opendeferred goal
eapply startup_frame_string ; eauto
2 opendeferred goal
intros ; lia
deferred goal
–destruct Hshort as bytes H
exists bytes
eapply startup_frame_string ; eauto
intros ; lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Sixteen-byte rounding provides at least the original positive request.
Explore proof 6 tactics
Initial goal
intros size Hsize
unfold heap_req
simpl
pose proof Z.mod_pos_boundsize + 15 16 ltac:lia
pose proof Z.div_modsize + 15 16 ltac:lia
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The table's actual object, bounds and alignment justify each slot access.
Explore proof 11 tactics
Initial goal
intros m table end_ a size rights align Hr Hlo Hhi Ha
unfold access_res , cap_access_res
rewrite Hr
simpl
assert table ≤? a && a + size ≤? end_ = true as E
2 openfocused goal
{apply andb_true_iff
2 opendeferred goal
split ; apply Z.leb_le ; lia
deferred goal
rewrite E
unfold aligned_res
rewrite Ha
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Startup copying over the caller's exact machine instance.
The external-call effects of this machine.
Copying through supplied write authority is a finite path of local effects.
Explore proof 21 tactics
Initial goal
induction bytes as | head rest IH ; intros sources roots releases requests s m born a Hw
2 openfocused goal
–eapply E.effects_local with m1 := store_bytesm a 1 0
3 openfocused goal
deferred goal
+apply local_store_bytes
3 opendeferred goal
deferred goal
intros b Hb
3 opendeferred goal
deferred goal
apply Hw
3 opendeferred goal
deferred goal
simpl
3 opendeferred goal
deferred goal
lia
2 opendeferred goal
deferred goal
+constructor
deferred goal
–eapply E.effects_local with m1 := store_bytesm a 1 head
2 openfocused goal
+apply local_store_bytes
2 opendeferred goal
intros b Hb
2 opendeferred goal
apply Hw
2 opendeferred goal
change a ≤ b < a + Z.of_natSlengthrest + 1
2 opendeferred goal
rewrite Nat2Z.inj_succ
2 opendeferred goal
lia
deferred goal
+apply IH
intros b Hb
apply Hw
change a ≤ b < a + Z.of_natSlengthrest + 1
rewrite Nat2Z.inj_succ
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Success remains conditional on the runtime's real answer, for the original strlen + 1 request. No small fixed bound or NULL-success case is introduced. The result includes the entire checked NUL.
Proof 63 steps Qed
Append two actual effect paths, retaining the same contract authority.
Explore proof 2 tactics
Initial goal
intros sources roots releases requests s m born s1 m1 born1 s2 m2 born2 H
induction H ; intros Htail ; eauto using E.effects_local , E.effects_alloc
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Preconditions on copied pre-NUL payloads and their original allocation sizes.
Fill a preallocated pointer table in forward order. None says only that this successful construction did not complete, not why native startup ended. Each allocation uses the preceding runtime state.
Allocate the pointer table first, even when there are no strings. Fresh zero bytes and capabilities supply its sentinel, not a synthetic final store. Allocation failures remain unclassified.
The forward loop retains earlier strings and the sentinel while writing only its remaining slots in the already-born table.
Proof 97 steps Qed
A successful table-first construction gives a checked writable vector and frames every object that existed before its table.
Proof 66 steps Qed
The environment's count, increment and checked multiplication fit size_t whenever its original table request is legal. Unlike argv, this count is not restricted to signed int.
Explore proof 3 tactics
Initial goal
intros n H
unfold max_allocation_size in H
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Compose the argv and environment memory constructions. This is not the complete native launcher trace: obtaining/tracking main between the two loops, auxv and libc initialization still need coverage.
Explore proof 15 tactics
Initial goal
intros args environment s m born argv s1 m1 born1 envp s2 m2 born2 sources roots releases requests Ha He Hr Hargc Hargs Henv Hmax Hrequesta Hrequeste
pose proof proj2argv_copy_bounds_ Hargc as Hargmax
unfold argv_copy_size in Hargmax
destruct copy_vector_correctargs s m born argv s1 m1 born1 sources roots releases requests Ha Hr Hargs ltac:lia Hrequesta as Hea & Hr1 & Hp1 & Hf1 & Hva & Hwa
destruct copy_vector_correctenvironment s1 m1 born1 envp s2 m2 born2 sources roots releases requests He Hr1 Henv Hmax Hrequeste as Hee & Hr2 & Hp2 & Hf2 & Hve & Hwe
split ; eapply effects_trans ; eauto |
split ; exact Hr2 |
split
2 openfocused goal
–eapply persists_trans ; eauto
deferred goal
–split
2 openfocused goal
+eapply startup_frame_join with mid := 0 ; lia | exact Hf1 | exact Hf2
deferred goal
+split ; lia |
split ; reflexivity |
split ; | exact Hve
eapply startup_frame_vector ; eauto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A ready entry frame for a linked two-parameter main after the successful launcher copies. Existing global cells and name strings survive; the linked symbol map and exact runtime state are retained. FILE/TLS validity and the program's logical precondition are still separate trusted entry obligations, not consequences of copying.
Explore proof 12 tactics
Initial goal
forall (args environment : list (list Z)) (s : R.state)
(m : mem) (born : list Z) (argv : ptr) (s1 : R.state)
(m1 : mem) (born1 : list Z) (envp : ptr) (s2 : R.state)
(m2 : mem) (born2 : list Z) (sources roots : list span)
(releases : list Z) (requests : Z -> Z -> Prop)
(ge : genv) (g : libc_global_cells) (out err full short : ptr)
(f : func) (b : block) (blocks : list block) (an vn : name)
(fuel : Z),
copy_vector args s m born = Some (argv, s1, m1, born1) ->
copy_vector environment s1 m1 born1 = Some (envp, s2, m2, born2) ->
R.ready s m ->
1 <= Z.of_nat (Datatypes.length args) < 2 ^ 31 - 1 ->
payloads_allowed requests args ->
payloads_allowed requests environment ->
8 * (Z.of_nat (Datatypes.length environment) + 1) <= max_allocation_size ->
requests 16 (8 * (Z.of_nat (Datatypes.length args) + 1)) ->
requests 16 (8 * (Z.of_nat (Datatypes.length environment) + 1)) ->
libc_globals_bound ge g ->
libc_globals_at m g out err full short ->
find_fn ge (TAtom "main") = Some (Defined f) ->
fn_params f = [(W, an); (P, vn)] ->
fn_blocks f = b :: blocks ->
variadic_func f = false ->
exists fr : frame,
call_frame f (main_arguments ... ... ...) = Some fr /\
find_fn ... ... = Some ... /\
E.effects ... ... ... ... ... ... ... ... ... ... /\ ... /\ ...intros args environment s m born argv s1 m1 born1 envp s2 m2 born2 sources roots releases requests ge g out err full short f b blocks an vn fuel Ha He Hr Hargc Hargs Henv Hmax Hra Hre Hbound Hglobals Hfind Hp Hb Hv
destruct copied_startupargs environment s m born argv s1 m1 born1 envp s2 m2 born2 sources roots releases requests Ha He Hr Hargc Hargs Henv Hmax Hra Hre as Heffects & Hr2 & Hpersists & Hframe & Hstartup
eexists
2 openshelved goal
split ; eapply main_argv_frame ; eauto |
split ; exact Hfind |
split ; exact Heffects |
split ; exact Hr2 |
split ; exact Hpersists |
split ; exact Hframe |
split ; exact Hstartup |
split ; exact Hbound |
eapply startup_frame_libc_globals ; eauto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Standalone wrapper for existing entry clients.
Entry regressions
Two arguments of unequal lengths, including the empty string, and an empty environment distinguish argc, slot spacing and sentinels. The fixture reuses the independent hello string, not its fake ABI.
argv: a three-slot array at 4096.
envp: a one-slot array at 4200, the sentinel alone.
hello_mem plus the two arrays: argv's slots point at hello (with its read-only capability) and at an empty string in the object at 3072, then null; envp's only slot is null.
entry_mem is an entry image with argc 2, arguments hello and the empty string, and no environment.
Explore proof 12 tactics
Initial goal
split ; lia |
split ; reflexivity |
split
2 openfocused goal
–split ; reflexivity |
2 opendeferred goal
exists hello_ptr
2 opendeferred goal
split ; vm_compute ; repeat split ; congruence |
2 opendeferred goal
split ; vm_compute ; repeat split ; congruence |
2 opendeferred goal
exists mkPtr3072 Obj3072
2 opendeferred goal
vm_compute
2 opendeferred goal
repeat split ; congruence
deferred goal
–vm_compute
repeat split ; congruence
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
argc must count the arguments.
Explore proof 2 tactics
Initial goal
intros _ & H & _
discriminate H
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A nonzero address in argv's sentinel slot is not a string_vector.
Explore proof 3 tactics
Initial goal
intros _ H
pose proof string_slots_sentinel_ _ _ H as _ & Hbits & _
discriminate Hbits
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Nor is a slot whose aux lost its capability, though its address bytes are right.
Explore proof 5 tactics
Initial goal
intros _ p & _ & Hbits & Hcap & Hread _ & _
change 1024 = ptr_addrp in Hbits
change CNone = ptr_capp in Hcap
rewrite <- Hbits , <- Hcap in Hread
discriminate Hread
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Nor an argv object too small to hold the sentinel slot.
Explore proof 2 tactics
Initial goal
intros H _
discriminate H
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Nor a slot whose address bytes point one byte into the string.
Explore proof 5 tactics
Initial goal
intros _ p & _ & Hbits & _ & _ Hstring & _
change 1025 = ptr_addrp in Hbits
rewrite <- Hbits in Hstring
destruct Hstring as _ & Hbyte & _
discriminate Hbyte
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Nor a string whose NUL was overwritten.
Explore proof 5 tactics
Initial goal
intros _ p & _ & Hbits & _ & _ Hstring & _
change 1024 = ptr_addrp in Hbits
rewrite <- Hbits in Hstring
destruct Hstring as _ & _ & _ & _ & _ & _ & _ & _ & _ & _ & Hnul
discriminate Hnul
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The largest argc whose copy size is computable, INT_MAX - 1, gives 17179869176 bytes; at INT_MAX, argc + 1 overflows int.
Explore proof 1 tactics
Initial goal
split ; reflexivity | lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Status 513 reports 1, and -1 reports 255.
Explore proof 1 tactics
Initial goal
split ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Construction, not a preassumed final entry image. All old argument table bytes/capabilities stay; high bytes are not interpreted as text, and the NUL must fit the new object's checked bounds.
An empty string needs one byte for its NUL, within a rounded 16-byte object.
Explore proof 1 tactics
Initial goal
repeat split ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
High bytes survive exactly, along with the old pointer slot and environment.
Explore proof 2 tactics
Initial goal
vm_compute
repeat constructor ; discriminate
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Sixteen payload bytes need a seventeenth NUL byte and a 32-byte extent.
Explore proof 2 tactics
Initial goal
vm_compute
repeat constructor ; discriminate
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Correct payload bytes are insufficient when the NUL lies outside the object.
Explore proof 2 tactics
Initial goal
intros H _
discriminate H
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A pre-NUL payload contains neither a zero nor a value outside the byte range.
Explore proof 1 tactics
Initial goal
split ; intros H ; inversion H as | head rest Hb Hrest ; subst ; inversion Hrest as | head tail Hbad Htail ; subst ; lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Executable construction examples use the ordinary interpreter runtime.
Table first, then three strings in forward order, with distinct sizes and contents. Old pointer bytes and read-only authority stay.
Explore proof 2 tactics
Initial goal
vm_compute
repeat constructor ; discriminate
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The environment copy preserves the earlier argv and its strings; an empty environment still allocates a checked sentinel table.
Explore proof 2 tactics
Initial goal
vm_compute
repeat constructor ; discriminate
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A populated environment uses its own forward copy loop and sentinel, retaining the earlier argv even through two further string allocations.
Explore proof 2 tactics
Initial goal
vm_compute
repeat constructor ; discriminate
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A resource-refusing allocator does not produce a successful empty table.
Explore proof 1 tactics
Initial goal
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Environment counts above INT_MAX are not rejected by argv's int rule.
Explore proof 4 tactics
Initial goal
intros n H
rewrite H
unfold max_allocation_size
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
An independent initialized module, not a preassumed cell predicate. Opaque stream storage is only raw data here, deliberately not FILE validity. Both names share a read-only object; short is interior.
The actual initialized symbol map and memory of exposed_module.
The initializer really succeeds at the hand-computed cell addresses.
Explore proof 2 tactics
Initial goal
vm_compute
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Exact cell identities, independent of the values stored in them.
Symbol lookup reaches cells while the initialized contents point elsewhere, with the name's exact read-only capability.
Explore proof 17 tactics
Initial goal
split ; vm_compute ; repeat split ; reflexivity |
unfold libc_globals_at
repeat split;lazymatch goal with|- ∃_, _⇒idtac_⇒vm_compute ; congruenceend
6 openfocused goal
focused goal
focused goal
focused goal
focused goal
–exists 66048, mkRegion66048 66056 GlobalData Live
6 opendeferred goal
deferred goal
deferred goal
deferred goal
deferred goal
repeat split ; reflexivity
5 opendeferred goal
deferred goal
deferred goal
deferred goal
deferred goal
–exists 66080, mkRegion66080 66088 GlobalData Live
5 opendeferred goal
deferred goal
deferred goal
deferred goal
repeat split ; reflexivity
4 opendeferred goal
deferred goal
deferred goal
deferred goal
–exists 66112, mkRegion66112 66120 GlobalData Live
4 opendeferred goal
deferred goal
deferred goal
repeat split ; reflexivity
3 opendeferred goal
deferred goal
deferred goal
–exists 66144, mkRegion66144 66152 GlobalData Live
3 opendeferred goal
deferred goal
repeat split ; reflexivity
2 opendeferred goal
deferred goal
–exists 120; 47; 104
2 opendeferred goal
vm_compute
2 opendeferred goal
repeat split ; reflexivity
deferred goal
–exists 104
vm_compute
repeat split ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Ordinary pointer loads recover different stored addresses and the exact mutable/read-only authority, not the cells' own capabilities.
Explore proof 2 tactics
Initial goal
vm_compute
split ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A basename can be the empty suffix in the same name object.
Explore proof 4 tactics
Initial goal
split ; | vm_compute ; repeat split ; reflexivity
repeat split;lazymatch goal with|- ∃_, _⇒idtac_⇒vm_compute ; congruenceend
exists 66144, mkRegion66144 66152 GlobalData Live
repeat split ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Right address bits do not compensate for missing stored authority.
Explore proof 2 tactics
Initial goal
intros _ & _ & _ & _ & _ & Haux
discriminate Haux
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Correct aux does not compensate for wrong stored address bits.
Explore proof 2 tactics
Initial goal
intros _ & _ & _ & _ & Hbits & _
discriminate Hbits
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Pointee authority is not authority for accessing the pointer cell.
Explore proof 2 tactics
Initial goal
intros _ & Hr & _
discriminate Hr
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The full aligned word must fit the cell's object.
Explore proof 2 tactics
Initial goal
intros _ & Hr & _
discriminate Hr
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Sufficient raw extent does not waive pointer-load alignment.
Explore proof 2 tactics
Initial goal
intros _ & Hr & _
discriminate Hr
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.