rocq/theories/LibcStreams.v
Composite stdout/stderr contracts. FILE metadata and physical counts live in libc_streams; stdout's only logical protocol lives in shutdown_stdout. Native representation and exclusive ownership remain trusted premises, not consequences of writable addresses. Closed handles retain identity and protocol, but grant no authority.
Exact handle comparison includes capability, not merely address.
Stdout's stable represented handle.
Stderr's stable represented handle.
Selection is capability-sensitive even for a consumed handle.
Lookup survives consumption and never restores a saved stdout FIFO.
Only active handles expose physical counts and ordinary stream calls.
These sources belong to FILE state, not to a caller's format strings. A zero-length handle span supplies its capability, not extra bytes.
Errno's fixed capability supports its scalar write root in generic delegation. It grants no readable aux slot and is excluded from the private FILE pools by file_errno_apart.
Active roots only; closing retires historical buffer authority.
Only FILE-private spans may change pointer aux; the extra scalar errno root in libc_stream_writes may not do so.
Exclusive heaps are not inferred from the handle or its roots.
Errno is a fixed scalar output, not FILE-private retained authority. Entry and endpoint representations independently establish this, including complete aux-loaded capabilities in private sources.
Structural obligations for an ACTIVE FILE. The supplied native representation additionally owns close rights and excludes caller setvbuf storage and static FILE identities from file_owned.
Legacy puts roots are the same active stdout inventory, not a second grant. Historical roots in closed FILE records are deliberately omitted.
A selected close cannot release either stable FILE, locale storage, or authority retained by the other active FILE. Exclusive ownership against caller storage still belongs to the native representation.
Endpoint readiness permits either FILE closed. It keeps locale/errno and shutdown structure coherent; it does not establish native representation, exclusive ownership or progress.
Stream calls preserve current locale, errno identity and lifecycle inventory. Only the selected FILE's state may change. Shared native metadata still needs the independent memory frame, not disjoint locks.
Concrete projections, with only native allocation policy and wide settlement remaining realization parameters. Wide conversion needs its own effects/representation witness even if settlement succeeds.
Reached ordinary entries. The fallback composes with the remaining libc registry; it cannot override these six actual plain symbols.
Lookup laws are definitional, independent of the fallback registry.
Explore proof 2 tactics
Initial goal
intros
repeat split ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Exact comparison accepts a retained handle with its own capability.
Explore proof 5 tactics
Initial goal
intros a c
unfold same_file
simpl
rewrite Z.eqb_refl
destruct c ; simpl ; try apply Z.eqb_refl ; try apply term_eqb_refl ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Stdout always projects the authoritative shutdown protocol, closed or open; there is no pre-close snapshot to restore.
Explore proof 4 tactics
Initial goal
intros
unfold libc_stream_state
rewrite same_file_refl
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A forged capability at the very same address is not the FILE.
Explore proof 4 tactics
Initial goal
intros w a Ho He
unfold libc_stream_at , libc_file_at
rewrite Ho , He
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
An active selected FILE has the structural representation obligations of its own inventory entry, not those of a sibling handle.
Explore proof 3 tactics
Initial goal
intros rep m w p file _ & _ & _ & _ & _ & _ & _ & _ & _ & _ & Hro & Hre & _ Hfile
unfold libc_file_at in Hfile
destruct same_filep libc_stdoutw ; destruct stdout_usablelibc_stdiofstw eqn: Ho | destruct same_filep libc_stderrw ; destruct libc_stderr_openlibc_streamsfstw eqn: He | ; try discriminate ; injection Hfile as ← ; auto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Admission follows from represented endpoint structure and an active exact handle; no output success or chosen query result is assumed.
Explore proof 23 tactics
Initial goal
intros rep requests wide m w p file Hready Hfile
pose proof Hready as _ & _ & Herrno & Hout & Herr & _ & _ & _ & _ & _ & Hro & Hre & _
pose proof libc_file_at_readyrep m w p file Hready Hfile as Hfile_ready
destruct Hfile_ready as _ & _ & Hpending & Hroots & _
exists mkStreamInfoif same_filep libc_stdoutw then 1 else 2 libc_stream_statew p file_pendingfile
split ; exact Hready |
split
2 openfocused goal
–unfold stream_at , libc_stream_model , libc_stream_at
2 opendeferred goal
rewrite Hfile
2 opendeferred goal
reflexivity
deferred goal
–split ; reflexivity |
split
2 openfocused goal
+split ; | exact Hpending
2 opendeferred goal
unfold libc_stream_state
2 opendeferred goal
destruct same_filep libc_stdoutw ; exact Hout |
2 opendeferred goal
destruct same_filep libc_stderrw eqn: He ; exact Herr |
2 opendeferred goal
apply stdout_initial_wf
deferred goal
+change Forallwritable_spanm libc_stream_writesw p
unfold libc_stream_writes
rewrite Hfile
apply Forall_app
split ; exact Hroots |
constructor ; exact proj1proj2Herrno | constructor
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Query/close admission is shared and independent of their outcomes.
Explore proof 4 tactics
Initial goal
intros
destruct libc_stream_openrep requests wide m w p file H H0 as info Ho
exists p, info
auto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Narrow literal/vararg interpretation is separate from the selected FILE representation. All errors and partial acceptance stay admitted.
Explore proof 7 tactics
Initial goal
intros rep requests wide api xs m w file bytes Hr Hfile Ho Htext
destruct libc_stream_openrep requests wide m w _ file Hr Hfile as info Hopen
exists info, bytes
split ; exact Hopen |
destruct Hopen as _ & _ & Hstate & _
rewrite Hstate
auto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
An unchanged active endpoint delegates its fixed scalar errno root as well as its private roots; it needs no new allocation or owner.
Proof 49 steps Qed
The same libc errno/locale/conversion registry stays usable after closing stdout; writable retired roots are not required.
Explore proof 13 tactics
Initial goal
intros rep m w Hrep & Hlocale & Herrno & Hout & Herr & Hu & Hstatus & Hphase & Hdistinct & Hroots & Hro & Hre & Hrelease
split ; exact Hrep |
split ; exact Hlocale |
split
2 openfocused goal
–rewrite Hroots
2 opendeferred goal
unfold libc_active_roots
2 opendeferred goal
apply Forall_app
2 opendeferred goal
split
3 openfocused goal
deferred goal
+destruct stdout_usablelibc_stdiofstw eqn: Ho ; | constructor
3 opendeferred goal
deferred goal
destruct Hroeq_refl as _ & _ & _ & Hr & _
3 opendeferred goal
deferred goal
exact Hr
2 opendeferred goal
deferred goal
+constructor ; exact proj1proj2Herrno | constructor
deferred goal
–auto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Keeping the world unchanged is a valid logical frame.
Explore proof 3 tactics
Initial goal
intros
unfold libc_stream_frame
repeat split ; destruct same_filep libc_stdoutw ; auto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Errno is scalar-only even when its entry aux is nonempty. The frame is required at all call prefixes, including resource stops.
Explore proof 20 tactics
Initial goal
intros rep requests wide m w p file m′ Hr Hfile Hframe
pose proof libc_file_at_readyrep m w p file Hr Hfile as _ & _ & _ & _ & _ & _ & Hapart & _
pose proof Hr as _ & _ & _ & Hcell & _ & _
apply Hframe
2 openfocused goal
–eapply write_authority_in with roots := mkSpanlibc_errnofstw 4 born := [ ]
2 opendeferred goal
left
2 opendeferred goal
exists mkSpanlibc_errnofstw 4
2 opendeferred goal
split ; simpl ; auto |
2 opendeferred goal
split ; exact Hcell |
2 opendeferred goal
unfold span_contains
2 opendeferred goal
simpl
2 opendeferred goal
lia
deferred goal
–change ¬write_authoritylibc_stream_aux_rootsw p [ ] m ptr_addrlibc_errnofstw
unfold libc_stream_aux_roots
rewrite Hfile
intros root & Hin & _ & Ha | base & reg & & _
specialize Hapartroot Hin
unfold spans_apart , span_contains in *
simpl in *
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The registry and projections use the consumer's actual machine.
A logical unchanged query has an independently admitted prefix. This is nonvacuity, not a claim that native locking changes nothing.
Explore proof 11 tactics
Initial goal
intros rep requests wide p file s m w Hr Hfile
destruct libc_stream_openrep requests wide m w p file Hr Hfile as info Ho
split ; constructor |
exists p, info
split ; reflexivity |
split ; exact proj1proj2Ho |
split ; exact Ho |
split ; apply libc_stream_frame_refl |
split ; apply libc_stream_delegates_refl ; exact Hr |
split ; reflexivity |
split ; unfold stream_aux_frame | ; intros ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The concrete ferror query admits either sticky-error value without assuming that the caller sees a successful output history.
Explore proof 19 tactics
Initial goal
intros rep requests wide r args p file s m w Habi Hr Hfile
destruct libc_stream_openrep requests wide m w p file Hr Hfile as info Ho
eapply S.ferror_return with born := [ ]
4 openfocused goal
focused goal
focused goal
–exact Habi
3 opendeferred goal
deferred goal
deferred goal
–exists p, info
3 opendeferred goal
deferred goal
auto
2 opendeferred goal
deferred goal
–eapply query_unchanged_prefix ; eauto
deferred goal
–exists p, info, if stream_errorlibc_stream_statew p then 1 else 0
split ; reflexivity |
split ; exact proj1proj2Ho |
split ; exact Ho |
split ; apply libc_stream_frame_refl |
split ; apply libc_stream_delegates_refl ; exact Hr |
split ; reflexivity |
split ; reflexivity |
destruct Ho as _ & _ & Hstate & _
rewrite Hstate
cbn [ stream_state_at libc_stream_model ]
destruct stream_errorlibc_stream_statew p ; split ; lia | split ; congruence | lia | split ; congruence
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Physical pending, not the logical FIFO length, is the query result.
Proof 40 steps Qed
The old exact errno lookup is still admitted with closed stdout.
Explore proof 4 tactics
Initial goal
intros
apply C.errno_admitted ; exact H |
apply libc_stream_ready_libc
exact H0
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Returning and resource-ending output expose the same represented world/frame/provenance cutpoint. Normal-result facts are separate.
Explore proof 6 tactics
Initial goal
intros rep requests wide api r args xs s m w trace ending s′ m′ w′ Hcall
destruct E.invoke_prefix_ _ _ _ _ _ _ _ _ _ _ _ _ Hcall as born & He & info & info′ & bytes & actions & tail & Hinfo & Htext & Hbytes & Hrun & Hopen & Hid & Hframe & Hdelegate & Htrace & Haux
split ; exact proj1Hopen |
split ; exact Hframe |
exists born
auto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Ordinary narrow output results remain canonical, including errors.
Explore proof 2 tactics
Initial goal
intros
eapply F.output_returned ; eauto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Logical controls, not a claim that these tiny objects are native FILEs. Physical pending counts deliberately differ from FIFO length.
Static handles live in separate existing fixture objects.
Stderr has a different physical count.
Close retires stdout after settling its two logical obligations; physical pending is deliberately not the FIFO length.
Neither stream's private zero-length source exposes errno authority.
Explore proof 5 tactics
Initial goal
intros a n Hne
split ; intros root |
intros base Hbase | Hbase ; injection Hbase as <-| discriminate
split ; intros |
split ; intros Hnone | source & Hin & Hcap | source & addr & Hin & Ha & Hsize & _ | b & & _ ; try discriminate ; simpl in Hin ; destruct Hin as [ <-| [ ] ] ; simpl in * ; congruence | unfold span_contains in Ha ; simpl in Ha ; lia | discriminate | unfold span_contains in Ha ; simpl in Ha ; lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Both represented open FILE entries satisfy their structural slice.
Explore proof 15 tactics
Initial goal
assert Hread : ∀a, a = 1024 ∨ a = 2048 → readable_bytesconversion_mem mkPtra Obja 1
2 openfocused goal
{intros a → | → ; split ; simpl ; lia | | simpl ; lia |
3 openfocused goal
deferred goal
all: split
5 openfocused goal
focused goal
focused goal
deferred goal
1: {exists 1024, mkRegion1024 1056 GlobalData Live
5 opendeferred goal
deferred goal
deferred goal
deferred goal
auto
4 opendeferred goal
deferred goal
deferred goal
deferred goal
2: {exists 2048, mkRegion2048 2056 Stack Live
4 opendeferred goal
deferred goal
deferred goal
auto
3 opendeferred goal
deferred goal
deferred goal
all: split ; reflexivity |
3 openfocused goal
deferred goal
all: intros i Hi ; assert i = 0 as → by lia ; vm_compute ; split ; congruence
deferred goal
split ; unfold out_file , err_file , libc_file_ready ; split ; discriminate | | discriminate |
2 openfocused goal
all: split ; apply Hread ; auto |
2 openfocused goal
all: split ; simpl ; lia |
2 openfocused goal
all: split ; constructor |
2 openfocused goal
all: split ; constructor |
2 openfocused goal
all: split ; constructor | apply empty_file_errno ; lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Closed stdout is a nonempty represented state, not a vacuous pre.
Explore proof 17 tactics
Initial goal
intros opened
pose proof proj1conversion_pre1 ltac:lia as _ & Hl & _ & He & _
split ; exact I |
split ; exact Hl |
split ; exact He |
split ; split ; destruct opened ; repeat constructor ; lia | reflexivity |
split ; apply stdout_initial_wf |
split ; constructor |
split ; simpl ; lia |
split ; exact I |
split ; simpl ; lia |
split ; destruct opened ; reflexivity |
split ; intros _ ; exact proj1files_ready |
split ; intros _ ; exact proj2files_ready |
intros p file Hfile base Hin
unfold libc_file_at in Hfile
destruct same_filep libc_stdoutworldopened ; destruct opened | destruct same_filep libc_stderrworldopened ; try discriminate ; injection Hfile as ← ; contradiction
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Same registered errno contract, after stdout closes, returns exactly the original capability and snapshot.
Explore proof 1 tactics
Initial goal
apply C.errno_after_close ; split ; left ; reflexivity | reflexivity | apply ready
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
After stdout closes, stderr remains queryable with its own count.
Explore proof 6 tactics
Initial goal
apply C.fpending_unchanged with file := err_file
3 openfocused goal
focused goal
–split ; left ; reflexivity |
3 opendeferred goal
deferred goal
exists Const0
3 opendeferred goal
deferred goal
reflexivity
2 opendeferred goal
deferred goal
–apply ready
deferred goal
–reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Seven physical pending bytes are not the two logical obligations.
Explore proof 6 tactics
Initial goal
apply C.fpending_unchanged with file := out_file
3 openfocused goal
focused goal
–split ; left ; reflexivity |
3 opendeferred goal
deferred goal
exists Const0
3 opendeferred goal
deferred goal
reflexivity
2 opendeferred goal
deferred goal
–apply ready
deferred goal
–reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A closed handle cannot be queried again, regardless of the registry.
Explore proof 3 tactics
Initial goal
intros rep requests wide p & info & Hxs & _ & Hinfo & _
injection Hxs as ←
discriminate Hinfo
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A genuine completed fclose, not merely a chosen closed fixture: error-discard settles the old FIFO and EOF still consumes the handle.
Explore proof 5 tactics
Initial goal
intros
exists Discard65; 66
split
2 openfocused goal
–eapply stream_next ; exact stream_discard65; 66 [ ] true ltac:discriminate | constructor
deferred goal
–split ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Explore proof 1 tactics
Initial goal
repeat split ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Explore proof 2 tactics
Initial goal
split ; intros root |
split ; intros x ; contradiction
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Explore proof 40 tactics
Initial goal
split ; | exact closed_errno
eapply M.E.invoke_normal with born := [ ]
7 openfocused goal
focused goal
focused goal
focused goal
focused goal
focused goal
–split ; left ; reflexivity |
7 opendeferred goal
deferred goal
deferred goal
deferred goal
deferred goal
deferred goal
exists Const0
7 opendeferred goal
deferred goal
deferred goal
deferred goal
deferred goal
deferred goal
reflexivity
6 opendeferred goal
deferred goal
deferred goal
deferred goal
deferred goal
deferred goal
–apply libc_stream_admitted with file := out_file ; apply ready | reflexivity
5 opendeferred goal
deferred goal
deferred goal
deferred goal
deferred goal
–split ; constructor |
5 opendeferred goal
deferred goal
deferred goal
deferred goal
exists file_handleout_file, mkStreamInfo1 mkStreamByteOriented 65; 66 true 7, mkStreamByteOriented [ ] true
5 opendeferred goal
deferred goal
deferred goal
deferred goal
split ; reflexivity |
5 opendeferred goal
deferred goal
deferred goal
deferred goal
split ; reflexivity |
5 opendeferred goal
deferred goal
deferred goal
deferred goal
split ; apply close_settles |
5 opendeferred goal
deferred goal
deferred goal
deferred goal
split ; reflexivity |
5 opendeferred goal
deferred goal
deferred goal
deferred goal
split ; apply ready |
5 opendeferred goal
deferred goal
deferred goal
deferred goal
split ; apply close_frame |
5 opendeferred goal
deferred goal
deferred goal
deferred goal
split ; apply close_delegates |
5 opendeferred goal
deferred goal
deferred goal
deferred goal
split ; reflexivity |
5 opendeferred goal
deferred goal
deferred goal
deferred goal
split ; left ; reflexivity |
5 opendeferred goal
deferred goal
deferred goal
deferred goal
unfold stream_aux_frame
5 opendeferred goal
deferred goal
deferred goal
deferred goal
intros ; reflexivity
4 opendeferred goal
deferred goal
deferred goal
deferred goal
–exists file_handleout_file, mkStreamInfo1 mkStreamByteOriented 65; 66 true 7, mkStreamByteOriented [ ] true, stream_eof
4 opendeferred goal
deferred goal
deferred goal
split ; reflexivity |
4 opendeferred goal
deferred goal
deferred goal
split ; reflexivity |
4 opendeferred goal
deferred goal
deferred goal
split ; apply close_settles |
4 opendeferred goal
deferred goal
deferred goal
split ; reflexivity |
4 opendeferred goal
deferred goal
deferred goal
split ; right ; reflexivity |
4 opendeferred goal
deferred goal
deferred goal
split ; reflexivity |
4 opendeferred goal
deferred goal
deferred goal
split ; intros base |
4 opendeferred goal
deferred goal
deferred goal
split ; apply ready |
4 opendeferred goal
deferred goal
deferred goal
split ; apply close_frame |
4 opendeferred goal
deferred goal
deferred goal
auto
3 opendeferred goal
deferred goal
deferred goal
–intros why Hbad
3 opendeferred goal
deferred goal
discriminate
2 opendeferred goal
deferred goal
–intros values Hvalues
2 opendeferred goal
injection Hvalues as ←
2 opendeferred goal
split
3 openfocused goal
deferred goal
+exists WIntstream_eof
3 opendeferred goal
deferred goal
split ; reflexivity
2 opendeferred goal
deferred goal
+repeat constructor
deferred goal
–intros status Hbad
discriminate
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The private-aux frame rejects clobbering a nontrivial errno aux, independently of the scalar byte-write permission.
Explore proof 6 tactics
Initial goal
intros m m′ Hin Hold Hnew Hframe
assert Houtside : ¬write_authoritystream_aux_rootsmodel worldtrue file_handleout_file [ ] m 5120
2 openfocused goal
{intros root & & _ | base & reg & & _
deferred goal
specialize Hframe5120 Hin Houtside
rewrite Hold , Hnew in Hframe
discriminate
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Query-only byte framing protects the last errno byte too, even though ordinary effects authorize all four scalar errno writes.
Explore proof 3 tactics
Initial goal
intros spec s m′ s′ trace ending Hspec Hchanged Hcall
destruct Hspec as → | →
2 openfocused goal
all: destruct M.E.invoke_prefix_ _ _ _ _ _ _ _ _ _ _ _ _ Hcall as born & _ & p & info & Hxs & _ & _ & _ & _ & _ & _ & Hbytes ; injection Hxs as ← ; apply Hchanged , Hbytes ; exists 5120, mkRegion5120 5128 Heap Live ; split ; reflexivity | simpl ; lia | intros root & & _ | base & reg & & _
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Two active, different FILEs may not both own the same release.
Explore proof 3 tactics
Initial goal
intros m w p file q other base Hp Hq Hne Hin Hother Hsep
destruct Hsepp file Hp base Hin as _ & Howners & _
exact Hownersq other Hq Hne Hother
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Stable FILE capability identities cannot enter an active release pool, even when the memory happens to classify them as Heap.
Explore proof 10 tactics
Initial goal
intros m w p file base Hp Hcap Hin Hsep
destruct Hsepp file Hp base Hin as _ & _ & Hnot & _
apply Hnot
right
left
exists mkSpanlibc_stdoutw 0
split ; left ; reflexivity |
simpl
symmetry
exact Hcap
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.