rocq/theories/ExitMemory.v
A selected memory view of user-glibc's exit registry, not an executor or proof of native satisfaction. Layout is read from the pinned stdlib/exit.h and checked by compiling its extracted declarations with Fil-C: entry 32, block 1040, next/idx/fns at 0/8/16. Physical slots and logical pending registrations are distinct. Synchronization, callback admission and ownership remain separate obligations.
Tags 0/1 are skipped by the exit loop. A reserved slot is not an installed callback; arbitrary unknown flavors are not admitted. Tokens are ghost registration instances, never native slot indices/addresses.
| | | FreeSlot | ||
| | | ReservedSlot | ||
| | | OnSlot | ||
| | | AtSlot | ||
| | | CxaSlot |
A decoded function capability is not an admitted code specification.
Only the flavor-selected fields matter. In particular free/reserved slots impose no requirements on stale payloads. Cxa's DSO pointer is represented but not dereferenced by ordinary exit. Native pointer mangling is a no-op in this selected source, not in arbitrary glibc.
Flavor, not the public API's spelling, selects the callback form. This pin's atexit stores ef_cxa with null argument and DSO; adapting that to logical AtExit requires a separate calling-convention contract.
Native slots are stored oldest first; exit scans downward, skipping holes.
The slots below idx, not an assertion that idx counts live callbacks.
Full readable containing-object bounds/alignment are independent of pointer-slot decoding. Slots at or above idx are deliberately ignored. Writable spans are NOT inferred from this read-only view.
The actual next-slot value for this finite suffix.
A finite null-terminated chain, linked by decoded pointer capabilities.
Block identities are distinct, not merely the pointers' address bits in next slots. Base capabilities in exit_block_memory tie them together.
Blocks are visited head-first; each block is scanned in reverse slot order.
Callback specifications and retained argument requirements are independent of decoded Fn capabilities. Active evidence is detached from any old slot: idx has already decreased, and cxa may already have cleared it.
Release eligibility AFTER unlinking, not a memory transition. Explicit ownership, an exhausted live Heap base, enough extent, a distinct nonempty successor chain and the updated head are all required. Merely reading a block, finding it live, or observing next != NULL confers no ownership.
A free hole at the next index consumes no pending registration.
Explore proof 4 tactics
Initial goal
intros
unfold exit_pending
rewrite rev_app_distr
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Reserved physical slots are skipped too, not treated as installed code.
Explore proof 4 tactics
Initial goal
intros
unfold exit_pending
rewrite rev_app_distr
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Popping an installed slot detaches its registration before callback entry. This is a projection lemma, not construction of native write effects.
Explore proof 6 tactics
Initial goal
intros slots slot entry H
unfold exit_pending
rewrite rev_app_distr
simpl
rewrite H
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Decoding a represented slot also supplies checked containing-object access.
Explore proof 2 tactics
Initial goal
intros m block next i slot _ & Hread & _ & _ & _ & Hslots Hi
auto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Being the last node prevents release even if the caller owns a live heap block.
Explore proof 3 tactics
Initial goal
intros owned m head block _ & _ & Hnonempty & _
apply Hnonempty
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A readable, writable or live block is still not a release permission.
Explore proof 2 tactics
Initial goal
intros m head block rest Howned _
exact Howned
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The array's fixed native capacity rejects idx=33, independently of memory.
Explore proof 3 tactics
Initial goal
intros m p next _ & _ & _ & _ & Hlength & _
simpl in Hlength
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Repeated blocks cannot form a selected registry, even if slot bytes look linked.
Explore proof 3 tactics
Initial goal
intros m head block _ & _ & _ & Hdistinct
inversion Hdistinct ; subst
match goal withHnot : ¬In_ _ |- _⇒apply Hnot ; left ; reflexivityend
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Constructing one pop, before callback execution
The native index decrement; older is the prefix left after the pop.
Native cxa removal also clears its flavor, after decrementing idx. Payload bytes and every auxiliary capability remain untouched.
Only idx and, for cxa, the removed flavor need write authority. A readable containing block is not this permission.
The head cell and other block storage must not alias this block. Distinct object identities alone do not establish byte separation.
A byte store preserves all reads disjoint from its actual footprint.
Explore proof 9 tactics
Initial goal
intros m a n x b size Hsize Hdis
apply load_bytes_agree ; exact Hsize |
intros i Hi
simpl
destruct a ≤? b + i && b + i <? a + n eqn: E ; | reflexivity
apply Bool.andb_true_iff in E as Hlo Hhi
apply Z.leb_le in Hlo
apply Z.ltb_lt in Hhi
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A pointer slot depends on its eight bytes and its own shadow entry.
Explore proof 10 tactics
Initial goal
intros m m′ a p Haux Hb Hp & Hload & Hcap
split ; exact Hp |
split
2 open–rewrite <- Hload
2 openapply load_bytes_agree ; lia |
2 openintros i Hi
2 openapply Hb
2 openlia
–rewrite Haux
exact Hcap
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Physical slot decoding is framed by its 32 bytes and unchanged shadow.
Explore proof 31 tactics
Initial goal
intros m m′ a slot Haux Hb Hslot
assert Hload : ∀off, 0 ≤ off ≤ 24 → load_bytesm′ a + off 8 = load_bytesm a + off 8
2 openfocused goal
{intros off Hoff
2 opendeferred goal
apply load_bytes_agree ; lia |
2 opendeferred goal
intros i Hi
2 opendeferred goal
apply Hb
2 opendeferred goal
lia
deferred goal
assert Hptr : ∀off p, 0 ≤ off ≤ 24 → pointer_slotm a + off p → pointer_slotm′ a + off p
2 openfocused goal
{intros off p Hoff
2 opendeferred goal
apply exit_pointer_agree ; apply Haux ; lia |
2 opendeferred goal
intros b Hrange
2 opendeferred goal
apply Hb
2 opendeferred goal
lia
deferred goal
assert Hzero : load_bytesm′ a 8 = load_bytesm a 8
2 openfocused goal
{replace a with a + 0 by lia
2 opendeferred goal
apply Hload
2 opendeferred goal
lia
deferred goal
destruct slot ; simpl in * ; rewrite Hzero ; try exact Hslot
3 openfocused goal
focused goal
–destruct Hslot as Htag & Hfn Hcap & Harg
3 opendeferred goal
deferred goal
split ; exact Htag |
3 opendeferred goal
deferred goal
split
4 openfocused goal
deferred goal
deferred goal
+split ; apply Hptr ; lia | exact Hfn | exact Hcap
3 opendeferred goal
deferred goal
deferred goal
+apply Hptr ; lia | exact Harg
2 opendeferred goal
deferred goal
–destruct Hslot as Htag & Hfn Hcap
2 opendeferred goal
split ; exact Htag |
2 opendeferred goal
split ; apply Hptr ; lia | exact Hfn | exact Hcap
deferred goal
–destruct Hslot as Htag & Hfn Hcap & Harg & Hdso
split ; exact Htag |
split
2 openfocused goal
+split ; apply Hptr ; lia | exact Hfn | exact Hcap
deferred goal
+split ; apply Hptr ; try lia ; assumption
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A block view is preserved by an exact frame over its full storage.
Explore proof 27 tactics
Initial goal
intros m m′ block next Hregions Haux Hb Hcap & Hread & Hnext & Hidx & Hlen & Hslots
split ; exact Hcap |
split
2 openfocused goal
–unfold access_res
2 opendeferred goal
rewrite Hregions
2 opendeferred goal
exact Hread
deferred goal
–split
2 openfocused goal
+apply exit_pointer_agreem m′ ; apply Haux ; lia | | exact Hnext
2 opendeferred goal
intros b Hrange
2 opendeferred goal
apply Hb
2 opendeferred goal
lia
deferred goal
+split
2 openfocused goal
∗rewrite <- Hidx
2 opendeferred goal
apply load_bytes_agree ; lia |
2 opendeferred goal
intros i Hi
2 opendeferred goal
apply Hb
2 opendeferred goal
lia
deferred goal
∗split ; exact Hlen |
intros i slot Hi
assert i < lengthblock_slotsblock%nat by apply nth_error_Some ; congruence
apply Nat2Z.inj_lt in H
apply Nat2Z.inj_le in Hlen
apply exit_slot_memory_agreem m′ ; | | auto ; intros a Ha
2 openfocused goal
--apply Haux
2 opendeferred goal
lia
deferred goal
--apply Hb
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Exact metadata frames keep regions and shadow everywhere, and bytes outside the one or two narrow roots, not merely outside the block.
Explore proof 22 tactics
Initial goal
intros m p older selected
split ; destruct selected ; reflexivity |
split ; destruct selected ; reflexivity |
intros a Hout
assert Hidx : ptr_addrp + 8 ≤? a && a <? ptr_addrp + 8 + 8 = false
2 openfocused goal
{apply Bool.not_true_is_false
2 opendeferred goal
intros H
2 opendeferred goal
apply Bool.andb_true_iff in H as Hlo Hhi
2 opendeferred goal
apply Z.leb_le in Hlo
2 opendeferred goal
apply Z.ltb_lt in Hhi
2 opendeferred goal
apply Hout
2 opendeferred goal
exists mkSpanmkPtrptr_addrp + 8 ptr_capp 8
2 opendeferred goal
split ; left ; reflexivity | exact conjHlo Hhi
deferred goal
destruct selected ; cbn - [ Z.mul ] in * ; rewrite Hidx ; try reflexivity
destruct ptr_addrp + 16 + 32 × Z.of_natlengtholder ≤? a && a <? ptr_addrp + 16 + 32 × Z.of_natlengtholder + 8 eqn: E ; | reflexivity
exfalso
apply Hout
apply Bool.andb_true_iff in E as Hlo Hhi
apply Z.leb_le in Hlo
apply Z.ltb_lt in Hhi
eexists
2 opensplit ; right ; left ; reflexivity | exact conjHlo Hhi
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Every constructed write lies inside the original nonempty block.
Explore proof 11 tactics
Initial goal
intros m p older selected Hlen a Hout
apply proj2proj2exit_pop_framem p older selected
intros root & Hin & Ha
unfold exit_pop_writes in Hin
destruct Hin as [ <-| Hin ] ; unfold span_contains in Ha ; simpl in Ha ; lia |
destruct selected ; try contradiction
destruct Hin as [ <-| [ ] ]
unfold span_contains in Ha
cbn - [ Z.mul ] in Ha
apply Nat2Z.inj_lt in Hlen
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Decrementing idx leaves every older slot decoded, including free holes.
Explore proof 29 tactics
Initial goal
intros m p older selected next Hcap & Hread & Hnext & Hidx & Hlen & Hslots
cbn - [ Z.mul ] in *
rewrite length_app in Hlen
simpl in Hlen
split ; exact Hcap |
split ; exact Hread |
split
2 openfocused goal
–apply pointer_slot_bytes_disjointm ptr_addrp + 8 8 Z.of_natlengtholder ptr_addrp next ; lia | left ; lia | exact Hnext
deferred goal
–split
2 openfocused goal
+unfold exit_pop_index
2 opendeferred goal
rewrite stored_bytes_value by lia
2 opendeferred goal
apply Z.mod_small
2 opendeferred goal
split ; lia | apply Nat2Z.inj_le in Hlen ; cbn ; lia
deferred goal
+split ; simpl ; lia |
intros i slot Hi
change nth_errorolder i = Someslot in Hi
apply exit_slot_memory_agreem ; intros ; reflexivity | |
2 openfocused goal
∗intros a Ha
2 opendeferred goal
cbn - [ Z.mul ] in Ha
2 opendeferred goal
simpl
2 opendeferred goal
destruct ptr_addrp + 8 ≤? a && a <? ptr_addrp + 8 + 8 eqn: E ; | reflexivity
2 opendeferred goal
apply Bool.andb_true_iff in E as Hlo Hhi
2 opendeferred goal
apply Z.leb_le in Hlo
2 opendeferred goal
apply Z.ltb_lt in Hhi
2 opendeferred goal
lia
deferred goal
∗apply Hslots
rewrite nth_error_app1 ; exact Hi |
apply nth_error_Some
congruence
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A store beyond the represented prefix preserves its block view.
Explore proof 17 tactics
Initial goal
intros m block next a n x Hcap & Hread & Hnext & Hidx & Hlen & Hslots Hn Ha
split ; exact Hcap |
split ; exact Hread |
split
2 openfocused goal
–apply pointer_slot_bytes_disjoint ; lia | left ; lia | exact Hnext
deferred goal
–split ; rewrite exit_load_bytes_disjoint by lia ; exact Hidx |
split ; exact Hlen |
intros i slot Hi
apply exit_slot_memory_agreem ; intros ; reflexivity | | auto
assert i < lengthblock_slotsblock%nat by apply nth_error_Some ; congruence
apply Nat2Z.inj_lt in H
intros b Hb
simpl
destruct a ≤? b && b <? a + n eqn: E ; | reflexivity
apply Bool.andb_true_iff in E as Hlo Hhi
apply Z.leb_le in Hlo
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Cxa's flavor clear is outside the shortened represented prefix.
Explore proof 4 tactics
Initial goal
intros m p older selected next Hblock
pose proof exit_pop_index_representedm p older selected next Hblock as Hidx
destruct selected ; try exact Hidx
apply exit_block_store_after ; exact Hidx | lia | simpl ; lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The containing access supplies aligned field checks for either read or write, but not the independent writable-root permission/liveness.
Explore proof 17 tactics
Initial goal
intros m block next off rights Hcap & Hread & _ Hlo Hhi Hoff
rewrite Hcap in *
unfold access_res , cap_access_res in *
destruct object_regionptr_addrblock_ptrblock m_regionsm as reg | eqn: Hr ; try discriminate
destruct ptr_addrblock_ptrblock ≤? ptr_addrblock_ptrblock && ptr_addrblock_ptrblock + 1040 ≤? r_endreg eqn: Hbounds ; try discriminate
apply andb_true_iff in Hbounds as _ Hend
apply Z.leb_le in Hend
unfold aligned_res in Hread
destruct ptr_addrblock_ptrblock mod 8 =? 0 eqn: Halign ; try discriminate
apply Z.eqb_eq in Halign
assert ptr_addrblock_ptrblock ≤? ptr_addrblock_ptrblock + off && ptr_addrblock_ptrblock + off + 8 ≤? r_endreg = true as Hfield
2 openfocused goal
{apply andb_true_iff
2 opendeferred goal
split ; apply Z.leb_le ; lia
deferred goal
rewrite Hfield
unfold aligned_res
rewrite Z.add_mod , Halign , Hoff by lia
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Captured payload capabilities come from complete checked source slots; the source span grants no write authority and no callback specification.
Explore proof 18 tactics
Initial goal
intros m block next i off value Hblock Hi Hoff Halign _ & _ & Haux
assert Hbound : 16 + 32 × Z.of_nati + off + 8 ≤ 1040
2 openfocused goal
{destruct Hblock as _ & _ & _ & _ & Hlen & _
2 opendeferred goal
apply Nat2Z.inj_lt in Hi
2 opendeferred goal
apply Nat2Z.inj_le in Hlen
2 opendeferred goal
lia
deferred goal
right
right
left
exists mkSpanblock_ptrblock 1040, ptr_addrblock_ptrblock + 16 + 32 × Z.of_nati + off
split ; left ; reflexivity |
split ; unfold span_contains ; cbn - [ Z.add Z.mul ] ; lia |
split ; cbn - [ Z.add Z.mul ] ; lia |
split ; | symmetry ; exact Haux
replace ptr_addrblock_ptrblock + 16 + 32 × Z.of_nati + off with ptr_addrblock_ptrblock + 16 + 32 × Z.of_nati + off by lia
apply exit_block_field_accessm block next ; exact Hblock | lia | exact Hbound |
rewrite Z.add_mod16 + 32 × Z.of_nati off 8 , Z.add_mod16 32 × Z.of_nati 8 , Z.mul_mod32 Z.of_nati 8 , Halign by lia
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Capacity and containing alignment derive both native eight-byte stores.
Explore proof 16 tactics
Initial goal
intros m p older selected next Hblock
assert Hlen : lengtholder < 32%nat
2 openfocused goal
{destruct Hblock as _ & _ & _ & _ & Hlen & _
2 opendeferred goal
simpl in Hlen
2 opendeferred goal
rewrite length_app in Hlen
2 opendeferred goal
simpl in Hlen
2 opendeferred goal
lia
deferred goal
split ; exact Hlen |
split
2 openfocused goal
–exact exit_block_field_accessm mkExitBlockp older ++ selected next 8 Write Hblock ltac:lia ltac:lia eq_refl
deferred goal
–replace ptr_addrp + 16 + 32 × Z.of_natlengtholder with ptr_addrp + 16 + 32 × Z.of_natlengtholder by lia
apply exit_block_field_accessm mkExitBlockp older ++ selected next ; exact Hblock | lia | |
2 openfocused goal
+apply Nat2Z.inj_lt in Hlen
2 opendeferred goal
lia
deferred goal
+rewrite Z.add_mod , Z.mul_mod by lia
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Popping a separated nonempty head preserves the head pointer, remaining chain and identities. Exhausting a block does not unlink or release it.
Proof 31 steps Qed
An installed physical slot is exactly the first pending registration.
Explore proof 4 tactics
Initial goal
intros p older selected rest entry Hslot
change exit_pendingolder ++ selected ++ exit_registry_pendingrest = entry :: exit_pendingolder ++ exit_registry_pendingrest
rewrite exit_pending_popolder selected entry Hslot
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Skipping a hole stutters logically; it is not a callback or TLS action.
Explore proof 7 tactics
Initial goal
intros p older selected rest → | →
2 openfocused goal
–change exit_pendingolder ++ FreeSlot ++ exit_registry_pendingrest = exit_pendingolder ++ exit_registry_pendingrest
2 opendeferred goal
rewrite exit_pending_skip_free
2 opendeferred goal
reflexivity
deferred goal
–change exit_pendingolder ++ ReservedSlot ++ exit_registry_pendingrest = exit_pendingolder ++ exit_registry_pendingrest
rewrite exit_pending_skip_reserved
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The installed pop constructs the existing logical callback-entry edge; uniqueness is supplied independently, never inferred from slot addresses.
Explore proof 7 tactics
Initial goal
intros p older selected rest entry status consumed q Hslot before after Hunique
assert Hstep : shutdown_stepbefore InvokeCallbackentry status after
2 openfocused goal
{unfold before , after
2 opendeferred goal
rewrite exit_pop_pendingp older selected rest entry Hslot
2 opendeferred goal
constructor
deferred goal
split ; exact Hstep |
eapply shutdown_step_unique ; eauto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Admission specifications may depend on memory. Stability is a general footprint rule over any two snapshots, not the desired endpoint premise. In particular an argument that aliases idx needs separate justification.
The same exact frame transports every remaining and active admission.
Explore proof 11 tactics
Initial goal
intros admitted m p older selected rest entry Hslot Hstable Hall _
rewrite exit_pop_pendingp older selected rest entry Hslot in Hall
inversion Hall as [ |? ? Hentry Hrest ] ; subst
destruct exit_pop_framem p older selected as Hregions Haux Hbytes
assert Htransport : ∀item, admittedm item → admittedexit_pop_memorym p older selected item
2 openfocused goal
{apply Hstable ; assumption
deferred goal
split ; | apply Htransport ; exact Hentry
eapply Forall_impl ; | exact Hrest
intros item Hi
apply Htransport
exact Hi
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Construction uses the existing bounded-write effects, with no allocations or releases. Both the index-only prefix and cxa's final prefix are valid.
Writable roots survive these stores because their regions do not change.
Explore proof 23 tactics
Initial goal
intros sources s m p older selected Hw
assert Hindex : local_effectsources exit_pop_writesp older selected [ ] [ ] m exit_pop_indexm p older
2 openfocused goal
{apply local_store_bytes
2 opendeferred goal
intros a Ha
2 opendeferred goal
left
2 opendeferred goal
exists mkSpanmkPtrptr_addrp + 8 ptr_capp 8
2 opendeferred goal
split ; left ; reflexivity |
2 opendeferred goal
split ; inversion Hw ; assumption | exact Ha
deferred goal
assert Hprefix : E.effectssources exit_pop_writesp older selected [ ] λ_ _ ⇒ False s m [ ] s exit_pop_indexm p older [ ]
2 openfocused goal
{eapply E.effects_local ; exact Hindex | constructor
deferred goal
split ; exact Hprefix |
destruct selected ; try exact Hprefix
eapply E.effects_local ; exact Hindex |
eapply E.effects_local ; | constructor
apply local_store_bytes
intros a Ha
left
exists mkSpanmkPtrptr_addrp + 16 + 32 × Z.of_natlengtholder ptr_capp 8
split ; right ; left ; reflexivity |
split ; | exact Ha
change writable_spanm mkSpanmkPtrptr_addrp + 16 + 32 × Z.of_natlengtholder ptr_capp 8
inversion Hw as [ |? ? _ Htail ] ; subst
inversion Htail ; assumption
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Any runtime stays ready and every identity persists at both constructed cutpoints. No behavior of generic runtime free is used.
Explore proof 3 tactics
Initial goal
intros s m p older selected Hw Hr
destruct pop_effects[ ] s m p older selected Hw as Hindex Hpop
split ; eapply E.effects_preserve ; eauto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Standalone wrapper; composition clients supply their exact machine.
Unlinking an exhausted head, without retirement
The actual pointer store also installs the successor's capability. A last node is unlinked to null, not freed or kept in the chain.
This is head-cell separation, unlike pop's modified-block separation.
Unlink changes only eight head bytes and the head's own shadow cell; every region, including the removed block's lifetime, is unchanged.
Explore proof 17 tactics
Initial goal
intros m head rest
split ; reflexivity |
split
2 openfocused goal
–intros a Hout
2 opendeferred goal
unfold exit_unlink_memory , startup_store
2 opendeferred goal
simpl
2 opendeferred goal
destruct ptr_addrhead ≤? a && a <? ptr_addrhead + 8 eqn: E ; | reflexivity
2 opendeferred goal
apply andb_true_iff in E as Hlo Hhi
2 opendeferred goal
apply Z.leb_le in Hlo
2 opendeferred goal
apply Z.ltb_lt in Hhi
2 opendeferred goal
lia
deferred goal
–intros a Hneq
unfold exit_unlink_memory , startup_store
simpl
assert a =? ptr_addrhead = false as E by apply Z.eqb_neq ; exact Hneq
rewrite E
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The successor capability comes from the original checked next slot, not from the head's old capability or the successor's address bits.
Explore proof 20 tactics
Initial goal
intros m block next Hblock
destruct Hblock as Hcap & Hread & Hnext & Htail
right
right
left
exists mkSpanblock_ptrblock 1040, ptr_addrblock_ptrblock
split ; left ; reflexivity |
split ; unfold span_contains ; simpl ; lia |
split ; simpl ; lia |
split
2 openfocused goal
–replace ptr_addrblock_ptrblock with ptr_addrblock_ptrblock + 0 at 1 by lia
2 opendeferred goal
eapply exit_block_field_access with block := block next := next off := 0
5 openfocused goal
focused goal
focused goal
deferred goal
+split ; exact Hcap |
5 opendeferred goal
deferred goal
deferred goal
deferred goal
split ; exact Hread |
5 opendeferred goal
deferred goal
deferred goal
deferred goal
split ; assumption
4 opendeferred goal
deferred goal
deferred goal
deferred goal
+lia
3 opendeferred goal
deferred goal
deferred goal
+lia
2 opendeferred goal
deferred goal
+reflexivity
deferred goal
–symmetry
exact proj2proj2Hnext
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Writable head authority plus the original aligned read permits the native aligned store; neither premise is inferred from stored bytes.
Explore proof 4 tactics
Initial goal
intros m head _ & base & reg & Hcap & _ Hread
simpl in Hcap
rewrite Hcap in *
exact Hread
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Exact local frames preserve the old chain, including the detached node, when every represented block is separated from the head store.
Explore proof 13 tactics
Initial goal
intros m head rest blocks Hchain Hsep
destruct exit_unlink_framem head rest as Hregions Hbytes Haux
induction blocks as | block blocks IH ; exact I |
destruct Hchain as Hblock Hchain
inversion Hsep as [ |? ? Hdis Htail ] ; subst
split ; | apply IH ; assumption
apply exit_block_memory_agreem ; exact Hregions | | | exact Hblock
2 openfocused goal
–intros a Ha
2 opendeferred goal
apply Haux
2 opendeferred goal
lia
deferred goal
–intros a Ha
apply Hbytes
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Removing an exhausted head preserves the checked suffix and the detached block's view. No free, done flag, lock change or cleanup action occurs.
Explore proof 9 tactics
Initial goal
intros m head p rest Hread & Hhead & Hchain & Hdistinct Hsep
destruct exit_unlink_chain_representedm head rest mkExitBlockp [ ] :: rest Hchain Hsep as Hdetached Hsuffix
split ; | exact Hdetached
split ; exact Hread |
split
2 openfocused goal
–apply pointer_slot_written
2 opendeferred goal
exact proj1proj1proj2proj2proj1Hchain
deferred goal
–split ; exact Hsuffix |
inversion Hdistinct ; assumption
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
An empty physical node contributes no callback, even when it is last.
Explore proof 1 tactics
Initial goal
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Admission may observe the head's old capability, so pop's globally unchanged-shadow premise is insufficient. This rule permits precisely the head store's byte and shadow changes in arbitrary snapshots.
Unlink stutters on pending/active registrations and transports every admission only when its independent pointer-store frame rule holds.
Explore proof 11 tactics
Initial goal
intros admitted m head p rest active Hstable Hall Hactive
rewrite exit_unlink_pending in Hall
destruct exit_unlink_framem head rest as Hregions Hbytes Haux
assert Htransport : ∀entry, admittedm entry → admittedexit_unlink_memorym head rest entry
2 openfocused goal
{apply Hstable ; assumption
deferred goal
split
2 openfocused goal
–eapply Forall_impl ; | exact Hall
2 opendeferred goal
intros entry Hi
2 opendeferred goal
apply Htransport
2 opendeferred goal
exact Hi
deferred goal
–destruct active ; apply Htransport ; exact Hactive | exact I
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
One actual pointer-store effect over any runtime, with no retirement.
The existing external-call effects of the caller's machine.
The source capability is loaded from next; only the head is writable.
Explore proof 9 tactics
Initial goal
intros s m head p rest Hblock Hw
eapply E.effects_local ; | constructor
apply local_store_pointer
2 openfocused goal
–intros a Ha
2 opendeferred goal
left
2 opendeferred goal
exists mkSpanhead 8
2 opendeferred goal
split ; left ; reflexivity |
2 opendeferred goal
split ; exact Hw | exact Ha
deferred goal
–exact exit_next_authoritym mkExitBlockp [ ] exit_headrest Hblock
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Readiness and identity persistence follow from the constructed effect, not from a claim that libc always reaches or completes this cutpoint.
Explore proof 2 tactics
Initial goal
intros s m head p rest Hblock Hw Hr
eapply E.effects_preserve ; exact unlink_effectss m head p rest Hblock Hw | exact Hr
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Standalone wrapper for existing unlink clients.
Concrete model memory checks do not locate the native hidden registry.
Two distinct callback forms with asymmetric tokens and arguments.
The newest stored callback has no argument; cxa still stores its null slot.
idx=3 describes two installed callbacks separated by a finalized hole.
Build actual address bytes and shadow capabilities with existing stores.
The concrete bytes inhabit a checked block view, with idx counting the hole.
Explore proof 9 tactics
Initial goal
split ; reflexivity |
split ; reflexivity |
split
2 openfocused goal
–vm_compute
2 opendeferred goal
repeat split ; congruence
deferred goal
–split ; reflexivity |
split ; simpl ; lia |
intros i slot Hi
destruct i as | | | i ; simpl in Hi ; try destruct i ; discriminate Hi ; injection Hi as ← ; vm_compute ; repeat split ; congruence
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A readable head and a distinct, null-terminated chain inhabit the registry view.
Explore proof 8 tactics
Initial goal
split ; reflexivity |
split
2 openfocused goal
–vm_compute
2 opendeferred goal
repeat split ; congruence
deferred goal
–split ; split ; exact block_represented | exact I |
repeat constructor
simpl
tauto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A head block precedes an older block; both scan backward and skip holes.
Explore proof 1 tactics
Initial goal
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
After decreasing idx the former newest slot is outside the pending scan. Even replacing its argument capability with nonsense does not invalidate this shorter registry view. Active callback evidence is independent.
Explore proof 9 tactics
Initial goal
split ; reflexivity |
split ; reflexivity |
split
2 openfocused goal
–vm_compute
2 opendeferred goal
repeat split ; congruence
deferred goal
–split ; reflexivity |
split ; simpl ; lia |
intros i slot Hi
destruct i as | | i ; simpl in Hi ; try destruct i ; discriminate Hi ; injection Hi as ← ; vm_compute ; repeat split ; congruence
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Correct next-pointer bits cannot compensate for its wrong capability.
Explore proof 2 tactics
Initial goal
intros _ & _ & _ & _ & Haux & _
discriminate Haux
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Correct function address bits cannot turn an object capability into Fn.
Explore proof 2 tactics
Source script
Unknown flavors are not silently reclassified as holes.
Explore proof 2 tactics
Initial goal
intros slot Hslot
destruct slot ; simpl in Hslot ; try discriminate Hslot ; destruct Hslot as Htag _ ; discriminate Htag
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
An empty pending chain cannot erase the detached active callback's contract.
Explore proof 4 tactics
Initial goal
intros m entry
split ; split ; constructor |
intros _ Hactive
exact Hactive
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A represented Fn capability does not authorize a missing callback contract.
Explore proof 3 tactics
Initial goal
split ; exact registry_represented |
intros Hcallbacks _
inversion Hcallbacks ; assumption
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Cxa removes exactly its newest flavor, leaving older slots and captured function/argument capabilities. Index-only completion is insufficient.
Explore proof 8 tactics
Initial goal
intros m′
split ; reflexivity |
split ; reflexivity |
split ; reflexivity |
split ; vm_compute ; repeat split ; congruence |
split ; reflexivity |
apply exit_pop_registry_representedmemory mkPtr1000 Obj1000 block_ptrblock oldest; FreeSlot newest [ ] registry_represented
split ; left ; simpl ; lia | constructor
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Hole and ordinary callback removal decrement idx without clearing payloads.
Explore proof 1 tactics
Initial goal
repeat split ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The narrow cxa roots are independently writable, without permitting any callback argument write or heap release.
Explore proof 8 tactics
Initial goal
constructor
2 open–split ; simpl ; lia |
2 openexists 2048, mkRegion2048 3088 GlobalData Live
2 openrepeat split ; reflexivity
–constructor ; | constructor
split ; simpl ; lia |
exists 2048, mkRegion2048 3088 GlobalData Live
repeat split ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A real changed index cannot be justified by an empty write footprint.
Explore proof 5 tactics
Initial goal
intros _ & _ & Hframe & _
assert Hnone : ¬write_authority[ ] [ ] memory 2056
2 open{intros root & & _ | base & reg & & _
destruct Hframe2056 Hnone as Hbyte _
discriminate Hbyte
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
An empty physical prefix cannot be decomposed into a selected pop.
Explore proof 5 tactics
Initial goal
intros older selected H
apply f_equal@lengthexit_slot in H
rewrite length_app in H
simpl in H
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Data-sensitive admission of the known callbacks, retaining the pending on_exit argument's checked byte. Not a native callback implementation.
Its checked data lies outside both metadata roots, so the general stability premise is discharged rather than assumed at the endpoint.
Explore proof 11 tactics
Initial goal
intros m m′ Hregions Haux Hbytes entry Hin & Hread & Hdata
split ; exact Hin |
split
2 openfocused goal
–unfold access_res
2 opendeferred goal
rewrite Hregions
2 opendeferred goal
exact Hread
deferred goal
–rewrite <- Hdata
apply load_bytes_agree ; lia |
intros i Hi
apply Hbytes
intros root & ← | ← | & Hrange ; unfold span_contains in Hrange ; cbn - [ Z.add Z.mul ] in Hrange ; lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Both the still-pending argument and the detached active callback stay admitted at the actual constructed endpoint.
Explore proof 8 tactics
Initial goal
apply exit_pop_admittedpop_admission memory block_ptrblock oldest; FreeSlot newest [ ] ; reflexivity | exact pop_admission_stable |
split ; | exact I
constructor
2 openfocused goal
–split ; left ; reflexivity |
2 opendeferred goal
split ; reflexivity
deferred goal
–constructor ; | constructor
split ; right ; left ; reflexivity |
split ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A specification depending on idx does NOT satisfy footprint stability.
Explore proof 4 tactics
Initial goal
intros Hstable
destruct exit_pop_framememory block_ptrblock oldest; FreeSlot newest as Hregions Haux Hbytes
pose proof Hstablememory exit_pop_memorymemory block_ptrblock oldest; FreeSlot newest Hregions Haux Hbytes mkRegistration11 AtExitTAtom"index" eq_refl as Hbad
discriminate Hbad
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
A second block with one skipped physical slot is genuinely represented.
Link the original block to separate storage, preserving its callback data.
Both blocks and the external head cell satisfy the checked snapshot.
Explore proof 20 tactics
Initial goal
split ; reflexivity |
split ; vm_compute ; repeat split ; congruence |
split
2 openfocused goal
–split
3 openfocused goal
deferred goal
+split ; reflexivity |
3 opendeferred goal
deferred goal
split ; reflexivity |
3 opendeferred goal
deferred goal
split ; vm_compute ; repeat split ; congruence |
3 opendeferred goal
deferred goal
split ; reflexivity |
3 opendeferred goal
deferred goal
split ; simpl ; lia |
3 opendeferred goal
deferred goal
intros i slot Hi
3 opendeferred goal
deferred goal
destruct i as | | | i ; simpl in Hi ; try destruct i ; discriminate Hi ; injection Hi as ← ; vm_compute ; repeat split ; congruence
2 opendeferred goal
deferred goal
+split ; | exact I
2 opendeferred goal
split ; reflexivity |
2 opendeferred goal
split ; reflexivity |
2 opendeferred goal
split ; vm_compute ; repeat split ; congruence |
2 opendeferred goal
split ; reflexivity |
2 opendeferred goal
split ; simpl ; lia |
2 opendeferred goal
intros i slot Hi
2 opendeferred goal
destruct i ; simpl in Hi ; injection Hi as ← ; reflexivity | destruct i ; discriminate Hi
deferred goal
–repeat constructor ; simpl ; intuition congruence
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A constructed cxa pop preserves a nonempty separated suffix, not only singleton registries. No block is freed at this cutpoint.
Explore proof 3 tactics
Initial goal
apply exit_pop_registry_representedchain_memory mkPtr1000 Obj1000 block_ptrblock oldest; FreeSlot newest tail_block chain_represented
split ; left ; simpl ; lia |
constructor ; right ; simpl ; lia | constructor
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A snapshot can alias its own head cell with idx; distinct block identities alone therefore do not justify metadata-write preservation.
Eight free physical slots make both interpretations of that cell agree.
Explore proof 17 tactics
Initial goal
split ; reflexivity |
split ; vm_compute ; repeat split ; congruence |
split
2 openfocused goal
–split ; | exact I
2 opendeferred goal
split ; reflexivity |
2 opendeferred goal
split ; reflexivity |
2 opendeferred goal
split ; vm_compute ; repeat split ; congruence |
2 opendeferred goal
split ; reflexivity |
2 opendeferred goal
split ; simpl ; lia |
2 opendeferred goal
intros i slot Hi
2 opendeferred goal
apply nth_error_In in Hi
2 opendeferred goal
apply repeat_spec in Hi
2 opendeferred goal
subst slot
2 opendeferred goal
change load_bytesstore_bytesmkMemλ_ ⇒ 0 mkRegion8 1048 GlobalData Live λ_ ⇒ CNone 16 8 8 8 + 16 + 32 × Z.of_nati 8 = 0
2 opendeferred goal
rewrite exit_load_bytes_disjoint by lia
2 opendeferred goal
reflexivity
deferred goal
–constructor ; simpl ; tauto | constructor
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The actual decrement destroys that aliased head; the separation premise excludes this valid counterexample to the unrestricted theorem.
Explore proof 3 tactics
Initial goal
split ; intros H _ ; simpl in H ; lia |
intros _ & _ & Hload & _ & _
discriminate Hload
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
An exhausted heap head links to the callback-bearing older block. Its successor has different address bits AND a different capability.
The source view is inhabited, not merely an executable update example.
Explore proof 20 tactics
Initial goal
split ; reflexivity |
split ; vm_compute ; repeat split ; congruence |
split
2 openfocused goal
–split
3 openfocused goal
deferred goal
+split ; reflexivity |
3 opendeferred goal
deferred goal
split ; reflexivity |
3 opendeferred goal
deferred goal
split ; vm_compute ; repeat split ; congruence |
3 opendeferred goal
deferred goal
split ; reflexivity |
3 opendeferred goal
deferred goal
split ; simpl ; lia |
3 opendeferred goal
deferred goal
intros i slot Hi
3 opendeferred goal
deferred goal
destruct i ; discriminate Hi
2 opendeferred goal
deferred goal
+split ; | exact I
2 opendeferred goal
split ; reflexivity |
2 opendeferred goal
split ; reflexivity |
2 opendeferred goal
split ; vm_compute ; repeat split ; congruence |
2 opendeferred goal
split ; reflexivity |
2 opendeferred goal
split ; simpl ; lia |
2 opendeferred goal
intros i slot Hi
2 opendeferred goal
destruct i as | | | i ; simpl in Hi ; try destruct i ; discriminate Hi ; injection Hi as ← ; vm_compute ; repeat split ; congruence
deferred goal
–repeat constructor ; simpl ; intuition congruence
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Unlink preserves the callback-bearing suffix and detached node, using an independently checked writable head and the actual source view.
Explore proof 8 tactics
Initial goal
split
2 openfocused goal
–split ; simpl ; lia |
2 opendeferred goal
exists 1000, mkRegion1000 1008 GlobalData Live
2 opendeferred goal
repeat split ; reflexivity
deferred goal
–split ; vm_compute ; repeat split ; congruence |
apply exit_unlink_registry_representedunlink_memory mkPtr1000 Obj1000 mkPtr8192 Obj8192 block unlink_source_represented
constructor ; left ; simpl ; lia |
constructor ; left ; simpl ; lia | constructor
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Singleton removal installs canonical null but retains its heap allocation.
Explore proof 19 tactics
Initial goal
intros m
assert Hsource : exit_registry_memorym mkPtr1000 Obj1000 mkExitBlockmkPtr8192 Obj8192 [ ]
2 openfocused goal
{split ; reflexivity |
2 opendeferred goal
split ; vm_compute ; repeat split ; congruence |
2 opendeferred goal
split
3 openfocused goal
deferred goal
–split ; | exact I
3 opendeferred goal
deferred goal
split ; reflexivity |
3 opendeferred goal
deferred goal
split ; reflexivity |
3 opendeferred goal
deferred goal
split ; vm_compute ; repeat split ; congruence |
3 opendeferred goal
deferred goal
split ; reflexivity |
3 opendeferred goal
deferred goal
split ; simpl ; lia |
3 opendeferred goal
deferred goal
intros i slot Hi
3 opendeferred goal
deferred goal
destruct i ; discriminate Hi
2 opendeferred goal
deferred goal
–repeat constructor
2 opendeferred goal
simpl
2 opendeferred goal
tauto
deferred goal
split ; exact Hsource |
split ; | reflexivity
apply proj1exit_unlink_registry_representedm mkPtr1000 Obj1000 mkPtr8192 Obj8192 [ ] Hsource ltac:constructor ; left ; simpl ; lia | constructor
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Updating address bits alone loses the successor's capability.
Explore proof 2 tactics
Initial goal
intros _ & _ & Haux
discriminate Haux
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The changed head byte cannot be justified without writable roots.
Explore proof 5 tactics
Initial goal
intros _ & _ & Hframe & _
assert Hnone : ¬write_authority[ ] [ ] unlink_memory 1001
2 openfocused goal
{intros root & & _ | base & reg & & _
deferred goal
destruct Hframe1001 Hnone as Hbyte _
discriminate Hbyte
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Retained argument admission survives arbitrary head stores, not just this endpoint: the admitted data and its access remain outside the head.
Explore proof 12 tactics
Initial goal
intros m m′ Hregions Hbytes Haux entry Hin & Hread & Hdata
split ; exact Hin |
split
2 openfocused goal
–unfold access_res
2 opendeferred goal
rewrite Hregions
2 opendeferred goal
exact Hread
deferred goal
–rewrite <- Hdata
apply load_bytes_agree ; lia |
intros i Hi
apply Hbytes
cbn - [ Z.add ]
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Both pending callbacks and a detached active registration retain their admitted argument checks through the actual pointer store.
Explore proof 10 tactics
Initial goal
apply exit_unlink_admittedpop_admission unlink_memory mkPtr1000 Obj1000 mkPtr8192 Obj8192 block ; exact unlink_admission_stable |
split
2 openfocused goal
–constructor
3 openfocused goal
deferred goal
+split ; left ; reflexivity |
3 opendeferred goal
deferred goal
split ; reflexivity
2 opendeferred goal
deferred goal
+constructor ; | constructor
2 opendeferred goal
split ; right ; left ; reflexivity |
2 opendeferred goal
split ; reflexivity
deferred goal
–split ; right ; left ; reflexivity |
split ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A specification observing the old head shadow does not frame through unlink, despite every allocation and every other shadow cell surviving.
Explore proof 4 tactics
Initial goal
intros Hstable
destruct exit_unlink_frameunlink_memory mkPtr1000 Obj1000 block as Hregions Hbytes Haux
pose proof Hstableunlink_memory exit_unlink_memoryunlink_memory mkPtr1000 Obj1000 block Hregions Hbytes Haux mkRegistration11 AtExitTAtom"head" eq_refl as Hbad
discriminate Hbad
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Even distinct block identities may overlap. Here the readable head cell is the older block's idx; unlink would change it from 32 to 8.
The unrestricted snapshot admits the alias, so separation is substantive.
Explore proof 24 tactics
Initial goal
split ; reflexivity |
split ; vm_compute ; repeat split ; congruence |
split
2 openfocused goal
–split
3 openfocused goal
deferred goal
+split ; reflexivity |
3 opendeferred goal
deferred goal
split ; reflexivity |
3 opendeferred goal
deferred goal
split ; vm_compute ; repeat split ; congruence |
3 opendeferred goal
deferred goal
split ; reflexivity |
3 opendeferred goal
deferred goal
split ; simpl ; lia |
3 opendeferred goal
deferred goal
intros i slot Hi
3 opendeferred goal
deferred goal
destruct i ; discriminate Hi
2 opendeferred goal
deferred goal
+split ; | exact I
2 opendeferred goal
split ; reflexivity |
2 opendeferred goal
split ; reflexivity |
2 opendeferred goal
split ; vm_compute ; repeat split ; congruence |
2 opendeferred goal
split ; reflexivity |
2 opendeferred goal
split ; simpl ; lia |
2 opendeferred goal
intros i slot Hi
2 opendeferred goal
apply nth_error_In in Hi
2 opendeferred goal
apply repeat_spec in Hi
2 opendeferred goal
subst slot
2 opendeferred goal
change load_bytesstore_bytesstore_bytesmkMemλ_ ⇒ 0 mkRegion8 1048 GlobalData Live; mkRegion32 1072 Heap Live λ_ ⇒ CNone 16 8 32 32 8 8 8 + 16 + 32 × Z.of_nati 8 = 0
2 opendeferred goal
destruct i ; rewrite ! exit_load_bytes_disjoint by lia ; reflexivity
deferred goal
–repeat constructor ; simpl ; intuition congruence
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Head/suffix separation rejects this actual representation-breaking store.
Explore proof 7 tactics
Initial goal
split
2 openfocused goal
–intros H
2 opendeferred goal
inversion H as [ |? ? Hdis Htail ]
2 opendeferred goal
simpl in Hdis
2 opendeferred goal
lia
deferred goal
–intros _ & _ & _ & _ & _ & Hidx & _ _ & _
discriminate Hidx
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.