1use crate::combinators::{Refined, Tail};
9use crate::core::exec::input::InputSlice;
10use crate::core::exec::output::OutputBuf;
11use crate::core::exec::{
12 parser::{PResult, Parser},
13 serializer::{ByteLen, PreSerializeError, Prepare, Serializer},
14 ParseError,
15};
16use crate::core::{proof::*, spec::*};
17use vstd::prelude::*;
18
19use super::RealFmt;
20
21verus! {
22
23pub type RealSpec = Seq<u8>;
24
25pub type RealInnerFmt = Refined<Tail, PredFnSpec<Seq<u8>>>;
26
27pub const REAL_PLUS_INFINITY: u8 = 0x40;
28
29pub const REAL_MINUS_INFINITY: u8 = 0x41;
30
31pub const REAL_NOT_A_NUMBER: u8 = 0x42;
32
33pub const REAL_MINUS_ZERO: u8 = 0x43;
34
35pub const REAL_DECIMAL_NR3: u8 = 0x03;
36
37pub const ASCII_SPACE: u8 = 0x20;
38
39pub const ASCII_ZERO: u8 = 0x30;
40
41pub const ASCII_ONE: u8 = 0x31;
42
43pub const ASCII_NINE: u8 = 0x39;
44
45pub const ASCII_MINUS: u8 = 0x2d;
46
47pub const ASCII_PLUS: u8 = 0x2b;
48
49pub const ASCII_FULL_STOP: u8 = 0x2e;
50
51pub const ASCII_COMMA: u8 = 0x2c;
52
53pub const ASCII_E: u8 = 0x45;
54
55pub const ASCII_LOWER_E: u8 = 0x65;
56
57pub open spec fn ascii_digit(b: u8) -> bool {
58 ASCII_ZERO <= b <= ASCII_NINE
59}
60
61pub open spec fn ascii_nonzero_digit(b: u8) -> bool {
62 ASCII_ONE <= b <= ASCII_NINE
63}
64
65pub open spec fn ascii_digits(bytes: Seq<u8>, start: int, end: int) -> bool {
66 forall|i: int| #![auto] start <= i < end ==> ascii_digit(bytes[i])
67}
68
69pub open spec fn ascii_digits_have_nonzero(bytes: Seq<u8>, start: int, end: int) -> bool {
70 exists|i: int| #![auto] start <= i < end && ascii_nonzero_digit(bytes[i])
71}
72
73pub open spec fn skip_ascii_spaces(bytes: Seq<u8>, start: nat) -> nat
74 decreases bytes.len() - start,
75{
76 if start < bytes.len() && bytes[start as int] == ASCII_SPACE {
77 skip_ascii_spaces(bytes, start + 1)
78 } else {
79 start
80 }
81}
82
83pub open spec fn scan_ascii_digits(bytes: Seq<u8>, start: nat) -> nat
84 decreases bytes.len() - start,
85{
86 if start < bytes.len() && ascii_digit(bytes[start as int]) {
87 scan_ascii_digits(bytes, start + 1)
88 } else {
89 start
90 }
91}
92
93pub open spec fn decimal_mark(b: u8) -> bool {
94 b == ASCII_FULL_STOP || b == ASCII_COMMA
95}
96
97pub open spec fn exponent_mark(b: u8) -> bool {
98 b == ASCII_E || b == ASCII_LOWER_E
99}
100
101pub open spec fn after_optional_sign(bytes: Seq<u8>, start: nat) -> nat {
102 if start < bytes.len() && (bytes[start as int] == ASCII_PLUS || bytes[start as int]
103 == ASCII_MINUS) {
104 start + 1
105 } else {
106 start
107 }
108}
109
110pub open spec fn ber_real_decimal_nr1_wf(bytes: Seq<u8>) -> bool {
111 let start = after_optional_sign(bytes, skip_ascii_spaces(bytes, 1));
112 let end = scan_ascii_digits(bytes, start);
113 &&& start < end
114 &&& end == bytes.len()
115 &&& ascii_digits_have_nonzero(bytes, start as int, end as int)
116}
117
118pub open spec fn ber_real_decimal_significand(bytes: Seq<u8>) -> Option<(nat, nat, nat, nat)> {
119 let before = after_optional_sign(bytes, skip_ascii_spaces(bytes, 1));
120 let mark = scan_ascii_digits(bytes, before);
121 if mark < bytes.len() && decimal_mark(bytes[mark as int]) {
122 let after = mark + 1;
123 let end = scan_ascii_digits(bytes, after);
124 if before < mark || after < end {
125 Some((before, mark, after, end))
126 } else {
127 None
128 }
129 } else {
130 None
131 }
132}
133
134pub open spec fn ber_real_decimal_mantissa_nonzero(
135 bytes: Seq<u8>,
136 before: nat,
137 mark: nat,
138 after: nat,
139 end: nat,
140) -> bool {
141 ||| ascii_digits_have_nonzero(bytes, before as int, mark as int)
142 ||| ascii_digits_have_nonzero(bytes, after as int, end as int)
143}
144
145pub open spec fn ber_real_decimal_nr2_wf(bytes: Seq<u8>) -> bool {
146 match ber_real_decimal_significand(bytes) {
147 Some((before, mark, after, end)) => {
148 &&& end == bytes.len()
149 &&& ber_real_decimal_mantissa_nonzero(bytes, before, mark, after, end)
150 },
151 None => false,
152 }
153}
154
155pub open spec fn ber_real_decimal_nr3_wf(bytes: Seq<u8>) -> bool {
156 match ber_real_decimal_significand(bytes) {
157 Some((before, mark, after, end)) => {
158 if end < bytes.len() && exponent_mark(bytes[end as int]) {
159 let exponent_sign = end + 1;
160 let exponent = exponent_sign + 1;
161 let exponent_end = scan_ascii_digits(bytes, exponent);
162 &&& exponent_sign < bytes.len()
163 &&& (bytes[exponent_sign as int] == ASCII_PLUS || bytes[exponent_sign as int]
164 == ASCII_MINUS)
165 &&& exponent < exponent_end
166 &&& exponent_end == bytes.len()
167 &&& ber_real_decimal_mantissa_nonzero(bytes, before, mark, after, end)
168 } else {
169 false
170 }
171 },
172 None => false,
173 }
174}
175
176pub open spec fn ber_real_decimal_wf(bytes: Seq<u8>) -> bool {
183 &&& bytes.len() > 1
184 &&& match bytes[0] {
185 0x01u8 => ber_real_decimal_nr1_wf(bytes),
186 0x02u8 => ber_real_decimal_nr2_wf(bytes),
187 0x03u8 => ber_real_decimal_nr3_wf(bytes),
188 _ => false,
189 }
190}
191
192pub open spec fn decimal_mantissa_start(bytes: Seq<u8>) -> int {
193 if bytes.len() > 1 && bytes[1] == ASCII_MINUS {
194 2
195 } else {
196 1
197 }
198}
199
200pub open spec fn der_real_decimal_at(bytes: Seq<u8>, dot: int) -> bool {
202 let start = decimal_mantissa_start(bytes);
203 let exponent = dot + 2;
204 &&& bytes.len() >= 6
205 &&& bytes[0] == REAL_DECIMAL_NR3
206 &&& start < dot < bytes.len()
207 &&& ascii_digits(bytes, start, dot)
208 &&& bytes[start] != ASCII_ZERO
209 &&& bytes[dot - 1] != ASCII_ZERO
210 &&& dot + 2 <= bytes.len()
211 &&& bytes[dot] == ASCII_FULL_STOP
212 &&& bytes[dot + 1] == ASCII_E
213 &&& {
214 ||| exponent + 2 == bytes.len() && bytes[exponent] == ASCII_PLUS && bytes[exponent + 1]
216 == ASCII_ZERO
217 ||| {
220 let digits = if exponent < bytes.len() && bytes[exponent] == ASCII_MINUS {
221 exponent + 1
222 } else {
223 exponent
224 };
225 &&& exponent < bytes.len()
226 &&& bytes[exponent] != ASCII_PLUS
227 &&& digits < bytes.len()
228 &&& ASCII_ONE <= bytes[digits] <= ASCII_NINE
229 &&& ascii_digits(bytes, digits, bytes.len() as int)
230 }
231 }
232}
233
234pub open spec fn der_real_decimal_wf(bytes: Seq<u8>) -> bool {
235 exists|dot: int| der_real_decimal_at(bytes, dot)
236}
237
238pub open spec fn der_real_exponent_minimal(bytes: Seq<u8>, offset: int, len: int) -> bool {
239 &&& len > 0
240 &&& offset >= 0
241 &&& offset + len <= bytes.len()
242 &&& (len > 1 ==> {
243 &&& !(bytes[offset] == 0x00u8 && bytes[offset + 1] < 0x80u8)
244 &&& !(bytes[offset] == 0xffu8 && bytes[offset + 1] >= 0x80u8)
245 })
246}
247
248pub open spec fn der_real_binary_wf(bytes: Seq<u8>) -> bool {
250 if bytes.len() < 3 {
251 false
252 } else {
253 let info = bytes[0];
254 let form = info & 0x03u8;
255 let exponent_offset: int = if form == 0x03u8 {
256 2
257 } else {
258 1
259 };
260 let exponent_len: int = match form {
261 0x00u8 => 1,
262 0x01u8 => 2,
263 0x02u8 => 3,
264 _ => bytes[1] as int,
265 };
266 let mantissa_offset = exponent_offset + exponent_len;
267 &&& info & 0x80u8
268 != 0
269 &&& info & 0x30u8 == 0
271 &&& info & 0x0cu8
272 == 0
273 &&& (form == 0x03u8 ==> exponent_len >= 4)
276 &&& der_real_exponent_minimal(bytes, exponent_offset, exponent_len)
277 &&& mantissa_offset
278 < bytes.len()
279 &&& bytes[mantissa_offset] != 0
281 &&& bytes.last() & 1u8 == 1u8
282 }
283}
284
285pub open spec fn ber_real_binary_wf(bytes: Seq<u8>) -> bool {
287 if bytes.len() < 3 {
288 false
289 } else {
290 let info = bytes[0];
291 let form = info & 0x03u8;
292 let exponent_offset: int = if form == 0x03u8 {
293 2
294 } else {
295 1
296 };
297 let exponent_len: int = match form {
298 0x00u8 => 1,
299 0x01u8 => 2,
300 0x02u8 => 3,
301 _ => bytes[1] as int,
302 };
303 let mantissa_offset = exponent_offset + exponent_len;
304 &&& info & 0x80u8
305 != 0
306 &&& info & 0x30u8
308 != 0x30u8
309 &&& (form == 0x03u8 ==> {
312 &&& exponent_len > 0
313 &&& der_real_exponent_minimal(bytes, exponent_offset, exponent_len)
314 })
315 &&& mantissa_offset
316 < bytes.len()
317 &&& exists|i: int| mantissa_offset <= i < bytes.len() && bytes[i] != 0u8
320 }
321}
322
323pub open spec fn der_real_special_wf(bytes: Seq<u8>) -> bool {
324 bytes.len() == 1 && (bytes[0] == REAL_PLUS_INFINITY || bytes[0] == REAL_MINUS_INFINITY
325 || bytes[0] == REAL_NOT_A_NUMBER || bytes[0] == REAL_MINUS_ZERO)
326}
327
328pub open spec fn der_real_bytes_wf(bytes: Seq<u8>) -> bool {
330 ||| bytes.len() == 0 ||| der_real_special_wf(bytes)
332 ||| der_real_binary_wf(bytes)
333 ||| der_real_decimal_wf(bytes)
334}
335
336pub open spec fn ber_real_bytes_wf(bytes: Seq<u8>) -> bool {
338 ||| bytes.len() == 0 ||| der_real_special_wf(bytes)
340 ||| ber_real_binary_wf(bytes)
341 ||| ber_real_decimal_wf(bytes)
342}
343
344pub open spec fn real_bytes_wf<const DER: bool>(bytes: Seq<u8>) -> bool {
345 if DER {
346 der_real_bytes_wf(bytes)
347 } else {
348 ber_real_bytes_wf(bytes)
349 }
350}
351
352pub proof fn lemma_der_real_bytes_cases(bytes: Seq<u8>)
353 ensures
354 bytes.len() == 0 ==> der_real_bytes_wf(bytes),
355 bytes.len() == 1 ==> (der_real_bytes_wf(bytes) <==> der_real_special_wf(bytes)),
356 bytes.len() > 1 && bytes[0] & 0x80u8 != 0 ==> (der_real_bytes_wf(bytes)
357 <==> der_real_binary_wf(bytes)),
358 bytes.len() > 1 && bytes[0] & 0x80u8 == 0 && bytes[0] == REAL_DECIMAL_NR3 ==> (
359 der_real_bytes_wf(bytes) <==> der_real_decimal_wf(bytes)),
360 bytes.len() > 1 && bytes[0] & 0x80u8 == 0 && bytes[0] != REAL_DECIMAL_NR3
361 ==> !der_real_bytes_wf(bytes),
362{
363 if bytes.len() > 1 && bytes[0] & 0x80u8 != 0 {
364 if der_real_decimal_wf(bytes) {
365 let dot = choose|dot: int| der_real_decimal_at(bytes, dot);
366 assert(bytes[0] == REAL_DECIMAL_NR3);
367 assert(REAL_DECIMAL_NR3 & 0x80u8 == 0) by (bit_vector);
368 }
369 }
370}
371
372pub proof fn lemma_ber_real_bytes_cases(bytes: Seq<u8>)
373 ensures
374 bytes.len() == 0 ==> ber_real_bytes_wf(bytes),
375 bytes.len() == 1 ==> (ber_real_bytes_wf(bytes) <==> der_real_special_wf(bytes)),
376 bytes.len() > 1 && bytes[0] & 0x80u8 != 0 ==> (ber_real_bytes_wf(bytes)
377 <==> ber_real_binary_wf(bytes)),
378 bytes.len() > 1 && bytes[0] & 0x80u8 == 0 ==> (ber_real_bytes_wf(bytes)
379 <==> ber_real_decimal_wf(bytes)),
380{
381 if bytes.len() > 1 && bytes[0] & 0x80u8 != 0 {
382 if ber_real_decimal_wf(bytes) {
383 assert(bytes[0] == 0x01u8 || bytes[0] == 0x02u8 || bytes[0] == 0x03u8);
384 assert(0x01u8 & 0x80u8 == 0 && 0x02u8 & 0x80u8 == 0 && 0x03u8 & 0x80u8 == 0)
385 by (bit_vector);
386 }
387 }
388}
389
390pub open spec fn real_fmt<const DER: bool>() -> RealInnerFmt {
391 Refined(Tail, |bytes: Seq<u8>| real_bytes_wf::<DER>(bytes))
392}
393
394pub proof fn lemma_decimal_dot_matches_scan(bytes: Seq<u8>, start: int, scanned: int, dot: int)
395 requires
396 start == decimal_mantissa_start(bytes),
397 0 <= start <= scanned <= bytes.len(),
398 ascii_digits(bytes, start, scanned),
399 scanned == bytes.len() || !ascii_digit(bytes[scanned]),
400 der_real_decimal_at(bytes, dot),
401 ensures
402 dot == scanned,
403{
404 if dot < scanned {
405 assert(ascii_digit(bytes[dot]));
406 assert(bytes[dot] == ASCII_FULL_STOP);
407 } else if scanned < dot {
408 assert(scanned < bytes.len());
409 assert(ascii_digit(bytes[scanned]));
410 }
411}
412
413pub proof fn lemma_decimal_scan_characterizes(bytes: Seq<u8>, start: int, scanned: int)
414 requires
415 start == decimal_mantissa_start(bytes),
416 0 <= start <= scanned <= bytes.len(),
417 ascii_digits(bytes, start, scanned),
418 scanned == bytes.len() || !ascii_digit(bytes[scanned]),
419 ensures
420 der_real_decimal_wf(bytes) <==> der_real_decimal_at(bytes, scanned),
421{
422 if der_real_decimal_wf(bytes) {
423 let dot = choose|dot: int| der_real_decimal_at(bytes, dot);
424 lemma_decimal_dot_matches_scan(bytes, start, scanned, dot);
425 }
426}
427
428fn all_ascii_digits(bytes: &[u8], start: usize, end: usize) -> (ok: bool)
429 requires
430 start <= end <= bytes@.len(),
431 ensures
432 ok == ascii_digits(bytes@, start as int, end as int),
433{
434 let mut i = start;
435 while i < end
436 invariant
437 start <= i <= end <= bytes@.len(),
438 ascii_digits(bytes@, start as int, i as int),
439 decreases end - i,
440 {
441 if !(ASCII_ZERO <= bytes[i] && bytes[i] <= ASCII_NINE) {
442 assert(!ascii_digits(bytes@, start as int, end as int));
443 return false;
444 }
445 i += 1;
446 }
447 true
448}
449
450fn skip_ascii_spaces_exec(bytes: &[u8], start: usize) -> (end: usize)
451 requires
452 start <= bytes@.len(),
453 ensures
454 end == skip_ascii_spaces(bytes@, start as nat),
455 start <= end <= bytes@.len(),
456{
457 let mut i = start;
458 while i < bytes.len() && bytes[i] == ASCII_SPACE
459 invariant
460 start <= i <= bytes@.len(),
461 skip_ascii_spaces(bytes@, start as nat) == skip_ascii_spaces(bytes@, i as nat),
462 decreases bytes@.len() - i,
463 {
464 proof {
465 reveal(skip_ascii_spaces);
466 assert(skip_ascii_spaces(bytes@, i as nat) == skip_ascii_spaces(bytes@, i as nat + 1));
467 }
468 i += 1;
469 }
470 proof {
471 reveal(skip_ascii_spaces);
472 assert(skip_ascii_spaces(bytes@, i as nat) == i as nat);
473 }
474 i
475}
476
477fn scan_ascii_digits_exec(bytes: &[u8], start: usize) -> (end: usize)
478 requires
479 start <= bytes@.len(),
480 ensures
481 end == scan_ascii_digits(bytes@, start as nat),
482 start <= end <= bytes@.len(),
483 ascii_digits(bytes@, start as int, end as int),
484 end == bytes@.len() || !ascii_digit(bytes@[end as int]),
485{
486 let mut i = start;
487 while i < bytes.len() && ASCII_ZERO <= bytes[i] && bytes[i] <= ASCII_NINE
488 invariant
489 start <= i <= bytes@.len(),
490 scan_ascii_digits(bytes@, start as nat) == scan_ascii_digits(bytes@, i as nat),
491 ascii_digits(bytes@, start as int, i as int),
492 decreases bytes@.len() - i,
493 {
494 proof {
495 reveal(scan_ascii_digits);
496 assert(scan_ascii_digits(bytes@, i as nat) == scan_ascii_digits(bytes@, i as nat + 1));
497 }
498 i += 1;
499 }
500 proof {
501 reveal(scan_ascii_digits);
502 assert(scan_ascii_digits(bytes@, i as nat) == i as nat);
503 }
504 i
505}
506
507fn ascii_digits_have_nonzero_exec(bytes: &[u8], start: usize, end: usize) -> (found: bool)
508 requires
509 start <= end <= bytes@.len(),
510 ensures
511 found == ascii_digits_have_nonzero(bytes@, start as int, end as int),
512{
513 let mut i = start;
514 while i < end
515 invariant
516 start <= i <= end <= bytes@.len(),
517 forall|j: int| #![auto] start <= j < i ==> !ascii_nonzero_digit(bytes@[j]),
518 decreases end - i,
519 {
520 if ASCII_ONE <= bytes[i] && bytes[i] <= ASCII_NINE {
521 assert(ascii_digits_have_nonzero(bytes@, start as int, end as int)) by {
522 assert(ascii_nonzero_digit(bytes@[i as int]));
523 }
524 return true;
525 }
526 i += 1;
527 }
528 assert(!ascii_digits_have_nonzero(bytes@, start as int, end as int));
529 false
530}
531
532fn ber_real_decimal_wf_exec(bytes: &[u8]) -> (ok: bool)
533 ensures
534 ok == ber_real_decimal_wf(bytes@),
535{
536 if bytes.len() <= 1 {
537 return false;
538 }
539 let representation = bytes[0];
540 if representation != 0x01u8 && representation != 0x02u8 && representation != 0x03u8 {
541 return false;
542 }
543 let mut start = skip_ascii_spaces_exec(bytes, 1);
544 let ghost unsigned_start = start;
545 if start < bytes.len() && (bytes[start] == ASCII_PLUS || bytes[start] == ASCII_MINUS) {
546 start += 1;
547 }
548 assert(start as nat == after_optional_sign(bytes@, unsigned_start as nat));
549
550 if representation == 0x01u8 {
551 let end = scan_ascii_digits_exec(bytes, start);
552 if start >= end || end != bytes.len() {
553 return false;
554 }
555 return ascii_digits_have_nonzero_exec(bytes, start, end);
556 }
557 let mark = scan_ascii_digits_exec(bytes, start);
558 if mark >= bytes.len() || !(bytes[mark] == ASCII_FULL_STOP || bytes[mark] == ASCII_COMMA) {
559 return false;
560 }
561 let after = mark + 1;
562 let end = scan_ascii_digits_exec(bytes, after);
563 if start == mark && after == end {
564 return false;
565 }
566 assert(ber_real_decimal_significand(bytes@) == Some(
567 (start as nat, mark as nat, after as nat, end as nat),
568 ));
569 let before_nonzero = ascii_digits_have_nonzero_exec(bytes, start, mark);
570 let after_nonzero = ascii_digits_have_nonzero_exec(bytes, after, end);
571 let nonzero = before_nonzero || after_nonzero;
572
573 if representation == 0x02u8 {
574 return end == bytes.len() && nonzero;
575 }
576 if end >= bytes.len() || !(bytes[end] == ASCII_E || bytes[end] == ASCII_LOWER_E) {
577 return false;
578 }
579 let exponent_sign = end + 1;
580 if exponent_sign >= bytes.len() || !(bytes[exponent_sign] == ASCII_PLUS || bytes[exponent_sign]
581 == ASCII_MINUS) {
582 return false;
583 }
584 let exponent = exponent_sign + 1;
585 let exponent_end = scan_ascii_digits_exec(bytes, exponent);
586 exponent < exponent_end && exponent_end == bytes.len() && nonzero
587}
588
589fn scan_decimal_mantissa(bytes: &[u8], start: usize) -> (scanned: usize)
590 requires
591 start <= bytes@.len(),
592 ensures
593 start <= scanned <= bytes@.len(),
594 ascii_digits(bytes@, start as int, scanned as int),
595 scanned == bytes@.len() || !ascii_digit(bytes@[scanned as int]),
596{
597 let mut i = start;
598 while i < bytes.len() && ASCII_ZERO <= bytes[i] && bytes[i] <= ASCII_NINE
599 invariant
600 start <= i <= bytes@.len(),
601 ascii_digits(bytes@, start as int, i as int),
602 decreases bytes@.len() - i,
603 {
604 i += 1;
605 }
606 i
607}
608
609fn der_real_decimal_at_exec(bytes: &[u8], dot: usize) -> (ok: bool)
610 ensures
611 ok == der_real_decimal_at(bytes@, dot as int),
612{
613 if bytes.len() < 6 || bytes[0] != REAL_DECIMAL_NR3 {
614 return false;
615 }
616 let start = if bytes[1] == ASCII_MINUS {
617 2
618 } else {
619 1
620 };
621 if start >= dot || dot >= bytes.len() {
622 return false;
623 }
624 if !all_ascii_digits(bytes, start, dot) {
625 return false;
626 }
627 if bytes[start] == ASCII_ZERO || bytes[dot - 1] == ASCII_ZERO {
628 return false;
629 }
630 if dot > bytes.len() - 2 || bytes[dot] != ASCII_FULL_STOP || bytes[dot + 1] != ASCII_E {
631 return false;
632 }
633 let exponent = dot + 2;
634 if exponent <= bytes.len() - 2 && exponent + 2 == bytes.len() && bytes[exponent] == ASCII_PLUS
635 && bytes[exponent + 1] == ASCII_ZERO {
636 return true;
637 }
638 if exponent >= bytes.len() || bytes[exponent] == ASCII_PLUS {
639 return false;
640 }
641 let digits = if bytes[exponent] == ASCII_MINUS {
642 exponent + 1
643 } else {
644 exponent
645 };
646 if digits >= bytes.len() || bytes[digits] < ASCII_ONE || bytes[digits] > ASCII_NINE {
647 return false;
648 }
649 all_ascii_digits(bytes, digits, bytes.len())
650}
651
652fn der_real_decimal_wf_exec(bytes: &[u8]) -> (ok: bool)
653 ensures
654 ok == der_real_decimal_wf(bytes@),
655{
656 if bytes.len() < 2 || bytes[0] != REAL_DECIMAL_NR3 {
657 return false;
658 }
659 let start = if bytes[1] == ASCII_MINUS {
660 2
661 } else {
662 1
663 };
664 if start > bytes.len() {
665 return false;
666 }
667 let scanned = scan_decimal_mantissa(bytes, start);
668 let ok = der_real_decimal_at_exec(bytes, scanned);
669 proof {
670 assert(start as int == decimal_mantissa_start(bytes@));
671 lemma_decimal_scan_characterizes(bytes@, start as int, scanned as int);
672 }
673 ok
674}
675
676fn der_real_binary_wf_exec(bytes: &[u8]) -> (ok: bool)
677 ensures
678 ok == der_real_binary_wf(bytes@),
679{
680 if bytes.len() < 3 {
681 return false;
682 }
683 let info = bytes[0];
684 if info & 0x80u8 == 0 || info & 0x30u8 != 0 || info & 0x0cu8 != 0 {
685 return false;
686 }
687 let form = info & 0x03u8;
688 let exponent_offset = if form == 0x03u8 {
689 2usize
690 } else {
691 1usize
692 };
693 let exponent_len = if form == 0x00u8 {
694 1usize
695 } else if form == 0x01u8 {
696 2usize
697 } else if form == 0x02u8 {
698 3usize
699 } else {
700 bytes[1] as usize
701 };
702 let ghost spec_exponent_offset: int = if form == 0x03u8 {
703 2
704 } else {
705 1
706 };
707 let ghost spec_exponent_len: int = match form {
708 0x00u8 => 1,
709 0x01u8 => 2,
710 0x02u8 => 3,
711 _ => bytes@[1] as int,
712 };
713 proof {
714 assert(exponent_offset as int == spec_exponent_offset);
715 assert(exponent_len as int == spec_exponent_len);
716 }
717 if form == 0x03u8 && exponent_len < 4 {
718 return false;
719 }
720 if exponent_len == 0 || exponent_offset > bytes.len() || exponent_len > bytes.len()
721 - exponent_offset {
722 return false;
723 }
724 if exponent_len > 1 {
725 let first = bytes[exponent_offset];
726 let second = bytes[exponent_offset + 1];
727 if (first == 0x00 && second < 0x80) || (first == 0xff && second >= 0x80) {
728 proof {
729 assert(!der_real_exponent_minimal(bytes@, spec_exponent_offset, spec_exponent_len));
730 assert(!der_real_binary_wf(bytes@));
731 }
732 return false;
733 }
734 }
735 let mantissa_offset = exponent_offset + exponent_len;
736 proof {
737 assert(mantissa_offset as int == spec_exponent_offset + spec_exponent_len);
738 }
739 if mantissa_offset >= bytes.len() || bytes[mantissa_offset] == 0 {
740 proof {
741 assert(!der_real_binary_wf(bytes@));
742 }
743 return false;
744 }
745 bytes[bytes.len() - 1] & 1u8 == 1u8
746}
747
748fn has_nonzero_octet(bytes: &[u8], start: usize) -> (found: bool)
749 requires
750 start <= bytes@.len(),
751 ensures
752 found == exists|i: int| start <= i < bytes@.len() && bytes@[i] != 0u8,
753{
754 let mut i = start;
755 while i < bytes.len()
756 invariant
757 start <= i <= bytes@.len(),
758 forall|j: int| start <= j < i ==> bytes@[j] == 0u8,
759 decreases bytes@.len() - i,
760 {
761 if bytes[i] != 0 {
762 assert(exists|j: int| start <= j < bytes@.len() && bytes@[j] != 0u8);
763 return true;
764 }
765 i += 1;
766 }
767 assert(!(exists|j: int| start <= j < bytes@.len() && bytes@[j] != 0u8));
768 false
769}
770
771fn ber_real_binary_wf_exec(bytes: &[u8]) -> (ok: bool)
772 ensures
773 ok == ber_real_binary_wf(bytes@),
774{
775 if bytes.len() < 3 {
776 return false;
777 }
778 let info = bytes[0];
779 if info & 0x80u8 == 0 || info & 0x30u8 == 0x30u8 {
780 return false;
781 }
782 let form = info & 0x03u8;
783 let exponent_offset = if form == 0x03u8 {
784 2usize
785 } else {
786 1usize
787 };
788 let exponent_len = if form == 0x00u8 {
789 1usize
790 } else if form == 0x01u8 {
791 2usize
792 } else if form == 0x02u8 {
793 3usize
794 } else {
795 bytes[1] as usize
796 };
797 let ghost spec_exponent_offset: int = if form == 0x03u8 {
798 2
799 } else {
800 1
801 };
802 let ghost spec_exponent_len: int = match form {
803 0x00u8 => 1,
804 0x01u8 => 2,
805 0x02u8 => 3,
806 _ => bytes@[1] as int,
807 };
808 proof {
809 assert(exponent_offset as int == spec_exponent_offset);
810 assert(exponent_len as int == spec_exponent_len);
811 }
812
813 if form == 0x03u8 && exponent_len == 0 {
814 assert(!ber_real_binary_wf(bytes@));
815 return false;
816 }
817 if exponent_offset > bytes.len() || exponent_len > bytes.len() - exponent_offset {
818 proof {
819 if exponent_offset > bytes@.len() {
820 assert(spec_exponent_offset > bytes@.len());
821 } else if exponent_len > bytes.len() - exponent_offset {
822 assert(spec_exponent_offset + spec_exponent_len > bytes@.len());
823 }
824 assert(!ber_real_binary_wf(bytes@));
825 }
826 return false;
827 }
828 if form == 0x03u8 && exponent_len > 1 {
829 let first = bytes[exponent_offset];
830 let second = bytes[exponent_offset + 1];
831 if (first == 0x00 && second < 0x80) || (first == 0xff && second >= 0x80) {
832 proof {
833 assert(!der_real_exponent_minimal(bytes@, spec_exponent_offset, spec_exponent_len));
834 }
835 return false;
836 }
837 }
838 let mantissa_offset = exponent_offset + exponent_len;
839 proof {
840 assert(mantissa_offset as int == spec_exponent_offset + spec_exponent_len);
841 }
842 if mantissa_offset >= bytes.len() {
843 return false;
844 }
845 has_nonzero_octet(bytes, mantissa_offset)
846}
847
848pub fn der_real_bytes_wf_exec(bytes: &[u8]) -> (ok: bool)
850 ensures
851 ok == der_real_bytes_wf(bytes@),
852{
853 proof {
854 lemma_der_real_bytes_cases(bytes@);
855 }
856 if bytes.len() == 0 {
857 true
858 } else if bytes.len() == 1 {
859 matches!(
860 bytes[0],
861 REAL_PLUS_INFINITY | REAL_MINUS_INFINITY | REAL_NOT_A_NUMBER | REAL_MINUS_ZERO
862 )
863 } else if bytes[0] & 0x80u8 != 0 {
864 der_real_binary_wf_exec(bytes)
865 } else if bytes[0] == REAL_DECIMAL_NR3 {
866 der_real_decimal_wf_exec(bytes)
867 } else {
868 false
869 }
870}
871
872pub fn ber_real_bytes_wf_exec(bytes: &[u8]) -> (ok: bool)
874 ensures
875 ok == ber_real_bytes_wf(bytes@),
876{
877 proof {
878 lemma_ber_real_bytes_cases(bytes@);
879 }
880 if bytes.len() == 0 {
881 true
882 } else if bytes.len() == 1 {
883 matches!(
884 bytes[0],
885 REAL_PLUS_INFINITY | REAL_MINUS_INFINITY | REAL_NOT_A_NUMBER | REAL_MINUS_ZERO
886 )
887 } else if bytes[0] & 0x80u8 != 0 {
888 ber_real_binary_wf_exec(bytes)
889 } else {
890 ber_real_decimal_wf_exec(bytes)
891 }
892}
893
894pub fn real_bytes_wf_exec<const DER: bool>(bytes: &[u8]) -> (ok: bool)
895 ensures
896 ok == real_bytes_wf::<DER>(bytes@),
897{
898 if DER {
899 der_real_bytes_wf_exec(bytes)
900 } else {
901 ber_real_bytes_wf_exec(bytes)
902 }
903}
904
905mod derived_specs {
906 use super::*;
907
908 impl<const DER: bool> SpecParser for RealFmt<DER> {
909 type PVal = RealSpec;
910
911 open spec fn spec_parse(&self, ibuf: Seq<u8>) -> Option<(int, Self::PVal)> {
912 real_fmt::<DER>().spec_parse(ibuf)
913 }
914 }
915
916 impl<const DER: bool> Consistency for RealFmt<DER> {
917 type Val = RealSpec;
918
919 open spec fn consistent(&self, v: Self::Val) -> bool {
920 real_fmt::<DER>().consistent(v)
921 }
922 }
923
924 impl<const DER: bool> SpecSerializerDps for RealFmt<DER> {
925 type SValue = RealSpec;
926
927 open spec fn spec_serialize_dps(&self, v: Self::SValue, obuf: Seq<u8>) -> Seq<u8> {
928 real_fmt::<DER>().spec_serialize_dps(v, obuf)
929 }
930 }
931
932 impl<const DER: bool> SpecSerializer for RealFmt<DER> {
933 type SVal = RealSpec;
934
935 open spec fn spec_serialize(&self, v: Self::SVal) -> Seq<u8> {
936 real_fmt::<DER>().spec_serialize(v)
937 }
938 }
939
940 impl<const DER: bool> SpecByteLen for RealFmt<DER> {
941 type T = RealSpec;
942
943 open spec fn byte_len(&self, v: Self::T) -> nat {
944 real_fmt::<DER>().byte_len(v)
945 }
946 }
947
948}
949
950mod derived_proofs {
951 use super::*;
952
953 impl<const DER: bool> SafeParser for RealFmt<DER> {
954 proof fn lemma_parse_safe(&self, ibuf: Seq<u8>) {
955 real_fmt::<DER>().lemma_parse_safe(ibuf);
956 }
957 }
958
959 impl<const DER: bool> Productive for RealFmt<DER> {
960 open spec fn productive_inv(&self) -> bool {
961 false
962 }
963
964 proof fn lemma_productive(&self, _ibuf: Seq<u8>) {
965 }
966 }
967
968 impl<const DER: bool> SoundParser for RealFmt<DER> {
969 proof fn lemma_parse_sound_consumption(&self, ibuf: Seq<u8>) {
970 real_fmt::<DER>().lemma_parse_sound_consumption(ibuf);
971 }
972
973 proof fn lemma_parse_sound_value(&self, ibuf: Seq<u8>) {
974 real_fmt::<DER>().lemma_parse_sound_value(ibuf);
975 }
976 }
977
978 impl<const DER: bool> GoodSerializer for RealFmt<DER> {
979 proof fn lemma_serialize_len(&self, v: Self::SVal) {
980 real_fmt::<DER>().lemma_serialize_len(v);
981 }
982 }
983
984 impl<const DER: bool> SPRoundTripDps for RealFmt<DER> {
985 proof fn theorem_serialize_dps_parse_roundtrip(&self, v: Self::T, obuf: Seq<u8>) {
986 real_fmt::<DER>().theorem_serialize_dps_parse_roundtrip(v, obuf);
987 }
988 }
989
990 impl<const DER: bool> NonMalleable for RealFmt<DER> {
991 proof fn lemma_parse_non_malleable(&self, buf1: Seq<u8>, buf2: Seq<u8>) {
992 real_fmt::<DER>().lemma_parse_non_malleable(buf1, buf2);
993 }
994 }
995
996 impl<const DER: bool> EquivSerializers for RealFmt<DER> {
997 proof fn lemma_serialize_equiv_on_empty(&self, v: Self::SVal) {
998 real_fmt::<DER>().lemma_serialize_equiv_on_empty(v);
999 }
1000 }
1001
1002}
1003
1004pub struct Real<'a, const DER: bool = true> {
1006 contents: &'a [u8],
1007}
1008
1009impl<'a, const DER: bool> DeepView for Real<'a, DER> {
1010 type V = RealSpec;
1011
1012 closed spec fn deep_view(&self) -> Self::V {
1013 self.contents.deep_view()
1014 }
1015}
1016
1017impl<'a, const DER: bool> Real<'a, DER> {
1018 #[verifier::type_invariant]
1019 spec fn wf(&self) -> bool {
1020 real_bytes_wf::<DER>(self.deep_view())
1021 }
1022
1023 fn new_verified(contents: &'a [u8]) -> (value: Self)
1024 requires
1025 real_bytes_wf::<DER>(contents@),
1026 ensures
1027 value.deep_view() == contents.deep_view(),
1028 {
1029 proof {
1030 assert(contents.deep_view() == contents@);
1031 }
1032 Self { contents }
1033 }
1034
1035 pub fn from_contents(contents: &'a [u8]) -> (value: Result<Self, ParseError>)
1037 ensures
1038 value matches Ok(v) ==> v.deep_view() == contents.deep_view(),
1039 value is Ok <==> real_bytes_wf::<DER>(contents@),
1040 {
1041 if real_bytes_wf_exec::<DER>(contents) {
1042 Ok(Self::new_verified(contents))
1043 } else {
1044 Err(ParseError::non_canonical())
1045 }
1046 }
1047
1048 pub fn contents(&self) -> (contents: &'a [u8])
1049 ensures
1050 contents.deep_view() == self.deep_view(),
1051 {
1052 self.contents
1053 }
1054}
1055
1056impl<'a> Real<'a, true> {
1057 pub fn from_der_contents(contents: &'a [u8]) -> (value: Result<Self, ParseError>)
1059 ensures
1060 value matches Ok(v) ==> v.deep_view() == contents.deep_view(),
1061 value is Ok <==> der_real_bytes_wf(contents@),
1062 {
1063 Self::from_contents(contents)
1064 }
1065}
1066
1067impl<'a> Real<'a, false> {
1068 pub fn from_ber_contents(contents: &'a [u8]) -> (value: Result<Self, ParseError>)
1070 ensures
1071 value matches Ok(v) ==> v.deep_view() == contents.deep_view(),
1072 value is Ok <==> ber_real_bytes_wf(contents@),
1073 {
1074 Self::from_contents(contents)
1075 }
1076}
1077
1078impl<'a, const DER: bool> Parser<&'a [u8]> for RealFmt<DER> {
1079 type PT = Real<'a, DER>;
1080
1081 fn parse(&self, ibuf: &&'a [u8]) -> PResult<Self::PT> {
1082 let (n, contents) = Tail.parse(ibuf)?;
1083 proof {
1084 contents.deep_view_eq_view();
1085 }
1086 if real_bytes_wf_exec::<DER>(contents) {
1087 let value = Real::new_verified(contents);
1088 Ok((n, value))
1089 } else {
1090 Err(ParseError::non_canonical())
1091 }
1092 }
1093}
1094
1095impl<'a, Output: OutputBuf, const DER: bool> Serializer<Output, Real<'a, DER>> for RealFmt<DER> {
1096 fn serialize_into(&self, v: &Real<'a, DER>, obuf: &mut Output) {
1097 proof {
1098 use_type_invariant(v);
1099 }
1100 Tail.serialize_into(&v.contents, obuf);
1101 }
1102}
1103
1104impl<'a, const DER: bool> Prepare<Real<'a, DER>> for RealFmt<DER> {
1105 fn prepare(&self, v: &Real<'a, DER>) -> Result<usize, PreSerializeError> {
1106 proof {
1107 use_type_invariant(v);
1108 }
1109 Tail.prepare(&v.contents)
1110 }
1111}
1112
1113impl<'a, const DER: bool> ByteLen<Real<'a, DER>> for RealFmt<DER> {
1114 fn length(&self, v: &Real<'a, DER>) -> usize {
1115 Tail.length(&v.contents)
1116 }
1117}
1118
1119} #[cfg(test)]
1121mod tests {
1122 use super::*;
1123 use crate::asn1::ber::REAL as BER_REAL;
1124 use crate::asn1::der::REAL;
1125 use crate::core::exec::{Parser, Prepare, SerializerExt};
1126
1127 fn roundtrip(contents: &[u8]) {
1128 let mut input = vec![0x09, contents.len() as u8];
1129 input.extend_from_slice(contents);
1130 let (_, value) = REAL.parse(&&input[..]).unwrap();
1131 let mut output = vec![0; REAL.prepare(&value).unwrap()];
1132 REAL.serialize(&value, &mut output);
1133 assert_eq!(output, input);
1134 }
1135
1136 fn roundtrip_ber(contents: &[u8]) {
1137 let mut input = vec![0x09, contents.len() as u8];
1138 input.extend_from_slice(contents);
1139 let (_, value) = BER_REAL.parse(&&input[..]).unwrap();
1140 let mut output = vec![0; BER_REAL.prepare(&value).unwrap()];
1141 BER_REAL.serialize(&value, &mut output);
1142 assert_eq!(output, input);
1143 }
1144
1145 #[test]
1146 fn real_roundtrips_all_der_families() {
1147 roundtrip(&[]); roundtrip(&[REAL_MINUS_ZERO]);
1149 roundtrip(&[REAL_PLUS_INFINITY]);
1150 roundtrip(&[REAL_MINUS_INFINITY]);
1151 roundtrip(&[REAL_NOT_A_NUMBER]);
1152 roundtrip(&[0x80, 0x00, 0x01]); roundtrip(b"\x03123.E-2");
1154 roundtrip(b"\x031.E+0");
1155 }
1156
1157 #[test]
1158 fn real_rejects_noncanonical_forms() {
1159 for contents in [
1160 &b"\x031.0E+0"[..], &b"\x031.E+1"[..], &[0x80, 0x00, 0x02], &[0x83, 0x01, 0x00, 0x01], ] {
1165 let mut input = vec![0x09, contents.len() as u8];
1166 input.extend_from_slice(contents);
1167 assert!(REAL.parse(&&input[..]).is_err());
1168 }
1169 }
1170
1171 #[test]
1172 fn ber_real_roundtrips_additional_binary_and_decimal_forms() {
1173 roundtrip_ber(&[0x90, 0x00, 0x02]); roundtrip_ber(&[0x84, 0x00, 0x02]); roundtrip_ber(&[0x83, 0x01, 0x00, 0x02]); roundtrip_ber(b"\x01123"); roundtrip_ber(b"\x02-12.5"); roundtrip_ber(b"\x03 1.25E+2"); roundtrip_ber(b"\x03.125e+3"); }
1181
1182 #[test]
1183 fn ber_real_rejects_reserved_or_non_real_contents() {
1184 for contents in [
1185 &[0xb0, 0x00, 0x01][..], &[0x80, 0x00, 0x00], &b"\x010"[..], &b"\x0212"[..], &b"\x031.2E2"[..], ] {
1191 let mut input = vec![0x09, contents.len() as u8];
1192 input.extend_from_slice(contents);
1193 assert!(BER_REAL.parse(&&input[..]).is_err());
1194 }
1195 }
1196}