rocq/theories/HelloConvDefs.v
The pure part of GNU Hello's conversion proofs
The definitions and lemmas of HelloConv that do not need the program logic: memory read as lists, spans of live objects, a block after a call, libc's private state, and the IR of gnulib's rpl_mbrtowc and rpl_mbsrtowcs. They live apart so that HelloMain, which uses a few of them, does not wait for the conversion's triples.
Memory read as lists
The n bytes of the memory m from the address a.
The n aux slots of the memory m from the address a.
As le_value(Bytes, U): the little-endian integer of the bytes xs.
As many bytes as asked for.
Explore proof 3 tactics
Source script
As many slots as asked for.
Explore proof 3 tactics
Source script
The memory reads back the bytes xs it holds from a.
Explore proof 12 tactics
Initial goal
intros H
apply list_eq
intros i
unfold mem_bytes
rewrite list_lookup_fmap
destruct xs !! i as x | eqn: E
2 open–rewrite lookup_seq_lt ; | exact lookup_lt_Some_ _ _ E
2 opencbn
2 openf_equal
2 openexact Hi x E
–rewrite lookup_seq_ge ; reflexivity |
exact lookup_ge_None_1_ _ E
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A four-byte load is the little-endian value of the four bytes.
Explore proof 4 tactics
Initial goal
unfold load_bytes , le_value , mem_bytes
change Z.to_nat4 with 4%nat
cbn
ring
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The state bytes of mbrtowc_pre are the eight bytes at state.
Explore proof 1 tactics
Initial goal
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Spans of live objects
Spans inside two different live objects are apart.
Explore proof 4 tactics
Initial goal
intros Hd H1 H2 Hne
unfold spans_apart
cbn
destruct Hd_ _ _ _ H1 H2 Hne ; lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A span apart from an object's whole extent is apart from every span inside it.
Explore proof 3 tactics
Initial goal
unfold spans_apart
cbn
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Apart spans share no address.
Explore proof 2 tactics
Initial goal
unfold spans_apart , span_contains
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The bytes xs from offset o of the live object b, where they agree: in its bounds, and held by the memory.
Explore proof 13 tactics
Initial goal
intros Hl Ha Hne
destruct xs as | x0 xs′ ; congruence |
destruct byte_ps_agreem b reg o x0 :: xs′ 0 x0 Hl Ha eq_refl as _ & H0 & _
destruct lookup_lt_is_Some_2x0 :: xs′ lengthxs′ ltac:cbn ; lia as y Hy
destruct byte_ps_agree_ _ _ _ _ _ _ Hl Ha Hy as _ & _ & H1
cbn [ length ] in *
split ; lia |
split ; lia |
intros i x Hx
destruct byte_ps_agree_ _ _ _ _ _ _ Hl Ha Hx as Hv & _
rewrite <- Hv
f_equal
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A block after a call
The block of k bytes from offset o of the object b, live in m' with the region reg and in its bounds, holding what m' holds there, agrees with m'.
Explore proof 36 tactics
Initial goal
intros Hl Ho He Hin
unfold block_ps in Hin
apply elem_of_cons in Hin as Hin | Hin
2 open{injection Hin as → →
2 openexact Hl
assert Hreg : registeredm′ b by destruct Hl as E _ ; unfold registered ; congruence
apply elem_of_app in Hin as Hin | Hin
2 openfocused goal
–apply byte_ps_elem in Hin as i & x & Hx & → & →
2 opendeferred goal
unfold mem_bytes in Hx
2 opendeferred goal
apply list_lookup_fmap_Some in Hx as i′ & → & Hi
2 opendeferred goal
apply lookup_seq in Hi as → Hi
2 opendeferred goal
cbn [ agree_piece ]
2 opendeferred goal
split ; exact Hreg |
2 opendeferred goal
intros reg′ E L
2 opendeferred goal
destruct Hl as E0 _
2 opendeferred goal
rewrite E0 in E
2 opendeferred goal
injection E as ←
2 opendeferred goal
split ; lia |
2 opendeferred goal
split ; lia |
2 opendeferred goal
f_equal
2 opendeferred goal
lia
deferred goal
–apply aux_ps_elem in Hin as i & c & Hc & → & →
unfold mem_auxes in Hc
apply list_lookup_fmap_Some in Hc as i′ & → & Hi
apply lookup_seq in Hi as → Hi
cbn [ agree_piece ]
split ; exact Hreg |
intros reg′ E L
destruct Hl as E0 _
rewrite E0 in E
injection E as ←
split ; lia |
split ; lia |
left
f_equal
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A byte or aux piece of a live object, inside its bounds at an address inside the k bytes from offset o of the live object b, is among the keys of the block there.
Explore proof 8 tactics
Initial goal
intros Hd Hl Ho He Hc Hk Hl′ Ho′ He′ Ha
assert b′ = b as →
2 open{destruct Z.eq_decb′ b as E | Hne ; exact E |
2 opendestruct Hd_ _ _ _ Hl′ Hl Hne ; lia
rewrite fmap_app
apply elem_of_app
replace o′ with o + o′ − o in Hk by lia
destruct Hk as → | → ; left ; apply byte_ps_key | right ; apply aux_ps_key ; lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
What owning a block of the bytes xs tells about the memory: its object is live, the bytes are in its bounds, and the memory holds them.
Explore proof 18 tactics
Initial goal
intros Ha Hlk Hne
assert Hl : live_atm b reg
2 openfocused goal
{apply HaPLiveb VLivereg , Hlk
2 opendeferred goal
apply elem_of_cons
2 opendeferred goal
left
2 opendeferred goal
reflexivity
deferred goal
assert Hx : all_agreem byte_psb o xs
2 open{apply all_agree_intro
2 openintros l v Hin
2 openapply Ha , Hlk
2 openunfold block_ps
2 openapply elem_of_cons
2 openright
2 openapply elem_of_app
2 openleft
2 openexact Hin
split ; exact Hl |
exact byte_block_factsm b reg o xs Hl Hx Hne
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A list of length k + 1 is not empty.
Explore proof 2 tactics
Initial goal
intros H →
discriminate H
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A block's byte and aux keys hold no life piece.
Explore proof 3 tactics
Initial goal
rewrite fmap_app byte_ps_keys aux_ps_keys
intros Hin
apply elem_of_app in Hin as Hin | Hin ; apply list_elem_of_fmap in Hin as ? & E & _ ; discriminate E
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A block's byte and aux keys are keys of the block after a call, of as many bytes and slots.
Explore proof 7 tactics
Initial goal
intros Hx Hc Hin
rewrite block_ps_keysb reg o xs cs ; | rewrite length_mem_bytes ; auto | rewrite length_mem_auxes ; auto
unfold block_ps
rewrite fmap_cons
apply elem_of_cons
right
exact Hin
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
libc's private state
libc's private state keeps apart from the program's objects: no piece of h is of an object libc may release, and of every live object owning a piece of h, every private root lies outside its extent and libc's private sources hand out none of its capabilities.
What the program learns from mbrtowc(out, src, n, state) returning r, for 0 < n and the audited codec, read through the bytes it owns (mbrtowc_result): ss are the source bytes and xo the output's bytes before the call; xo', ys' and xe' the output's, state's and errno's bytes after it. A NUL converts to 0 and resets the state; a character of r bytes, none of them NUL, to a nonzero wide character; an invalid sequence sets errno to EILSEQ (84); an incomplete one, under the audited codec, is shorter than 16 bytes with no NUL. Under the audited C codec (CodecC) an invalid sequence keeps the state's bytes ys and starts with a byte of 128 or more (mbrtowc_c_error).
gnulib's rpl_mbrtowc
rpl_mbrtowc(pwc, s, n, ps): mbrtowc into pwc, or into a local if pwc is null; on an invalid or incomplete sequence, outside a hard locale, the first byte stands for itself.
A block of rpl_mbrtowc.
rpl_mbrtowc's entry binds its four arguments.
Explore proof 1 tactics
Initial goal
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A signed byte load, then its low byte unsigned: the byte.
Explore proof 17 tactics
Initial goal
intros Hx
cbn [ extension ]
unfold sign_extension
assert E : x mod 256 = x by apply Z.mod_small ; lia
rewrite E
destruct Z.leb_spec128 x as Hh | Hh
2 openfocused goal
–assert E2 : x − 256 mod 2 ^ 32 = x − 256 + 2 ^ 32 by symmetry ; apply Z.mod_unique with −1 ; lia
2 opendeferred goal
rewrite E2
2 opendeferred goal
assert E3 : x − 256 + 2 ^ 32 mod 256 = x by symmetry ; apply Z.mod_unique with 2 ^ 24 − 1 ; lia
2 opendeferred goal
rewrite E3
2 opendeferred goal
apply Z.mod_small
2 opendeferred goal
lia
deferred goal
–assert E2 : x mod 2 ^ 32 = x by apply Z.mod_small ; lia
rewrite E2
rewrite E
apply Z.mod_small
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
What rpl_mbrtowc's caller learns, in conv_result's terms: mbrtowc's own answer r', or, after an invalid or incomplete sequence outside a hard locale, 1, with the first byte x stored as the wide character.
mbrtowc's answers are 64-bit words, and the two at the top are the invalid and the incomplete sequence, which leave the output alone.
Explore proof 1 tactics
Initial goal
intros → & _ | Hr & Hr2 & _ | → & _ & Hx & _ | → & _ & Hx & _ ; split ; try lia ; auto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
gnulib's rpl_mbsrtowcs
rpl_mbsrtowcs(dest, srcp, len, ps): converts the string at *srcp into at most len wide characters at dest, one rpl_mbrtowc call per character, each given a window of n bytes that reaches the NUL or is 16 bytes long.
A block of rpl_mbsrtowcs.
A nonzero byte loaded signed is not zero.
Explore proof 7 tactics
Initial goal
intros Hx
apply Z.eqb_neq
destruct Z.leb_spec128 x
2 openfocused goal
–assert E : x − 256 mod 2 ^ 32 = x − 256 + 2 ^ 32 by symmetry ; apply Z.mod_unique with −1 ; lia
2 opendeferred goal
rewrite E
2 opendeferred goal
lia
deferred goal
–rewrite Z.mod_small ; lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
In a string's bytes and NUL, a zero byte is the NUL.
Explore proof 12 tactics
Initial goal
intros Hbs Hk
pose proof proj1Forall_lookup_ _ Hbs as Hb
apply lookup_app_Some in Hk as Hk | Hl Hk
2 openfocused goal
–pose proof Hb_ _ Hk as Hx
2 opendeferred goal
cbv beta in Hx
2 opendeferred goal
apply lookup_lt_Some in Hk
2 opendeferred goal
split ; lia |
2 opendeferred goal
split ; intros E ; lia | auto
deferred goal
–apply list_lookup_singleton_Some in Hk as Hk Ex
subst x
split ; lia |
split ; intros _ ; lia | intros E ; lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A window of four bytes and a count from the fifth: what strnlen1's answer plus 4 comes to.
Explore proof 2 tactics
Initial goal
(4 <= l)%nat → ((l - 4)%nat + 1) `min` 12 + 4 = (l + 1) `min` 16intros Hl
((l - 4)%nat + 1) `min` 12 + 4 = (l + 1) `min` 16lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A byte stored as a four-byte word reads back as itself.
Explore proof 15 tactics
Initial goal
intros Hx
unfold le_bytes , le_value , byte_of
cbn
change 8 × Z.of_nat1 with 8
change 8 × Z.of_nat2 with 16
change 8 × Z.of_nat3 with 24
change 8 × Z.of_nat0 with 0
rewrite Z.pow_0_r
rewrite Z.div_1_r
rewrite Z.mod_smallx 256 ; | lia
rewrite Z.div_smallx 2 ^ 8 ; | lia
rewrite Z.div_smallx 2 ^ 16 ; | lia
rewrite Z.div_smallx 2 ^ 24 ; | lia
rewrite Zmod_0_l
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A run of nonzero bytes at the start of a string and its NUL ends before the NUL.
Explore proof 9 tactics
Initial goal
intros Hr H
destruct Z.le_gt_casesr Z.of_natlengthbs as Hle | Hgt ; exact Hle |
exfalso
rewrite Forall_lookup in H
apply Hlengthbs 0 ; | reflexivity
rewrite lookup_take_lt ; | lia
rewrite lookup_app_r ; | lia
rewrite Nat.sub_diag
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
One rpl_mbrtowc call of rpl_mbsrtowcs's converting loop, on the suffix bs of the string, with the window that reaches the NUL or is 16 bytes long, from a valid state in its initial shift state: never the incomplete answer, which would abort; EILSEQ stores 84 in errno; the NUL stores a zero character; anything else consumes r bytes before the NUL and stores a nonzero character, leaving a valid initial state.
Explore proof 20 tactics
Initial goal
Forall (λ x : Z, 0 < x < 256) bs
→ valid codec ys
→ le_value (take 4 ys) = 0
→ rpl_result valid c codec ((length bs + 1) `min` 16)
(bs ++ [0]) xo ys xo' ys' xe' r
→ 0 <= r < 2 ^ 64
∧ r ≠ 2 ^ 64 - 2
∧ (r = 2 ^ 64 - 1 → le_value xe' = 84)
∧ (r = 0 → le_value xo' = 0)
∧ (r ≠ 0
→ r ≠ 2 ^ 64 - 1
→ 0 < r <= length bs
∧ 0 < le_value xo' < 2 ^ 32
∧ valid codec ys' ∧ le_value (take 4 ys') = 0)intros Hbs Hval Hinit Hres
Hres :
rpl_result valid c codec ((length bs + 1) `min` 16)
(bs ++ [0]) xo ys xo' ys' xe' rassert No2 : ∀ys1 xo1 r1, ¬r1 = 2 ^ 64 − 2 ∧ validcodec ys1 ∧ xo1 = xo ∧ Z.minZ.of_natlengthbs + 1 16 < 16 ∧ Forallλx ⇒ x ≠ 0 takeZ.to_natZ.minZ.of_natlengthbs + 1 16 bs ++ 0
2 openHres :
rpl_result valid c codec ((length bs + 1) `min` 16)
(bs ++ [0]) xo ys xo' ys' xe' r∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))focused goal
Hres :
rpl_result valid c codec ((length bs + 1) `min` 16)
(bs ++ [0]) xo ys xo' ys' xe' rNo2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0]))){intros ys1 xo1 r1 _ & _ & _ & Hn16 & Hnz
2 openHres :
rpl_result valid c codec ((length bs + 1) `min` 16)
(bs ++ [0]) xo ys xo' ys' xe' rHn16 : (length bs + 1) `min` 16 < 16Hnz :
Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0]))deferred goal
Hres :
rpl_result valid c codec ((length bs + 1) `min` 16)
(bs ++ [0]) xo ys xo' ys' xe' rNo2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))apply before_nul in Hnz ; lia
deferred goal
Hres :
rpl_result valid c codec ((length bs + 1) `min` 16)
(bs ++ [0]) xo ys xo' ys' xe' rNo2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))destruct Hres as Hc | → & r0 & Hr0 & Hc0 & x & Hx & →
2 openHc :
conv_result valid c codec ((length bs + 1) `min` 16)
(bs ++ [0]) xo ys xo' ys' xe' rNo2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))focused goal
Hc0 :
conv_result valid c codec ((length bs + 1) `min` 16)
(bs ++ [0]) xo ys xo ys' xe' r0No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))–destruct Hc as → & _ & _ & Ho & _ | Hr & Hr2 & Hv & Ho & Hs & Hnz | → & He & _ | H2
5 openNo2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))focused goal
Hr : 0 < r <= (length bs + 1) `min` 16No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))focused goal
No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))focused goal
H2 :
r = 2 ^ 64 - 2
∧ valid codec ys'
∧ xo' = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0]))No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))deferred goal
Hc0 :
conv_result valid c codec ((length bs + 1) `min` 16)
(bs ++ [0]) xo ys xo ys' xe' r0No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))+repeat split ; try lia ; auto
4 opendeferred goal
Hr : 0 < r <= (length bs + 1) `min` 16No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))deferred goal
No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))deferred goal
H2 :
r = 2 ^ 64 - 2
∧ valid codec ys'
∧ xo' = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0]))No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))deferred goal
Hc0 :
conv_result valid c codec ((length bs + 1) `min` 16)
(bs ++ [0]) xo ys xo ys' xe' r0No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))+apply before_nul in Hnz ; | lia
4 openHr : 0 < r <= (length bs + 1) `min` 16No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))deferred goal
No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))deferred goal
H2 :
r = 2 ^ 64 - 2
∧ valid codec ys'
∧ xo' = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0]))No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))deferred goal
Hc0 :
conv_result valid c codec ((length bs + 1) `min` 16)
(bs ++ [0]) xo ys xo ys' xe' r0No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))repeat split ; try lia ; auto
3 opendeferred goal
No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))deferred goal
H2 :
r = 2 ^ 64 - 2
∧ valid codec ys'
∧ xo' = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0]))No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))deferred goal
Hc0 :
conv_result valid c codec ((length bs + 1) `min` 16)
(bs ++ [0]) xo ys xo ys' xe' r0No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))+repeat split ; try lia ; auto
2 opendeferred goal
H2 :
r = 2 ^ 64 - 2
∧ valid codec ys'
∧ xo' = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0]))No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))deferred goal
Hc0 :
conv_result valid c codec ((length bs + 1) `min` 16)
(bs ++ [0]) xo ys xo ys' xe' r0No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))+exfalso
2 openH2 :
r = 2 ^ 64 - 2
∧ valid codec ys'
∧ xo' = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0]))No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))deferred goal
Hc0 :
conv_result valid c codec ((length bs + 1) `min` 16)
(bs ++ [0]) xo ys xo ys' xe' r0No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))exact No2_ _ _ H2
deferred goal
Hc0 :
conv_result valid c codec ((length bs + 1) `min` 16)
(bs ++ [0]) xo ys xo ys' xe' r0No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))–destruct nul_index_ _ _ Hbs Hx as Hxr & _ & Hn
Hc0 :
conv_result valid c codec ((length bs + 1) `min` 16)
(bs ++ [0]) xo ys xo ys' xe' r0No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))destruct Hc0 as → & _ | _ & Hr2 & _ | _ & _ & _ & _ & Hlaw | H2 ; try lia ; | exfalso ; exact No2_ _ _ H2
No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))destruct HlawHval Hinit as Hv′ & Hs′ & x′ & Hx′ & Hx0
No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))rewrite Hx in Hx′
No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))injection Hx′ as ←
No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))pose proof HnHx0 as Hlen
No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))rewrite le_value_bytex Hxr
No2 :
∀ (ys1 xo1 : list Z) (r1 : Z),
¬ (r1 = 2 ^ 64 - 2
∧ valid codec ys1
∧ xo1 = xo
∧ (length bs + 1) `min` 16 < 16
∧ Forall (λ x : Z, x ≠ 0)
(take (Z.to_nat ((length bs + 1) `min` 16)) (bs ++ [0])))repeat split ; try lia ; auto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The four-byte words of ws are wide characters, none of them zero.
No words, no wide characters.
Explore proof 3 tactics
A nonzero wide character after i of them.
Explore proof 10 tactics
Initial goal
intros Hw Lw Lx Hx k Hk
rewrite length_app in Hk
destruct decide4 × k + 4 ≤ lengthws%nat as Hlt | Hge
2 open–rewrite drop_app_le ; | lia
2 openrewrite take_app_le ; | rewrite length_drop ; lia
2 openapply Hw
2 openexact Hlt
–assert Ek : 4 × k = lengthws%nat by lia
rewrite Ek drop_app_length
rewrite take_ge ; exact Hx | lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.