rocq/theories/HelloLocale.v
GNU Hello's locale helpers through the program logic of Logic.v (docs/logic.md): gnulib's hard_locale and the setlocale_null_r chain beneath it, which rpl_mbrtowc calls to decide whether a byte may stand for itself.
setlocale_null_unlocked(k) is setlocale's query of the category k, whose answer is libc's own name for it: a string the world lends (LentLogic.v). setlocale_null_r_unlocked(k, buf, n) copies that name into buf when it fits, returning 0, or the n - 1 bytes that do with a NUL after them, returning ERANGE (34); a name is never NULL, so the EINVAL path (22) is dead. hard_locale(k) copies the name into a 257-byte local and compares it with "C" and "POSIX".
The triples are generic in the world interpretation wi, given that wi keeps every lent string where lent_at says, that setlocale's query answers with the lent pointer and changes nothing, and that wi survives the allocation, the copy and the byte store these functions make into memory they own.
Integer arithmetic on an unknown stays folded when a premise is computed.
The functions
setlocale_null_unlocked(category).
Its one block: setlocale's query, returned.
setlocale_null_r_unlocked(category, buf, bufsize).
Query the name; is it NULL?
Its length; does it fit?
It fits: copy it with its NUL, and return 0.
It does not: is there room for anything?
Copy what fits, and end it with a NUL.
Return ERANGE.
setlocale_null_r(category, buf, bufsize), without a lock.
Its one block: the unlocked call, returned.
hard_locale(category).
A 257-byte buffer, and the name into it.
The name did not fit: not a hard locale.
Is it "C"?
Is it "POSIX"?
Branch on the answer.
A hard locale.
"C" or "POSIX": not a hard locale.
setlocale_null_unlocked has its entry.
Explore proof 2 tactics
Initial goal
vm_compute
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
setlocale_null_r_unlocked has its entry.
Explore proof 2 tactics
Initial goal
vm_compute
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
setlocale_null_r_unlocked has L10.
Explore proof 2 tactics
Initial goal
vm_compute
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
setlocale_null_r_unlocked has L27.
Explore proof 2 tactics
Initial goal
vm_compute
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
setlocale_null_r_unlocked has L28.
Explore proof 2 tactics
Initial goal
vm_compute
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
setlocale_null_r_unlocked has L39.
Explore proof 2 tactics
Initial goal
vm_compute
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
setlocale_null_r_unlocked has L41.
Explore proof 2 tactics
Source script
setlocale_null_r has its entry.
Explore proof 2 tactics
Initial goal
vm_compute
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
hard_locale has its entry.
Explore proof 2 tactics
Initial goal
vm_compute
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
hard_locale has L3.
Explore proof 2 tactics
Source script
hard_locale has L5.
Explore proof 2 tactics
Initial goal
vm_compute
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
hard_locale has L16.
Explore proof 2 tactics
Initial goal
vm_compute
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
hard_locale has L17.
Explore proof 2 tactics
Initial goal
vm_compute
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
hard_locale has L10.
Explore proof 2 tactics
Source script
hard_locale has L12.
Explore proof 2 tactics
Source script
setlocale_null_unlocked's entry binds its category.
Explore proof 1 tactics
setlocale_null_r_unlocked's entry binds its category, buffer and size.
Explore proof 1 tactics
Source script
setlocale_null_r's entry binds its category, buffer and size.
Explore proof 1 tactics
Source script
hard_locale's entry binds its category.
Explore proof 1 tactics
Initial goal
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The genv's functions, for a genv with Hello's module.
Explore proof 5 tactics
Initial goal
intros Hm
unfold find_fn
rewrite Hm
vm_compute
auto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The literals "C" and "POSIX" of hard-locale.c, read-only.
Its bytes.
"POSIX".
Its bytes.
Hello's symbols put the two literals there.
Explore proof 2 tactics
Initial goal
vm_compute
auto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
What setlocale_null_r_unlocked leaves in an n-byte buffer for the name t: the result r, the string u now at the buffer's start and the buffer's bytes ys. A name shorter than the buffer is copied with its NUL and r is 0; a longer one is cut to n - 1 bytes and a NUL, and r is ERANGE (34).
Take every branch of the goal's conditions: each path is safe.
The triples
The locale helpers over any runtime R.
The genv links Hello, whose world interpretation keeps every lent string where lent_at says.
setlocale's contract spec answers a query, of a category whose name the world lends, with that name, changing nothing; the query's arguments are admitted wherever the name is lent.
strlen and memcpy have their contracts.
The world interpretation survives a copy into a block the program owns, whatever bytes it leaves there, and a byte store into one.
strcmp has its contract, for streq.
The Iris instance of the registry and wi.
The expressions of the language.
setlocale_null_unlocked(k) returns the name the world lends for k.
Explore proof 11 tactics
Initial goal
intros Hk32
iIntros #Hk HΦ
rewrite snu_entry
iApply wp_enter ; exact find_u_start | reflexivity |
iNext
cbn [ b_insts b_jump u_start ]
iApply wp_lent_query_ _ _ _ _ _ _ _ _ _ _ _ set_spec WIntk; WPtrmkPtr0 CNone k p t with Hk ; exact Hset | exact Hset_ret | apply linked_outside ; exact Hlinked | reflexivity | apply linked_unbound ; exact Hlinked | reflexivity | reflexivity | cbn ; rewrite Z.mod_small ; reflexivity | exact Hk32 | apply Hset_abi | intros m w h Hw Hl ; exact Hset_prem w h k p t mkPtr0 CNone Hw Hl eq_refl | intros s m w h tr en s′ m′ w′ Hw Hl Hi ; exact Hset_query_ _ s m w h k p t mkPtr0 CNone tr en s' m' w' Hw Hl eq_refl Hi |
iNext
iApply wp_ret ; reflexivity | reflexivity |
iNext
iExact HΦ
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
setlocale_null_r_unlocked(k, buf, n), for the n-byte block of the bytes xs and the slots cs at the start of the live object b, at a multiple of 8, and the name t the world lends for k: it leaves snru_result in the block and returns its r.
Proof 147 steps Qed
The name fits: copy it with its NUL.
The name does not fit: copy n - 1 bytes of it and end them with a NUL.
setlocale_null_r(k, buf, n) is setlocale_null_r_unlocked's call (snru_spec): this build takes no lock.
Proof 18 steps Qed
The genv's literals are Hello's, and streq and setlocale_null_r are its functions.
Explore proof 5 tactics
Initial goal
destruct locale_globals as H1 & H2
destruct Hlinked as Hm & Hg & _
split ; exact Hg_ _ H1 |
split ; exact Hg_ _ H2 |
split ; unfold find_fn ; rewrite Hm ; vm_compute ; reflexivity | exact proj2proj2locale_fnsge Hm
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
hard_locale(k), for the name t the world lends for k, and the literals "C" and "POSIX" owned as strings: it copies the name into a fresh 257-byte buffer, compares it with both, and returns.
Proof 116 steps Qed
The name fit: compare it with "C", then "POSIX".
The name did not fit: not a hard locale.
HelloLocaleOn over a Logic instance of its own.