• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // rstest_reuse template functions have unused variables
2 #![allow(unused_variables)]
3 
4 use rand::{
5     self,
6     distributions::{self, Distribution as _},
7     rngs, Rng as _, SeedableRng as _,
8 };
9 use rstest::rstest;
10 use rstest_reuse::{apply, template};
11 use std::{collections, fmt};
12 
13 use crate::{
14     alphabet::{Alphabet, STANDARD},
15     encode::add_padding,
16     encoded_len,
17     engine::{general_purpose, naive, Config, DecodeEstimate, DecodePaddingMode, Engine},
18     tests::{assert_encode_sanity, random_alphabet, random_config},
19     DecodeError, PAD_BYTE,
20 };
21 
22 // the case::foo syntax includes the "foo" in the generated test method names
23 #[template]
24 #[rstest(engine_wrapper,
25 case::general_purpose(GeneralPurposeWrapper {}),
26 case::naive(NaiveWrapper {}),
27 )]
all_engines<E: EngineWrapper>(engine_wrapper: E)28 fn all_engines<E: EngineWrapper>(engine_wrapper: E) {}
29 
30 #[apply(all_engines)]
rfc_test_vectors_std_alphabet<E: EngineWrapper>(engine_wrapper: E)31 fn rfc_test_vectors_std_alphabet<E: EngineWrapper>(engine_wrapper: E) {
32     let data = vec![
33         ("", ""),
34         ("f", "Zg=="),
35         ("fo", "Zm8="),
36         ("foo", "Zm9v"),
37         ("foob", "Zm9vYg=="),
38         ("fooba", "Zm9vYmE="),
39         ("foobar", "Zm9vYmFy"),
40     ];
41 
42     let engine = E::standard();
43     let engine_no_padding = E::standard_unpadded();
44 
45     for (orig, encoded) in &data {
46         let encoded_without_padding = encoded.trim_end_matches('=');
47 
48         // unpadded
49         {
50             let mut encode_buf = [0_u8; 8];
51             let mut decode_buf = [0_u8; 6];
52 
53             let encode_len =
54                 engine_no_padding.internal_encode(orig.as_bytes(), &mut encode_buf[..]);
55             assert_eq!(
56                 &encoded_without_padding,
57                 &std::str::from_utf8(&encode_buf[0..encode_len]).unwrap()
58             );
59             let decode_len = engine_no_padding
60                 .decode_slice_unchecked(encoded_without_padding.as_bytes(), &mut decode_buf[..])
61                 .unwrap();
62             assert_eq!(orig.len(), decode_len);
63 
64             assert_eq!(
65                 orig,
66                 &std::str::from_utf8(&decode_buf[0..decode_len]).unwrap()
67             );
68 
69             // if there was any padding originally, the no padding engine won't decode it
70             if encoded.as_bytes().contains(&PAD_BYTE) {
71                 assert_eq!(
72                     Err(DecodeError::InvalidPadding),
73                     engine_no_padding.decode(encoded)
74                 )
75             }
76         }
77 
78         // padded
79         {
80             let mut encode_buf = [0_u8; 8];
81             let mut decode_buf = [0_u8; 6];
82 
83             let encode_len = engine.internal_encode(orig.as_bytes(), &mut encode_buf[..]);
84             assert_eq!(
85                 // doesn't have padding added yet
86                 &encoded_without_padding,
87                 &std::str::from_utf8(&encode_buf[0..encode_len]).unwrap()
88             );
89             let pad_len = add_padding(orig.len(), &mut encode_buf[encode_len..]);
90             assert_eq!(encoded.as_bytes(), &encode_buf[..encode_len + pad_len]);
91 
92             let decode_len = engine
93                 .decode_slice_unchecked(encoded.as_bytes(), &mut decode_buf[..])
94                 .unwrap();
95             assert_eq!(orig.len(), decode_len);
96 
97             assert_eq!(
98                 orig,
99                 &std::str::from_utf8(&decode_buf[0..decode_len]).unwrap()
100             );
101 
102             // if there was (canonical) padding, and we remove it, the standard engine won't decode
103             if encoded.as_bytes().contains(&PAD_BYTE) {
104                 assert_eq!(
105                     Err(DecodeError::InvalidPadding),
106                     engine.decode(encoded_without_padding)
107                 )
108             }
109         }
110     }
111 }
112 
113 #[apply(all_engines)]
roundtrip_random<E: EngineWrapper>(engine_wrapper: E)114 fn roundtrip_random<E: EngineWrapper>(engine_wrapper: E) {
115     let mut rng = seeded_rng();
116 
117     let mut orig_data = Vec::<u8>::new();
118     let mut encode_buf = Vec::<u8>::new();
119     let mut decode_buf = Vec::<u8>::new();
120 
121     let len_range = distributions::Uniform::new(1, 1_000);
122 
123     for _ in 0..10_000 {
124         let engine = E::random(&mut rng);
125 
126         orig_data.clear();
127         encode_buf.clear();
128         decode_buf.clear();
129 
130         let (orig_len, _, encoded_len) = generate_random_encoded_data(
131             &engine,
132             &mut orig_data,
133             &mut encode_buf,
134             &mut rng,
135             &len_range,
136         );
137 
138         // exactly the right size
139         decode_buf.resize(orig_len, 0);
140 
141         let dec_len = engine
142             .decode_slice_unchecked(&encode_buf[0..encoded_len], &mut decode_buf[..])
143             .unwrap();
144 
145         assert_eq!(orig_len, dec_len);
146         assert_eq!(&orig_data[..], &decode_buf[..dec_len]);
147     }
148 }
149 
150 #[apply(all_engines)]
encode_doesnt_write_extra_bytes<E: EngineWrapper>(engine_wrapper: E)151 fn encode_doesnt_write_extra_bytes<E: EngineWrapper>(engine_wrapper: E) {
152     let mut rng = seeded_rng();
153 
154     let mut orig_data = Vec::<u8>::new();
155     let mut encode_buf = Vec::<u8>::new();
156     let mut encode_buf_backup = Vec::<u8>::new();
157 
158     let input_len_range = distributions::Uniform::new(0, 1000);
159 
160     for _ in 0..10_000 {
161         let engine = E::random(&mut rng);
162         let padded = engine.config().encode_padding();
163 
164         orig_data.clear();
165         encode_buf.clear();
166         encode_buf_backup.clear();
167 
168         let orig_len = fill_rand(&mut orig_data, &mut rng, &input_len_range);
169 
170         let prefix_len = 1024;
171         // plenty of prefix and suffix
172         fill_rand_len(&mut encode_buf, &mut rng, prefix_len * 2 + orig_len * 2);
173         encode_buf_backup.extend_from_slice(&encode_buf[..]);
174 
175         let expected_encode_len_no_pad = encoded_len(orig_len, false).unwrap();
176 
177         let encoded_len_no_pad =
178             engine.internal_encode(&orig_data[..], &mut encode_buf[prefix_len..]);
179         assert_eq!(expected_encode_len_no_pad, encoded_len_no_pad);
180 
181         // no writes past what it claimed to write
182         assert_eq!(&encode_buf_backup[..prefix_len], &encode_buf[..prefix_len]);
183         assert_eq!(
184             &encode_buf_backup[(prefix_len + encoded_len_no_pad)..],
185             &encode_buf[(prefix_len + encoded_len_no_pad)..]
186         );
187 
188         let encoded_data = &encode_buf[prefix_len..(prefix_len + encoded_len_no_pad)];
189         assert_encode_sanity(
190             std::str::from_utf8(encoded_data).unwrap(),
191             // engines don't pad
192             false,
193             orig_len,
194         );
195 
196         // pad so we can decode it in case our random engine requires padding
197         let pad_len = if padded {
198             add_padding(orig_len, &mut encode_buf[prefix_len + encoded_len_no_pad..])
199         } else {
200             0
201         };
202 
203         assert_eq!(
204             orig_data,
205             engine
206                 .decode(&encode_buf[prefix_len..(prefix_len + encoded_len_no_pad + pad_len)],)
207                 .unwrap()
208         );
209     }
210 }
211 
212 #[apply(all_engines)]
encode_engine_slice_fits_into_precisely_sized_slice<E: EngineWrapper>(engine_wrapper: E)213 fn encode_engine_slice_fits_into_precisely_sized_slice<E: EngineWrapper>(engine_wrapper: E) {
214     let mut orig_data = Vec::new();
215     let mut encoded_data = Vec::new();
216     let mut decoded = Vec::new();
217 
218     let input_len_range = distributions::Uniform::new(0, 1000);
219 
220     let mut rng = rngs::SmallRng::from_entropy();
221 
222     for _ in 0..10_000 {
223         orig_data.clear();
224         encoded_data.clear();
225         decoded.clear();
226 
227         let input_len = input_len_range.sample(&mut rng);
228 
229         for _ in 0..input_len {
230             orig_data.push(rng.gen());
231         }
232 
233         let engine = E::random(&mut rng);
234 
235         let encoded_size = encoded_len(input_len, engine.config().encode_padding()).unwrap();
236 
237         encoded_data.resize(encoded_size, 0);
238 
239         assert_eq!(
240             encoded_size,
241             engine.encode_slice(&orig_data, &mut encoded_data).unwrap()
242         );
243 
244         assert_encode_sanity(
245             std::str::from_utf8(&encoded_data[0..encoded_size]).unwrap(),
246             engine.config().encode_padding(),
247             input_len,
248         );
249 
250         engine
251             .decode_vec(&encoded_data[0..encoded_size], &mut decoded)
252             .unwrap();
253         assert_eq!(orig_data, decoded);
254     }
255 }
256 
257 #[apply(all_engines)]
decode_doesnt_write_extra_bytes<E>(engine_wrapper: E) where E: EngineWrapper, <<E as EngineWrapper>::Engine as Engine>::Config: fmt::Debug,258 fn decode_doesnt_write_extra_bytes<E>(engine_wrapper: E)
259 where
260     E: EngineWrapper,
261     <<E as EngineWrapper>::Engine as Engine>::Config: fmt::Debug,
262 {
263     let mut rng = seeded_rng();
264 
265     let mut orig_data = Vec::<u8>::new();
266     let mut encode_buf = Vec::<u8>::new();
267     let mut decode_buf = Vec::<u8>::new();
268     let mut decode_buf_backup = Vec::<u8>::new();
269 
270     let len_range = distributions::Uniform::new(1, 1_000);
271 
272     for _ in 0..10_000 {
273         let engine = E::random(&mut rng);
274 
275         orig_data.clear();
276         encode_buf.clear();
277         decode_buf.clear();
278         decode_buf_backup.clear();
279 
280         let orig_len = fill_rand(&mut orig_data, &mut rng, &len_range);
281         encode_buf.resize(orig_len * 2 + 100, 0);
282 
283         let encoded_len = engine
284             .encode_slice(&orig_data[..], &mut encode_buf[..])
285             .unwrap();
286         encode_buf.truncate(encoded_len);
287 
288         // oversize decode buffer so we can easily tell if it writes anything more than
289         // just the decoded data
290         let prefix_len = 1024;
291         // plenty of prefix and suffix
292         fill_rand_len(&mut decode_buf, &mut rng, prefix_len * 2 + orig_len * 2);
293         decode_buf_backup.extend_from_slice(&decode_buf[..]);
294 
295         let dec_len = engine
296             .decode_slice_unchecked(&encode_buf, &mut decode_buf[prefix_len..])
297             .unwrap();
298 
299         assert_eq!(orig_len, dec_len);
300         assert_eq!(
301             &orig_data[..],
302             &decode_buf[prefix_len..prefix_len + dec_len]
303         );
304         assert_eq!(&decode_buf_backup[..prefix_len], &decode_buf[..prefix_len]);
305         assert_eq!(
306             &decode_buf_backup[prefix_len + dec_len..],
307             &decode_buf[prefix_len + dec_len..]
308         );
309     }
310 }
311 
312 #[apply(all_engines)]
decode_detect_invalid_last_symbol<E: EngineWrapper>(engine_wrapper: E)313 fn decode_detect_invalid_last_symbol<E: EngineWrapper>(engine_wrapper: E) {
314     // 0xFF -> "/w==", so all letters > w, 0-9, and '+', '/' should get InvalidLastSymbol
315     let engine = E::standard();
316 
317     assert_eq!(Ok(vec![0x89, 0x85]), engine.decode("iYU="));
318     assert_eq!(Ok(vec![0xFF]), engine.decode("/w=="));
319 
320     for (suffix, offset) in vec![
321         // suffix, offset of bad byte from start of suffix
322         ("/x==", 1_usize),
323         ("/z==", 1_usize),
324         ("/0==", 1_usize),
325         ("/9==", 1_usize),
326         ("/+==", 1_usize),
327         ("//==", 1_usize),
328         // trailing 01
329         ("iYV=", 2_usize),
330         // trailing 10
331         ("iYW=", 2_usize),
332         // trailing 11
333         ("iYX=", 2_usize),
334     ] {
335         for prefix_quads in 0..256 {
336             let mut encoded = "AAAA".repeat(prefix_quads);
337             encoded.push_str(suffix);
338 
339             assert_eq!(
340                 Err(DecodeError::InvalidLastSymbol(
341                     encoded.len() - 4 + offset,
342                     suffix.as_bytes()[offset],
343                 )),
344                 engine.decode(encoded.as_str())
345             );
346         }
347     }
348 }
349 
350 #[apply(all_engines)]
decode_detect_invalid_last_symbol_when_length_is_also_invalid<E: EngineWrapper>( engine_wrapper: E, )351 fn decode_detect_invalid_last_symbol_when_length_is_also_invalid<E: EngineWrapper>(
352     engine_wrapper: E,
353 ) {
354     let mut rng = seeded_rng();
355 
356     // check across enough lengths that it would likely cover any implementation's various internal
357     // small/large input division
358     for len in (0_usize..256).map(|len| len * 4 + 1) {
359         let engine = E::random_alphabet(&mut rng, &STANDARD);
360 
361         let mut input = vec![b'A'; len];
362 
363         // with a valid last char, it's InvalidLength
364         assert_eq!(Err(DecodeError::InvalidLength), engine.decode(&input));
365         // after mangling the last char, it's InvalidByte
366         input[len - 1] = b'"';
367         assert_eq!(
368             Err(DecodeError::InvalidByte(len - 1, b'"')),
369             engine.decode(&input)
370         );
371     }
372 }
373 
374 #[apply(all_engines)]
decode_detect_invalid_last_symbol_every_possible_two_symbols<E: EngineWrapper>( engine_wrapper: E, )375 fn decode_detect_invalid_last_symbol_every_possible_two_symbols<E: EngineWrapper>(
376     engine_wrapper: E,
377 ) {
378     let engine = E::standard();
379 
380     let mut base64_to_bytes = collections::HashMap::new();
381 
382     for b in 0_u8..=255 {
383         let mut b64 = vec![0_u8; 4];
384         assert_eq!(2, engine.internal_encode(&[b], &mut b64[..]));
385         let _ = add_padding(1, &mut b64[2..]);
386 
387         assert!(base64_to_bytes.insert(b64, vec![b]).is_none());
388     }
389 
390     // every possible combination of trailing symbols must either decode to 1 byte or get InvalidLastSymbol, with or without any leading chunks
391 
392     let mut prefix = Vec::new();
393     for _ in 0..256 {
394         let mut clone = prefix.clone();
395 
396         let mut symbols = [0_u8; 4];
397         for &s1 in STANDARD.symbols.iter() {
398             symbols[0] = s1;
399             for &s2 in STANDARD.symbols.iter() {
400                 symbols[1] = s2;
401                 symbols[2] = PAD_BYTE;
402                 symbols[3] = PAD_BYTE;
403 
404                 // chop off previous symbols
405                 clone.truncate(prefix.len());
406                 clone.extend_from_slice(&symbols[..]);
407                 let decoded_prefix_len = prefix.len() / 4 * 3;
408 
409                 match base64_to_bytes.get(&symbols[..]) {
410                     Some(bytes) => {
411                         let res = engine
412                             .decode(&clone)
413                             // remove prefix
414                             .map(|decoded| decoded[decoded_prefix_len..].to_vec());
415 
416                         assert_eq!(Ok(bytes.clone()), res);
417                     }
418                     None => assert_eq!(
419                         Err(DecodeError::InvalidLastSymbol(1, s2)),
420                         engine.decode(&symbols[..])
421                     ),
422                 }
423             }
424         }
425 
426         prefix.extend_from_slice(b"AAAA");
427     }
428 }
429 
430 #[apply(all_engines)]
decode_detect_invalid_last_symbol_every_possible_three_symbols<E: EngineWrapper>( engine_wrapper: E, )431 fn decode_detect_invalid_last_symbol_every_possible_three_symbols<E: EngineWrapper>(
432     engine_wrapper: E,
433 ) {
434     let engine = E::standard();
435 
436     let mut base64_to_bytes = collections::HashMap::new();
437 
438     let mut bytes = [0_u8; 2];
439     for b1 in 0_u8..=255 {
440         bytes[0] = b1;
441         for b2 in 0_u8..=255 {
442             bytes[1] = b2;
443             let mut b64 = vec![0_u8; 4];
444             assert_eq!(3, engine.internal_encode(&bytes, &mut b64[..]));
445             let _ = add_padding(2, &mut b64[3..]);
446 
447             let mut v = Vec::with_capacity(2);
448             v.extend_from_slice(&bytes[..]);
449 
450             assert!(base64_to_bytes.insert(b64, v).is_none());
451         }
452     }
453 
454     // every possible combination of symbols must either decode to 2 bytes or get InvalidLastSymbol, with or without any leading chunks
455 
456     let mut prefix = Vec::new();
457     for _ in 0..256 {
458         let mut input = prefix.clone();
459 
460         let mut symbols = [0_u8; 4];
461         for &s1 in STANDARD.symbols.iter() {
462             symbols[0] = s1;
463             for &s2 in STANDARD.symbols.iter() {
464                 symbols[1] = s2;
465                 for &s3 in STANDARD.symbols.iter() {
466                     symbols[2] = s3;
467                     symbols[3] = PAD_BYTE;
468 
469                     // chop off previous symbols
470                     input.truncate(prefix.len());
471                     input.extend_from_slice(&symbols[..]);
472                     let decoded_prefix_len = prefix.len() / 4 * 3;
473 
474                     match base64_to_bytes.get(&symbols[..]) {
475                         Some(bytes) => {
476                             let res = engine
477                                 .decode(&input)
478                                 // remove prefix
479                                 .map(|decoded| decoded[decoded_prefix_len..].to_vec());
480 
481                             assert_eq!(Ok(bytes.clone()), res);
482                         }
483                         None => assert_eq!(
484                             Err(DecodeError::InvalidLastSymbol(2, s3)),
485                             engine.decode(&symbols[..])
486                         ),
487                     }
488                 }
489             }
490         }
491         prefix.extend_from_slice(b"AAAA");
492     }
493 }
494 
495 #[apply(all_engines)]
decode_invalid_trailing_bits_ignored_when_configured<E: EngineWrapper>(engine_wrapper: E)496 fn decode_invalid_trailing_bits_ignored_when_configured<E: EngineWrapper>(engine_wrapper: E) {
497     let strict = E::standard();
498     let forgiving = E::standard_allow_trailing_bits();
499 
500     fn assert_tolerant_decode<E: Engine>(
501         engine: &E,
502         input: &mut String,
503         b64_prefix_len: usize,
504         expected_decode_bytes: Vec<u8>,
505         data: &str,
506     ) {
507         let prefixed = prefixed_data(input, b64_prefix_len, data);
508         let decoded = engine.decode(prefixed);
509         // prefix is always complete chunks
510         let decoded_prefix_len = b64_prefix_len / 4 * 3;
511         assert_eq!(
512             Ok(expected_decode_bytes),
513             decoded.map(|v| v[decoded_prefix_len..].to_vec())
514         );
515     }
516 
517     let mut prefix = String::new();
518     for _ in 0..256 {
519         let mut input = prefix.clone();
520 
521         // example from https://github.com/marshallpierce/rust-base64/issues/75
522         assert!(strict
523             .decode(prefixed_data(&mut input, prefix.len(), "/w=="))
524             .is_ok());
525         assert!(strict
526             .decode(prefixed_data(&mut input, prefix.len(), "iYU="))
527             .is_ok());
528         // trailing 01
529         assert_tolerant_decode(&forgiving, &mut input, prefix.len(), vec![255], "/x==");
530         assert_tolerant_decode(&forgiving, &mut input, prefix.len(), vec![137, 133], "iYV=");
531         // trailing 10
532         assert_tolerant_decode(&forgiving, &mut input, prefix.len(), vec![255], "/y==");
533         assert_tolerant_decode(&forgiving, &mut input, prefix.len(), vec![137, 133], "iYW=");
534         // trailing 11
535         assert_tolerant_decode(&forgiving, &mut input, prefix.len(), vec![255], "/z==");
536         assert_tolerant_decode(&forgiving, &mut input, prefix.len(), vec![137, 133], "iYX=");
537 
538         prefix.push_str("AAAA");
539     }
540 }
541 
542 #[apply(all_engines)]
decode_invalid_byte_error<E: EngineWrapper>(engine_wrapper: E)543 fn decode_invalid_byte_error<E: EngineWrapper>(engine_wrapper: E) {
544     let mut rng = seeded_rng();
545 
546     let mut orig_data = Vec::<u8>::new();
547     let mut encode_buf = Vec::<u8>::new();
548     let mut decode_buf = Vec::<u8>::new();
549 
550     let len_range = distributions::Uniform::new(1, 1_000);
551 
552     for _ in 0..10_000 {
553         let alphabet = random_alphabet(&mut rng);
554         let engine = E::random_alphabet(&mut rng, alphabet);
555 
556         orig_data.clear();
557         encode_buf.clear();
558         decode_buf.clear();
559 
560         let (orig_len, encoded_len_just_data, encoded_len_with_padding) =
561             generate_random_encoded_data(
562                 &engine,
563                 &mut orig_data,
564                 &mut encode_buf,
565                 &mut rng,
566                 &len_range,
567             );
568 
569         // exactly the right size
570         decode_buf.resize(orig_len, 0);
571 
572         // replace one encoded byte with an invalid byte
573         let invalid_byte: u8 = loop {
574             let byte: u8 = rng.gen();
575 
576             if alphabet.symbols.contains(&byte) {
577                 continue;
578             } else {
579                 break byte;
580             }
581         };
582 
583         let invalid_range = distributions::Uniform::new(0, orig_len);
584         let invalid_index = invalid_range.sample(&mut rng);
585         encode_buf[invalid_index] = invalid_byte;
586 
587         assert_eq!(
588             Err(DecodeError::InvalidByte(invalid_index, invalid_byte)),
589             engine.decode_slice_unchecked(
590                 &encode_buf[0..encoded_len_with_padding],
591                 &mut decode_buf[..],
592             )
593         );
594     }
595 }
596 
597 /// Any amount of padding anywhere before the final non padding character = invalid byte at first
598 /// pad byte.
599 /// From this, we know padding must extend to the end of the input.
600 #[apply(all_engines)]
decode_padding_before_final_non_padding_char_error_invalid_byte<E: EngineWrapper>( engine_wrapper: E, )601 fn decode_padding_before_final_non_padding_char_error_invalid_byte<E: EngineWrapper>(
602     engine_wrapper: E,
603 ) {
604     let mut rng = seeded_rng();
605 
606     // the different amounts of proper padding, w/ offset from end for the last non-padding char
607     let suffixes = vec![("/w==", 2), ("iYu=", 1), ("zzzz", 0)];
608 
609     let prefix_quads_range = distributions::Uniform::from(0..=256);
610 
611     for mode in all_pad_modes() {
612         // we don't encode so we don't care about encode padding
613         let engine = E::standard_with_pad_mode(true, mode);
614 
615         for _ in 0..100_000 {
616             for (suffix, offset) in suffixes.iter() {
617                 let mut s = "ABCD".repeat(prefix_quads_range.sample(&mut rng));
618                 s.push_str(suffix);
619                 let mut encoded = s.into_bytes();
620 
621                 // calculate a range to write padding into that leaves at least one non padding char
622                 let last_non_padding_offset = encoded.len() - 1 - offset;
623 
624                 // don't include last non padding char as it must stay not padding
625                 let padding_end = rng.gen_range(0..last_non_padding_offset);
626 
627                 // don't use more than 100 bytes of padding, but also use shorter lengths when
628                 // padding_end is near the start of the encoded data to avoid biasing to padding
629                 // the entire prefix on short lengths
630                 let padding_len = rng.gen_range(1..=usize::min(100, padding_end + 1));
631                 let padding_start = padding_end.saturating_sub(padding_len);
632 
633                 encoded[padding_start..=padding_end].fill(PAD_BYTE);
634 
635                 assert_eq!(
636                     Err(DecodeError::InvalidByte(padding_start, PAD_BYTE)),
637                     engine.decode(&encoded),
638                 );
639             }
640         }
641     }
642 }
643 
644 /// Any amount of padding before final chunk that crosses over into final chunk with 1-4 bytes =
645 /// invalid byte at first pad byte (except for 1 byte suffix = invalid length).
646 /// From this we know the padding must start in the final chunk.
647 #[apply(all_engines)]
decode_padding_starts_before_final_chunk_error_invalid_byte<E: EngineWrapper>( engine_wrapper: E, )648 fn decode_padding_starts_before_final_chunk_error_invalid_byte<E: EngineWrapper>(
649     engine_wrapper: E,
650 ) {
651     let mut rng = seeded_rng();
652 
653     // must have at least one prefix quad
654     let prefix_quads_range = distributions::Uniform::from(1..256);
655     // including 1 just to make sure that it really does produce invalid length
656     let suffix_pad_len_range = distributions::Uniform::from(1..=4);
657     for mode in all_pad_modes() {
658         // we don't encode so we don't care about encode padding
659         let engine = E::standard_with_pad_mode(true, mode);
660         for _ in 0..100_000 {
661             let suffix_len = suffix_pad_len_range.sample(&mut rng);
662             let mut encoded = "ABCD"
663                 .repeat(prefix_quads_range.sample(&mut rng))
664                 .into_bytes();
665             encoded.resize(encoded.len() + suffix_len, PAD_BYTE);
666 
667             // amount of padding must be long enough to extend back from suffix into previous
668             // quads
669             let padding_len = rng.gen_range(suffix_len + 1..encoded.len());
670             // no non-padding after padding in this test, so padding goes to the end
671             let padding_start = encoded.len() - padding_len;
672             encoded[padding_start..].fill(PAD_BYTE);
673 
674             if suffix_len == 1 {
675                 assert_eq!(Err(DecodeError::InvalidLength), engine.decode(&encoded),);
676             } else {
677                 assert_eq!(
678                     Err(DecodeError::InvalidByte(padding_start, PAD_BYTE)),
679                     engine.decode(&encoded),
680                 );
681             }
682         }
683     }
684 }
685 
686 /// 0-1 bytes of data before any amount of padding in final chunk = invalid byte, since padding
687 /// is not valid data (consistent with error for pad bytes in earlier chunks).
688 /// From this we know there must be 2-3 bytes of data before padding
689 #[apply(all_engines)]
decode_too_little_data_before_padding_error_invalid_byte<E: EngineWrapper>(engine_wrapper: E)690 fn decode_too_little_data_before_padding_error_invalid_byte<E: EngineWrapper>(engine_wrapper: E) {
691     let mut rng = seeded_rng();
692 
693     // want to test no prefix quad case, so start at 0
694     let prefix_quads_range = distributions::Uniform::from(0_usize..256);
695     let suffix_data_len_range = distributions::Uniform::from(0_usize..=1);
696     for mode in all_pad_modes() {
697         // we don't encode so we don't care about encode padding
698         let engine = E::standard_with_pad_mode(true, mode);
699         for _ in 0..100_000 {
700             let suffix_data_len = suffix_data_len_range.sample(&mut rng);
701             let prefix_quad_len = prefix_quads_range.sample(&mut rng);
702 
703             // ensure there is a suffix quad
704             let min_padding = usize::from(suffix_data_len == 0);
705 
706             // for all possible padding lengths
707             for padding_len in min_padding..=(4 - suffix_data_len) {
708                 let mut encoded = "ABCD".repeat(prefix_quad_len).into_bytes();
709                 encoded.resize(encoded.len() + suffix_data_len, b'A');
710                 encoded.resize(encoded.len() + padding_len, PAD_BYTE);
711 
712                 if suffix_data_len + padding_len == 1 {
713                     assert_eq!(Err(DecodeError::InvalidLength), engine.decode(&encoded),);
714                 } else {
715                     assert_eq!(
716                         Err(DecodeError::InvalidByte(
717                             prefix_quad_len * 4 + suffix_data_len,
718                             PAD_BYTE,
719                         )),
720                         engine.decode(&encoded),
721                         "suffix data len {} pad len {}",
722                         suffix_data_len,
723                         padding_len
724                     );
725                 }
726             }
727         }
728     }
729 }
730 
731 // https://eprint.iacr.org/2022/361.pdf table 2, test 1
732 #[apply(all_engines)]
decode_malleability_test_case_3_byte_suffix_valid<E: EngineWrapper>(engine_wrapper: E)733 fn decode_malleability_test_case_3_byte_suffix_valid<E: EngineWrapper>(engine_wrapper: E) {
734     assert_eq!(
735         b"Hello".as_slice(),
736         &E::standard().decode("SGVsbG8=").unwrap()
737     );
738 }
739 
740 // https://eprint.iacr.org/2022/361.pdf table 2, test 2
741 #[apply(all_engines)]
decode_malleability_test_case_3_byte_suffix_invalid_trailing_symbol<E: EngineWrapper>( engine_wrapper: E, )742 fn decode_malleability_test_case_3_byte_suffix_invalid_trailing_symbol<E: EngineWrapper>(
743     engine_wrapper: E,
744 ) {
745     assert_eq!(
746         DecodeError::InvalidLastSymbol(6, 0x39),
747         E::standard().decode("SGVsbG9=").unwrap_err()
748     );
749 }
750 
751 // https://eprint.iacr.org/2022/361.pdf table 2, test 3
752 #[apply(all_engines)]
decode_malleability_test_case_3_byte_suffix_no_padding<E: EngineWrapper>(engine_wrapper: E)753 fn decode_malleability_test_case_3_byte_suffix_no_padding<E: EngineWrapper>(engine_wrapper: E) {
754     assert_eq!(
755         DecodeError::InvalidPadding,
756         E::standard().decode("SGVsbG9").unwrap_err()
757     );
758 }
759 
760 // https://eprint.iacr.org/2022/361.pdf table 2, test 4
761 #[apply(all_engines)]
decode_malleability_test_case_2_byte_suffix_valid_two_padding_symbols<E: EngineWrapper>( engine_wrapper: E, )762 fn decode_malleability_test_case_2_byte_suffix_valid_two_padding_symbols<E: EngineWrapper>(
763     engine_wrapper: E,
764 ) {
765     assert_eq!(
766         b"Hell".as_slice(),
767         &E::standard().decode("SGVsbA==").unwrap()
768     );
769 }
770 
771 // https://eprint.iacr.org/2022/361.pdf table 2, test 5
772 #[apply(all_engines)]
decode_malleability_test_case_2_byte_suffix_short_padding<E: EngineWrapper>(engine_wrapper: E)773 fn decode_malleability_test_case_2_byte_suffix_short_padding<E: EngineWrapper>(engine_wrapper: E) {
774     assert_eq!(
775         DecodeError::InvalidPadding,
776         E::standard().decode("SGVsbA=").unwrap_err()
777     );
778 }
779 
780 // https://eprint.iacr.org/2022/361.pdf table 2, test 6
781 #[apply(all_engines)]
decode_malleability_test_case_2_byte_suffix_no_padding<E: EngineWrapper>(engine_wrapper: E)782 fn decode_malleability_test_case_2_byte_suffix_no_padding<E: EngineWrapper>(engine_wrapper: E) {
783     assert_eq!(
784         DecodeError::InvalidPadding,
785         E::standard().decode("SGVsbA").unwrap_err()
786     );
787 }
788 
789 // https://eprint.iacr.org/2022/361.pdf table 2, test 7
790 #[apply(all_engines)]
decode_malleability_test_case_2_byte_suffix_too_much_padding<E: EngineWrapper>( engine_wrapper: E, )791 fn decode_malleability_test_case_2_byte_suffix_too_much_padding<E: EngineWrapper>(
792     engine_wrapper: E,
793 ) {
794     assert_eq!(
795         DecodeError::InvalidByte(6, PAD_BYTE),
796         E::standard().decode("SGVsbA====").unwrap_err()
797     );
798 }
799 
800 /// Requires canonical padding -> accepts 2 + 2, 3 + 1, 4 + 0 final quad configurations
801 #[apply(all_engines)]
decode_pad_mode_requires_canonical_accepts_canonical<E: EngineWrapper>(engine_wrapper: E)802 fn decode_pad_mode_requires_canonical_accepts_canonical<E: EngineWrapper>(engine_wrapper: E) {
803     assert_all_suffixes_ok(
804         E::standard_with_pad_mode(true, DecodePaddingMode::RequireCanonical),
805         vec!["/w==", "iYU=", "AAAA"],
806     );
807 }
808 
809 /// Requires canonical padding -> rejects 2 + 0-1, 3 + 0 final chunk configurations
810 #[apply(all_engines)]
decode_pad_mode_requires_canonical_rejects_non_canonical<E: EngineWrapper>(engine_wrapper: E)811 fn decode_pad_mode_requires_canonical_rejects_non_canonical<E: EngineWrapper>(engine_wrapper: E) {
812     let engine = E::standard_with_pad_mode(true, DecodePaddingMode::RequireCanonical);
813 
814     let suffixes = vec!["/w", "/w=", "iYU"];
815     for num_prefix_quads in 0..256 {
816         for &suffix in suffixes.iter() {
817             let mut encoded = "AAAA".repeat(num_prefix_quads);
818             encoded.push_str(suffix);
819 
820             let res = engine.decode(&encoded);
821 
822             assert_eq!(Err(DecodeError::InvalidPadding), res);
823         }
824     }
825 }
826 
827 /// Requires no padding -> accepts 2 + 0, 3 + 0, 4 + 0 final chunk configuration
828 #[apply(all_engines)]
decode_pad_mode_requires_no_padding_accepts_no_padding<E: EngineWrapper>(engine_wrapper: E)829 fn decode_pad_mode_requires_no_padding_accepts_no_padding<E: EngineWrapper>(engine_wrapper: E) {
830     assert_all_suffixes_ok(
831         E::standard_with_pad_mode(true, DecodePaddingMode::RequireNone),
832         vec!["/w", "iYU", "AAAA"],
833     );
834 }
835 
836 /// Requires no padding -> rejects 2 + 1-2, 3 + 1 final chunk configuration
837 #[apply(all_engines)]
decode_pad_mode_requires_no_padding_rejects_any_padding<E: EngineWrapper>(engine_wrapper: E)838 fn decode_pad_mode_requires_no_padding_rejects_any_padding<E: EngineWrapper>(engine_wrapper: E) {
839     let engine = E::standard_with_pad_mode(true, DecodePaddingMode::RequireNone);
840 
841     let suffixes = vec!["/w=", "/w==", "iYU="];
842     for num_prefix_quads in 0..256 {
843         for &suffix in suffixes.iter() {
844             let mut encoded = "AAAA".repeat(num_prefix_quads);
845             encoded.push_str(suffix);
846 
847             let res = engine.decode(&encoded);
848 
849             assert_eq!(Err(DecodeError::InvalidPadding), res);
850         }
851     }
852 }
853 
854 /// Indifferent padding accepts 2 + 0-2, 3 + 0-1, 4 + 0 final chunk configuration
855 #[apply(all_engines)]
decode_pad_mode_indifferent_padding_accepts_anything<E: EngineWrapper>(engine_wrapper: E)856 fn decode_pad_mode_indifferent_padding_accepts_anything<E: EngineWrapper>(engine_wrapper: E) {
857     assert_all_suffixes_ok(
858         E::standard_with_pad_mode(true, DecodePaddingMode::Indifferent),
859         vec!["/w", "/w=", "/w==", "iYU", "iYU=", "AAAA"],
860     );
861 }
862 
863 //this is a MAY in the rfc: https://tools.ietf.org/html/rfc4648#section-3.3
864 #[apply(all_engines)]
decode_pad_byte_in_penultimate_quad_error<E: EngineWrapper>(engine_wrapper: E)865 fn decode_pad_byte_in_penultimate_quad_error<E: EngineWrapper>(engine_wrapper: E) {
866     for mode in all_pad_modes() {
867         // we don't encode so we don't care about encode padding
868         let engine = E::standard_with_pad_mode(true, mode);
869 
870         for num_prefix_quads in 0..256 {
871             // leave room for at least one pad byte in penultimate quad
872             for num_valid_bytes_penultimate_quad in 0..4 {
873                 // can't have 1 or it would be invalid length
874                 for num_pad_bytes_in_final_quad in 2..=4 {
875                     let mut s: String = "ABCD".repeat(num_prefix_quads);
876 
877                     // varying amounts of padding in the penultimate quad
878                     for _ in 0..num_valid_bytes_penultimate_quad {
879                         s.push('A');
880                     }
881                     // finish penultimate quad with padding
882                     for _ in num_valid_bytes_penultimate_quad..4 {
883                         s.push('=');
884                     }
885                     // and more padding in the final quad
886                     for _ in 0..num_pad_bytes_in_final_quad {
887                         s.push('=');
888                     }
889 
890                     // padding should be an invalid byte before the final quad.
891                     // Could argue that the *next* padding byte (in the next quad) is technically the first
892                     // erroneous one, but reporting that accurately is more complex and probably nobody cares
893                     assert_eq!(
894                         DecodeError::InvalidByte(
895                             num_prefix_quads * 4 + num_valid_bytes_penultimate_quad,
896                             b'=',
897                         ),
898                         engine.decode(&s).unwrap_err()
899                     );
900                 }
901             }
902         }
903     }
904 }
905 
906 #[apply(all_engines)]
decode_bytes_after_padding_in_final_quad_error<E: EngineWrapper>(engine_wrapper: E)907 fn decode_bytes_after_padding_in_final_quad_error<E: EngineWrapper>(engine_wrapper: E) {
908     for mode in all_pad_modes() {
909         // we don't encode so we don't care about encode padding
910         let engine = E::standard_with_pad_mode(true, mode);
911 
912         for num_prefix_quads in 0..256 {
913             // leave at least one byte in the quad for padding
914             for bytes_after_padding in 1..4 {
915                 let mut s: String = "ABCD".repeat(num_prefix_quads);
916 
917                 // every invalid padding position with a 3-byte final quad: 1 to 3 bytes after padding
918                 for _ in 0..(3 - bytes_after_padding) {
919                     s.push('A');
920                 }
921                 s.push('=');
922                 for _ in 0..bytes_after_padding {
923                     s.push('A');
924                 }
925 
926                 // First (and only) padding byte is invalid.
927                 assert_eq!(
928                     DecodeError::InvalidByte(
929                         num_prefix_quads * 4 + (3 - bytes_after_padding),
930                         b'='
931                     ),
932                     engine.decode(&s).unwrap_err()
933                 );
934             }
935         }
936     }
937 }
938 
939 #[apply(all_engines)]
decode_absurd_pad_error<E: EngineWrapper>(engine_wrapper: E)940 fn decode_absurd_pad_error<E: EngineWrapper>(engine_wrapper: E) {
941     for mode in all_pad_modes() {
942         // we don't encode so we don't care about encode padding
943         let engine = E::standard_with_pad_mode(true, mode);
944 
945         for num_prefix_quads in 0..256 {
946             let mut s: String = "ABCD".repeat(num_prefix_quads);
947             s.push_str("==Y=Wx===pY=2U=====");
948 
949             // first padding byte
950             assert_eq!(
951                 DecodeError::InvalidByte(num_prefix_quads * 4, b'='),
952                 engine.decode(&s).unwrap_err()
953             );
954         }
955     }
956 }
957 
958 #[apply(all_engines)]
decode_too_much_padding_returns_error<E: EngineWrapper>(engine_wrapper: E)959 fn decode_too_much_padding_returns_error<E: EngineWrapper>(engine_wrapper: E) {
960     for mode in all_pad_modes() {
961         // we don't encode so we don't care about encode padding
962         let engine = E::standard_with_pad_mode(true, mode);
963 
964         for num_prefix_quads in 0..256 {
965             // add enough padding to ensure that we'll hit all decode stages at the different lengths
966             for pad_bytes in 1..=64 {
967                 let mut s: String = "ABCD".repeat(num_prefix_quads);
968                 let padding: String = "=".repeat(pad_bytes);
969                 s.push_str(&padding);
970 
971                 if pad_bytes % 4 == 1 {
972                     assert_eq!(DecodeError::InvalidLength, engine.decode(&s).unwrap_err());
973                 } else {
974                     assert_eq!(
975                         DecodeError::InvalidByte(num_prefix_quads * 4, b'='),
976                         engine.decode(&s).unwrap_err()
977                     );
978                 }
979             }
980         }
981     }
982 }
983 
984 #[apply(all_engines)]
decode_padding_followed_by_non_padding_returns_error<E: EngineWrapper>(engine_wrapper: E)985 fn decode_padding_followed_by_non_padding_returns_error<E: EngineWrapper>(engine_wrapper: E) {
986     for mode in all_pad_modes() {
987         // we don't encode so we don't care about encode padding
988         let engine = E::standard_with_pad_mode(true, mode);
989 
990         for num_prefix_quads in 0..256 {
991             for pad_bytes in 0..=32 {
992                 let mut s: String = "ABCD".repeat(num_prefix_quads);
993                 let padding: String = "=".repeat(pad_bytes);
994                 s.push_str(&padding);
995                 s.push('E');
996 
997                 if pad_bytes % 4 == 0 {
998                     assert_eq!(DecodeError::InvalidLength, engine.decode(&s).unwrap_err());
999                 } else {
1000                     assert_eq!(
1001                         DecodeError::InvalidByte(num_prefix_quads * 4, b'='),
1002                         engine.decode(&s).unwrap_err()
1003                     );
1004                 }
1005             }
1006         }
1007     }
1008 }
1009 
1010 #[apply(all_engines)]
decode_one_char_in_final_quad_with_padding_error<E: EngineWrapper>(engine_wrapper: E)1011 fn decode_one_char_in_final_quad_with_padding_error<E: EngineWrapper>(engine_wrapper: E) {
1012     for mode in all_pad_modes() {
1013         // we don't encode so we don't care about encode padding
1014         let engine = E::standard_with_pad_mode(true, mode);
1015 
1016         for num_prefix_quads in 0..256 {
1017             let mut s: String = "ABCD".repeat(num_prefix_quads);
1018             s.push_str("E=");
1019 
1020             assert_eq!(
1021                 DecodeError::InvalidByte(num_prefix_quads * 4 + 1, b'='),
1022                 engine.decode(&s).unwrap_err()
1023             );
1024 
1025             // more padding doesn't change the error
1026             s.push('=');
1027             assert_eq!(
1028                 DecodeError::InvalidByte(num_prefix_quads * 4 + 1, b'='),
1029                 engine.decode(&s).unwrap_err()
1030             );
1031 
1032             s.push('=');
1033             assert_eq!(
1034                 DecodeError::InvalidByte(num_prefix_quads * 4 + 1, b'='),
1035                 engine.decode(&s).unwrap_err()
1036             );
1037         }
1038     }
1039 }
1040 
1041 #[apply(all_engines)]
decode_too_few_symbols_in_final_quad_error<E: EngineWrapper>(engine_wrapper: E)1042 fn decode_too_few_symbols_in_final_quad_error<E: EngineWrapper>(engine_wrapper: E) {
1043     for mode in all_pad_modes() {
1044         // we don't encode so we don't care about encode padding
1045         let engine = E::standard_with_pad_mode(true, mode);
1046 
1047         for num_prefix_quads in 0..256 {
1048             // <2 is invalid
1049             for final_quad_symbols in 0..2 {
1050                 for padding_symbols in 0..=(4 - final_quad_symbols) {
1051                     let mut s: String = "ABCD".repeat(num_prefix_quads);
1052 
1053                     for _ in 0..final_quad_symbols {
1054                         s.push('A');
1055                     }
1056                     for _ in 0..padding_symbols {
1057                         s.push('=');
1058                     }
1059 
1060                     match final_quad_symbols + padding_symbols {
1061                         0 => continue,
1062                         1 => {
1063                             assert_eq!(DecodeError::InvalidLength, engine.decode(&s).unwrap_err());
1064                         }
1065                         _ => {
1066                             // error reported at first padding byte
1067                             assert_eq!(
1068                                 DecodeError::InvalidByte(
1069                                     num_prefix_quads * 4 + final_quad_symbols,
1070                                     b'=',
1071                                 ),
1072                                 engine.decode(&s).unwrap_err()
1073                             );
1074                         }
1075                     }
1076                 }
1077             }
1078         }
1079     }
1080 }
1081 
1082 #[apply(all_engines)]
decode_invalid_trailing_bytes<E: EngineWrapper>(engine_wrapper: E)1083 fn decode_invalid_trailing_bytes<E: EngineWrapper>(engine_wrapper: E) {
1084     for mode in all_pad_modes() {
1085         // we don't encode so we don't care about encode padding
1086         let engine = E::standard_with_pad_mode(true, mode);
1087 
1088         for num_prefix_quads in 0..256 {
1089             let mut s: String = "ABCD".repeat(num_prefix_quads);
1090             s.push_str("Cg==\n");
1091 
1092             // The case of trailing newlines is common enough to warrant a test for a good error
1093             // message.
1094             assert_eq!(
1095                 Err(DecodeError::InvalidByte(num_prefix_quads * 4 + 4, b'\n')),
1096                 engine.decode(&s)
1097             );
1098 
1099             // extra padding, however, is still InvalidLength
1100             let s = s.replace('\n', "=");
1101             assert_eq!(Err(DecodeError::InvalidLength), engine.decode(s));
1102         }
1103     }
1104 }
1105 
1106 #[apply(all_engines)]
decode_wrong_length_error<E: EngineWrapper>(engine_wrapper: E)1107 fn decode_wrong_length_error<E: EngineWrapper>(engine_wrapper: E) {
1108     let engine = E::standard_with_pad_mode(true, DecodePaddingMode::Indifferent);
1109 
1110     for num_prefix_quads in 0..256 {
1111         // at least one token, otherwise it wouldn't be a final quad
1112         for num_tokens_final_quad in 1..=4 {
1113             for num_padding in 0..=(4 - num_tokens_final_quad) {
1114                 let mut s: String = "IIII".repeat(num_prefix_quads);
1115                 for _ in 0..num_tokens_final_quad {
1116                     s.push('g');
1117                 }
1118                 for _ in 0..num_padding {
1119                     s.push('=');
1120                 }
1121 
1122                 let res = engine.decode(&s);
1123                 if num_tokens_final_quad >= 2 {
1124                     assert!(res.is_ok());
1125                 } else if num_tokens_final_quad == 1 && num_padding > 0 {
1126                     // = is invalid if it's too early
1127                     assert_eq!(
1128                         Err(DecodeError::InvalidByte(
1129                             num_prefix_quads * 4 + num_tokens_final_quad,
1130                             61
1131                         )),
1132                         res
1133                     );
1134                 } else if num_padding > 2 {
1135                     assert_eq!(Err(DecodeError::InvalidPadding), res);
1136                 } else {
1137                     assert_eq!(Err(DecodeError::InvalidLength), res);
1138                 }
1139             }
1140         }
1141     }
1142 }
1143 
1144 #[apply(all_engines)]
decode_into_slice_fits_in_precisely_sized_slice<E: EngineWrapper>(engine_wrapper: E)1145 fn decode_into_slice_fits_in_precisely_sized_slice<E: EngineWrapper>(engine_wrapper: E) {
1146     let mut orig_data = Vec::new();
1147     let mut encoded_data = String::new();
1148     let mut decode_buf = Vec::new();
1149 
1150     let input_len_range = distributions::Uniform::new(0, 1000);
1151     let mut rng = rngs::SmallRng::from_entropy();
1152 
1153     for _ in 0..10_000 {
1154         orig_data.clear();
1155         encoded_data.clear();
1156         decode_buf.clear();
1157 
1158         let input_len = input_len_range.sample(&mut rng);
1159 
1160         for _ in 0..input_len {
1161             orig_data.push(rng.gen());
1162         }
1163 
1164         let engine = E::random(&mut rng);
1165         engine.encode_string(&orig_data, &mut encoded_data);
1166         assert_encode_sanity(&encoded_data, engine.config().encode_padding(), input_len);
1167 
1168         decode_buf.resize(input_len, 0);
1169 
1170         // decode into the non-empty buf
1171         let decode_bytes_written = engine
1172             .decode_slice_unchecked(encoded_data.as_bytes(), &mut decode_buf[..])
1173             .unwrap();
1174 
1175         assert_eq!(orig_data.len(), decode_bytes_written);
1176         assert_eq!(orig_data, decode_buf);
1177     }
1178 }
1179 
1180 #[apply(all_engines)]
decode_length_estimate_delta<E: EngineWrapper>(engine_wrapper: E)1181 fn decode_length_estimate_delta<E: EngineWrapper>(engine_wrapper: E) {
1182     for engine in [E::standard(), E::standard_unpadded()] {
1183         for &padding in &[true, false] {
1184             for orig_len in 0..1000 {
1185                 let encoded_len = encoded_len(orig_len, padding).unwrap();
1186 
1187                 let decoded_estimate = engine
1188                     .internal_decoded_len_estimate(encoded_len)
1189                     .decoded_len_estimate();
1190                 assert!(decoded_estimate >= orig_len);
1191                 assert!(
1192                     decoded_estimate - orig_len < 3,
1193                     "estimate: {}, encoded: {}, orig: {}",
1194                     decoded_estimate,
1195                     encoded_len,
1196                     orig_len
1197                 );
1198             }
1199         }
1200     }
1201 }
1202 
1203 /// Returns a tuple of the original data length, the encoded data length (just data), and the length including padding.
1204 ///
1205 /// Vecs provided should be empty.
generate_random_encoded_data<E: Engine, R: rand::Rng, D: distributions::Distribution<usize>>( engine: &E, orig_data: &mut Vec<u8>, encode_buf: &mut Vec<u8>, rng: &mut R, length_distribution: &D, ) -> (usize, usize, usize)1206 fn generate_random_encoded_data<E: Engine, R: rand::Rng, D: distributions::Distribution<usize>>(
1207     engine: &E,
1208     orig_data: &mut Vec<u8>,
1209     encode_buf: &mut Vec<u8>,
1210     rng: &mut R,
1211     length_distribution: &D,
1212 ) -> (usize, usize, usize) {
1213     let padding: bool = engine.config().encode_padding();
1214 
1215     let orig_len = fill_rand(orig_data, rng, length_distribution);
1216     let expected_encoded_len = encoded_len(orig_len, padding).unwrap();
1217     encode_buf.resize(expected_encoded_len, 0);
1218 
1219     let base_encoded_len = engine.internal_encode(&orig_data[..], &mut encode_buf[..]);
1220 
1221     let enc_len_with_padding = if padding {
1222         base_encoded_len + add_padding(orig_len, &mut encode_buf[base_encoded_len..])
1223     } else {
1224         base_encoded_len
1225     };
1226 
1227     assert_eq!(expected_encoded_len, enc_len_with_padding);
1228 
1229     (orig_len, base_encoded_len, enc_len_with_padding)
1230 }
1231 
1232 // fill to a random length
fill_rand<R: rand::Rng, D: distributions::Distribution<usize>>( vec: &mut Vec<u8>, rng: &mut R, length_distribution: &D, ) -> usize1233 fn fill_rand<R: rand::Rng, D: distributions::Distribution<usize>>(
1234     vec: &mut Vec<u8>,
1235     rng: &mut R,
1236     length_distribution: &D,
1237 ) -> usize {
1238     let len = length_distribution.sample(rng);
1239     for _ in 0..len {
1240         vec.push(rng.gen());
1241     }
1242 
1243     len
1244 }
1245 
fill_rand_len<R: rand::Rng>(vec: &mut Vec<u8>, rng: &mut R, len: usize)1246 fn fill_rand_len<R: rand::Rng>(vec: &mut Vec<u8>, rng: &mut R, len: usize) {
1247     for _ in 0..len {
1248         vec.push(rng.gen());
1249     }
1250 }
1251 
prefixed_data<'i, 'd>( input_with_prefix: &'i mut String, prefix_len: usize, data: &'d str, ) -> &'i str1252 fn prefixed_data<'i, 'd>(
1253     input_with_prefix: &'i mut String,
1254     prefix_len: usize,
1255     data: &'d str,
1256 ) -> &'i str {
1257     input_with_prefix.truncate(prefix_len);
1258     input_with_prefix.push_str(data);
1259     input_with_prefix.as_str()
1260 }
1261 
1262 /// A wrapper to make using engines in rstest fixtures easier.
1263 /// The functions don't need to be instance methods, but rstest does seem
1264 /// to want an instance, so instances are passed to test functions and then ignored.
1265 trait EngineWrapper {
1266     type Engine: Engine;
1267 
1268     /// Return an engine configured for RFC standard base64
standard() -> Self::Engine1269     fn standard() -> Self::Engine;
1270 
1271     /// Return an engine configured for RFC standard base64, except with no padding appended on
1272     /// encode, and required no padding on decode.
standard_unpadded() -> Self::Engine1273     fn standard_unpadded() -> Self::Engine;
1274 
1275     /// Return an engine configured for RFC standard alphabet with the provided encode and decode
1276     /// pad settings
standard_with_pad_mode(encode_pad: bool, decode_pad_mode: DecodePaddingMode) -> Self::Engine1277     fn standard_with_pad_mode(encode_pad: bool, decode_pad_mode: DecodePaddingMode)
1278         -> Self::Engine;
1279 
1280     /// Return an engine configured for RFC standard base64 that allows invalid trailing bits
standard_allow_trailing_bits() -> Self::Engine1281     fn standard_allow_trailing_bits() -> Self::Engine;
1282 
1283     /// Return an engine configured with a randomized alphabet and config
random<R: rand::Rng>(rng: &mut R) -> Self::Engine1284     fn random<R: rand::Rng>(rng: &mut R) -> Self::Engine;
1285 
1286     /// Return an engine configured with the specified alphabet and randomized config
random_alphabet<R: rand::Rng>(rng: &mut R, alphabet: &Alphabet) -> Self::Engine1287     fn random_alphabet<R: rand::Rng>(rng: &mut R, alphabet: &Alphabet) -> Self::Engine;
1288 }
1289 
1290 struct GeneralPurposeWrapper {}
1291 
1292 impl EngineWrapper for GeneralPurposeWrapper {
1293     type Engine = general_purpose::GeneralPurpose;
1294 
standard() -> Self::Engine1295     fn standard() -> Self::Engine {
1296         general_purpose::GeneralPurpose::new(&STANDARD, general_purpose::PAD)
1297     }
1298 
standard_unpadded() -> Self::Engine1299     fn standard_unpadded() -> Self::Engine {
1300         general_purpose::GeneralPurpose::new(&STANDARD, general_purpose::NO_PAD)
1301     }
1302 
standard_with_pad_mode( encode_pad: bool, decode_pad_mode: DecodePaddingMode, ) -> Self::Engine1303     fn standard_with_pad_mode(
1304         encode_pad: bool,
1305         decode_pad_mode: DecodePaddingMode,
1306     ) -> Self::Engine {
1307         general_purpose::GeneralPurpose::new(
1308             &STANDARD,
1309             general_purpose::GeneralPurposeConfig::new()
1310                 .with_encode_padding(encode_pad)
1311                 .with_decode_padding_mode(decode_pad_mode),
1312         )
1313     }
1314 
standard_allow_trailing_bits() -> Self::Engine1315     fn standard_allow_trailing_bits() -> Self::Engine {
1316         general_purpose::GeneralPurpose::new(
1317             &STANDARD,
1318             general_purpose::GeneralPurposeConfig::new().with_decode_allow_trailing_bits(true),
1319         )
1320     }
1321 
random<R: rand::Rng>(rng: &mut R) -> Self::Engine1322     fn random<R: rand::Rng>(rng: &mut R) -> Self::Engine {
1323         let alphabet = random_alphabet(rng);
1324 
1325         Self::random_alphabet(rng, alphabet)
1326     }
1327 
random_alphabet<R: rand::Rng>(rng: &mut R, alphabet: &Alphabet) -> Self::Engine1328     fn random_alphabet<R: rand::Rng>(rng: &mut R, alphabet: &Alphabet) -> Self::Engine {
1329         general_purpose::GeneralPurpose::new(alphabet, random_config(rng))
1330     }
1331 }
1332 
1333 struct NaiveWrapper {}
1334 
1335 impl EngineWrapper for NaiveWrapper {
1336     type Engine = naive::Naive;
1337 
standard() -> Self::Engine1338     fn standard() -> Self::Engine {
1339         naive::Naive::new(
1340             &STANDARD,
1341             naive::NaiveConfig {
1342                 encode_padding: true,
1343                 decode_allow_trailing_bits: false,
1344                 decode_padding_mode: DecodePaddingMode::RequireCanonical,
1345             },
1346         )
1347     }
1348 
standard_unpadded() -> Self::Engine1349     fn standard_unpadded() -> Self::Engine {
1350         naive::Naive::new(
1351             &STANDARD,
1352             naive::NaiveConfig {
1353                 encode_padding: false,
1354                 decode_allow_trailing_bits: false,
1355                 decode_padding_mode: DecodePaddingMode::RequireNone,
1356             },
1357         )
1358     }
1359 
standard_with_pad_mode( encode_pad: bool, decode_pad_mode: DecodePaddingMode, ) -> Self::Engine1360     fn standard_with_pad_mode(
1361         encode_pad: bool,
1362         decode_pad_mode: DecodePaddingMode,
1363     ) -> Self::Engine {
1364         naive::Naive::new(
1365             &STANDARD,
1366             naive::NaiveConfig {
1367                 encode_padding: false,
1368                 decode_allow_trailing_bits: false,
1369                 decode_padding_mode: decode_pad_mode,
1370             },
1371         )
1372     }
1373 
standard_allow_trailing_bits() -> Self::Engine1374     fn standard_allow_trailing_bits() -> Self::Engine {
1375         naive::Naive::new(
1376             &STANDARD,
1377             naive::NaiveConfig {
1378                 encode_padding: true,
1379                 decode_allow_trailing_bits: true,
1380                 decode_padding_mode: DecodePaddingMode::RequireCanonical,
1381             },
1382         )
1383     }
1384 
random<R: rand::Rng>(rng: &mut R) -> Self::Engine1385     fn random<R: rand::Rng>(rng: &mut R) -> Self::Engine {
1386         let alphabet = random_alphabet(rng);
1387 
1388         Self::random_alphabet(rng, alphabet)
1389     }
1390 
random_alphabet<R: rand::Rng>(rng: &mut R, alphabet: &Alphabet) -> Self::Engine1391     fn random_alphabet<R: rand::Rng>(rng: &mut R, alphabet: &Alphabet) -> Self::Engine {
1392         let mode = rng.gen();
1393 
1394         let config = naive::NaiveConfig {
1395             encode_padding: match mode {
1396                 DecodePaddingMode::Indifferent => rng.gen(),
1397                 DecodePaddingMode::RequireCanonical => true,
1398                 DecodePaddingMode::RequireNone => false,
1399             },
1400             decode_allow_trailing_bits: rng.gen(),
1401             decode_padding_mode: mode,
1402         };
1403 
1404         naive::Naive::new(alphabet, config)
1405     }
1406 }
1407 
seeded_rng() -> impl rand::Rng1408 fn seeded_rng() -> impl rand::Rng {
1409     rngs::SmallRng::from_entropy()
1410 }
1411 
all_pad_modes() -> Vec<DecodePaddingMode>1412 fn all_pad_modes() -> Vec<DecodePaddingMode> {
1413     vec![
1414         DecodePaddingMode::Indifferent,
1415         DecodePaddingMode::RequireCanonical,
1416         DecodePaddingMode::RequireNone,
1417     ]
1418 }
1419 
assert_all_suffixes_ok<E: Engine>(engine: E, suffixes: Vec<&str>)1420 fn assert_all_suffixes_ok<E: Engine>(engine: E, suffixes: Vec<&str>) {
1421     for num_prefix_quads in 0..256 {
1422         for &suffix in suffixes.iter() {
1423             let mut encoded = "AAAA".repeat(num_prefix_quads);
1424             encoded.push_str(suffix);
1425 
1426             let res = &engine.decode(&encoded);
1427             assert!(res.is_ok());
1428         }
1429     }
1430 }
1431