1use crate::{
5 frame::{self, new_connection_id::STATELESS_RESET_TOKEN_LEN},
6 stream::StreamType,
7 varint,
8};
9use core::ops::Range;
10pub use s2n_codec::{Encoder, EncoderBuffer, EncoderValue};
11
12pub trait Random {
13 fn fill(&mut self, bytes: &mut [u8]);
14
15 fn gen_range(&mut self, range: Range<u64>) -> u64;
16
17 #[inline]
18 fn shuffle(&mut self, bytes: &mut [u8]) {
19 if bytes.is_empty() {
20 return;
21 }
22
23 let len = bytes.len() as u64;
24
25 let count = self.gen_range(0..len);
26 for _ in 0..count {
27 let from = self.gen_range(0..len);
28 let to = self.gen_range(0..len);
29 bytes.swap(from as usize, to as usize);
30 }
31 }
32
33 #[inline]
34 fn gen_slice<'a>(&mut self, bytes: &'a mut [u8]) -> &'a mut [u8] {
35 if bytes.is_empty() {
36 return bytes;
37 }
38
39 let len = bytes.len() as u64;
40 let len = self.gen_range(0..len);
41 let bytes = &mut bytes[..len as usize];
42 self.fill(bytes);
43 bytes
44 }
45
46 #[inline]
47 fn gen_bool(&mut self) -> bool {
48 self.gen_u8() & 0b1 == 0b1
49 }
50
51 #[inline]
52 fn gen_u8(&mut self) -> u8 {
53 let mut o = [0];
54 self.fill(&mut o);
55 o[0]
56 }
57
58 #[inline]
59 fn gen_u32(&mut self) -> u32 {
60 let mut o = [0; 4];
61 self.fill(&mut o);
62 u32::from_le_bytes(o)
63 }
64
65 #[inline]
66 fn gen_u64(&mut self) -> u64 {
67 let mut o = [0; 8];
68 self.fill(&mut o);
69 u64::from_le_bytes(o)
70 }
71
72 #[inline]
73 fn gen_varint(&mut self) -> varint::VarInt {
74 use varint::VarInt;
75 let max = VarInt::MAX.as_u64();
76 let v = self.gen_range(0..(max + 1));
77 unsafe { VarInt::new_unchecked(v as _) }
78 }
79}
80
81pub trait Strategy: Sized {
82 fn havoc<R: Random>(&mut self, rand: &mut R, buffer: &mut EncoderBuffer);
84
85 #[inline]
87 fn havoc_slice<R: Random>(&mut self, rand: &mut R, buffer: &mut [u8]) -> usize {
88 let mut buffer = EncoderBuffer::new(buffer);
89 self.havoc(rand, &mut buffer);
90 buffer.len()
91 }
92
93 #[inline]
95 fn havoc_u16<R: Random>(&mut self, rand: &mut R, input: u16) -> u16 {
96 let buffer = &mut [0; 2];
97 let mut buffer = EncoderBuffer::new(buffer);
98 buffer.encode(&input);
99
100 self.havoc(rand, &mut buffer);
101
102 buffer
103 .as_mut_slice()
104 .try_into()
105 .map(u16::from_be_bytes)
106 .unwrap_or(input)
107 }
108
109 fn alternate<B: Strategy>(self, b: B, period: Range<usize>) -> Alternate<Self, B> {
111 Alternate::new(self, b, period)
112 }
113
114 fn repeat(self, count: Range<usize>) -> Repeat<Self> {
116 Repeat::new(self, count)
117 }
118
119 fn randomly(self) -> Randomly<Self> {
121 Randomly { strategy: self }
122 }
123
124 fn toggle(self, period: Range<usize>) -> Toggle<Self> {
126 Toggle::new(self, period)
127 }
128
129 fn and_then<B: Strategy>(self, b: B) -> AndThen<Self, B> {
131 AndThen { a: self, b }
132 }
133
134 fn while_has_capacity(self) -> WhileHasCapacity<Self> {
136 WhileHasCapacity { strategy: self }
137 }
138
139 #[cfg(feature = "alloc")]
141 fn hold(self, count: Range<usize>) -> Hold<Self> {
142 Hold::new(self, count)
143 }
144}
145
146impl<T: Strategy> Strategy for Option<T> {
147 fn havoc<R: Random>(&mut self, rand: &mut R, buffer: &mut EncoderBuffer) {
148 if let Some(strategy) = self.as_mut() {
149 strategy.havoc(rand, buffer);
150 }
151 }
152}
153
154#[derive(Clone, Copy, Debug, Default)]
155pub struct Alternate<A: Strategy, B: Strategy> {
156 a: A,
157 b: B,
158 min: u64,
159 max: u64,
160 is_a: bool,
161 remaining: u64,
162 init: bool,
163}
164
165impl<A: Strategy, B: Strategy> Alternate<A, B> {
166 pub fn new(a: A, b: B, range: Range<usize>) -> Self {
167 debug_assert_ne!(range.start, 0);
168 debug_assert!(range.start <= range.end);
169 Self {
170 a,
171 b,
172 min: range.start as _,
173 max: range.end as _,
174 is_a: false,
175 remaining: 0,
176 init: false,
177 }
178 }
179}
180
181impl<A: Strategy, B: Strategy> Strategy for Alternate<A, B> {
182 #[inline]
183 fn havoc<R: Random>(&mut self, rand: &mut R, buffer: &mut EncoderBuffer) {
184 if !self.init {
186 self.init = true;
187 self.is_a = rand.gen_bool();
188 }
189
190 loop {
191 if let Some(remaining) = self.remaining.checked_sub(1) {
192 self.remaining = remaining;
193
194 if self.is_a {
195 self.a.havoc(rand, buffer);
196 } else {
197 self.b.havoc(rand, buffer);
198 }
199
200 break;
201 }
202
203 self.remaining = rand.gen_range(self.min..self.max);
204 self.is_a = !self.is_a;
205 }
206 }
207}
208
209#[derive(Clone, Copy, Debug, Default)]
210pub struct AndThen<A: Strategy, B: Strategy> {
211 pub a: A,
212 pub b: B,
213}
214
215impl<A: Strategy, B: Strategy> Strategy for AndThen<A, B> {
216 #[inline]
217 fn havoc<R: Random>(&mut self, rand: &mut R, buffer: &mut EncoderBuffer) {
218 self.a.havoc(rand, buffer);
219 self.b.havoc(rand, buffer);
220 }
221}
222
223#[derive(Clone, Copy, Debug, Default)]
224pub struct Repeat<S: Strategy> {
225 strategy: S,
226 min: u64,
227 max: u64,
228}
229
230impl<S: Strategy> Repeat<S> {
231 pub fn new(strategy: S, range: Range<usize>) -> Self {
232 Self {
233 strategy,
234 min: range.start as _,
235 max: range.end as _,
236 }
237 }
238}
239
240impl<S: Strategy> Strategy for Repeat<S> {
241 #[inline]
242 fn havoc<R: Random>(&mut self, rand: &mut R, buffer: &mut EncoderBuffer) {
243 let count = rand.gen_range(self.min..self.max);
244 for _ in 0..count {
245 self.strategy.havoc(rand, buffer);
246 }
247 }
248}
249
250#[derive(Clone, Copy, Debug, Default)]
251pub struct WhileHasCapacity<S: Strategy> {
252 strategy: S,
253}
254
255impl<S: Strategy> WhileHasCapacity<S> {
256 pub fn new(strategy: S) -> Self {
257 Self { strategy }
258 }
259}
260
261impl<S: Strategy> Strategy for WhileHasCapacity<S> {
262 #[inline]
263 fn havoc<R: Random>(&mut self, rand: &mut R, buffer: &mut EncoderBuffer) {
264 for _ in 0..25 {
266 if !buffer.remaining_capacity() == 0 {
267 break;
268 }
269
270 self.strategy.havoc(rand, buffer);
271 }
272 }
273}
274
275#[derive(Clone, Copy, Debug, Default)]
276pub struct Toggle<S: Strategy> {
277 alt: Alternate<Disabled, S>,
278}
279
280impl<S: Strategy> Toggle<S> {
281 pub fn new(strategy: S, range: Range<usize>) -> Self {
282 Self {
283 alt: Alternate::new(Disabled, strategy, range),
284 }
285 }
286}
287
288impl<S: Strategy> Strategy for Toggle<S> {
289 #[inline]
290 fn havoc<R: Random>(&mut self, rand: &mut R, buffer: &mut EncoderBuffer) {
291 self.alt.havoc(rand, buffer);
292 }
293}
294
295#[derive(Clone, Copy, Debug, Default)]
296pub struct Randomly<S: Strategy> {
297 pub strategy: S,
298}
299
300impl<S: Strategy> Strategy for Randomly<S> {
301 #[inline]
302 fn havoc<R: Random>(&mut self, rand: &mut R, buffer: &mut EncoderBuffer) {
303 if rand.gen_bool() {
304 self.strategy.havoc(rand, buffer);
305 }
306 }
307}
308
309#[derive(Clone, Copy, Debug, Default)]
310pub struct Reset;
311
312impl Strategy for Reset {
313 #[inline]
314 fn havoc<R: Random>(&mut self, _rand: &mut R, buffer: &mut EncoderBuffer) {
315 buffer.set_position(0);
316 }
317}
318
319#[derive(Clone, Copy, Debug, Default)]
320pub struct Zero;
321
322impl Strategy for Zero {
323 #[inline]
324 fn havoc<R: Random>(&mut self, _rand: &mut R, buffer: &mut EncoderBuffer) {
325 for byte in buffer.as_mut_slice() {
326 *byte = 0;
327 }
328 }
329}
330
331#[derive(Clone, Copy, Debug, Default)]
332pub struct Shuffle;
333
334impl Strategy for Shuffle {
335 #[inline]
336 fn havoc<R: Random>(&mut self, rand: &mut R, buffer: &mut EncoderBuffer) {
337 if !buffer.is_empty() {
338 rand.shuffle(buffer.as_mut_slice());
339 }
340 }
341}
342
343#[derive(Clone, Copy, Debug, Default)]
344pub struct Swap;
345
346impl Strategy for Swap {
347 #[inline]
348 fn havoc<R: Random>(&mut self, rand: &mut R, buffer: &mut EncoderBuffer) {
349 let len = buffer.len() as u64;
350 if len > 0 {
351 let from = rand.gen_range(0..len) as usize;
352 let to = rand.gen_range(0..len) as usize;
353 buffer.as_mut_slice().swap(from, to);
354 }
355 }
356}
357
358#[derive(Clone, Copy, Debug, Default)]
359pub struct Truncate;
360
361impl Strategy for Truncate {
362 #[inline]
363 fn havoc<R: Random>(&mut self, rand: &mut R, buffer: &mut EncoderBuffer) {
364 let len = buffer.capacity() as u64;
365 if len > 0 {
366 let new_len = rand.gen_range(0..len) as usize;
367 buffer.set_position(new_len);
368 }
369 }
370}
371
372#[derive(Clone, Copy, Debug, Default)]
373pub struct Mutate;
374
375impl Strategy for Mutate {
376 #[inline]
377 fn havoc<R: Random>(&mut self, rand: &mut R, buffer: &mut EncoderBuffer) {
378 let len = buffer.len() as u64;
379 if len > 0 {
380 let index = rand.gen_range(0..len) as usize;
381 let value = rand.gen_u8();
382 buffer.as_mut_slice()[index] = value;
383 }
384 }
385}
386
387#[derive(Clone, Copy, Debug, Default)]
388pub struct Disabled;
389
390impl Strategy for Disabled {
391 #[inline]
392 fn havoc<R: Random>(&mut self, _rand: &mut R, _buffer: &mut EncoderBuffer) {}
393}
394
395#[cfg(feature = "alloc")]
396pub use hold::Hold;
397
398#[cfg(feature = "alloc")]
399mod hold {
400 use super::*;
401 use alloc::vec::Vec;
402
403 #[derive(Clone, Debug, Default)]
404 pub struct Hold<S: Strategy> {
405 strategy: S,
406 min: u64,
407 max: u64,
408 value: Vec<u8>,
409 remaining: u64,
410 }
411
412 impl<S: Strategy> Hold<S> {
413 pub fn new(strategy: S, range: Range<usize>) -> Self {
414 debug_assert!(range.start <= range.end);
415 Self {
416 strategy,
417 min: range.start as _,
418 max: range.end as _,
419 value: Vec::new(),
420 remaining: 0,
421 }
422 }
423 }
424
425 impl<S: Strategy> Strategy for Hold<S> {
426 #[inline]
427 fn havoc<R: Random>(&mut self, rand: &mut R, buffer: &mut EncoderBuffer) {
428 if self.remaining == 0 {
429 self.strategy.havoc(rand, buffer);
430 self.value.clear();
432 self.value.extend_from_slice(buffer.as_mut_slice());
433 self.remaining = rand.gen_range(self.min..self.max);
434 } else {
435 if !self.value.is_empty() {
436 let len = buffer.capacity().min(self.value.len());
438 buffer.set_position(0);
439 buffer.write_slice(&self.value.as_mut_slice()[..len]);
440 }
441 self.remaining -= 1;
442 }
443 }
444 }
445}
446
447#[derive(Clone, Copy, Debug, Default)]
448pub struct VarInt {
449 min: u64,
450 max: u64,
451}
452
453impl VarInt {
454 pub fn new(range: Range<varint::VarInt>) -> Self {
455 let min = range.start.as_u64();
456 let max = range.end.as_u64();
457 Self { min, max }
458 }
459}
460
461impl Strategy for VarInt {
462 #[inline]
463 fn havoc<R: Random>(&mut self, rand: &mut R, buffer: &mut EncoderBuffer) {
464 let value = rand.gen_range(self.min..self.max);
465 let value: varint::VarInt = value.try_into().unwrap();
466 if value.encoding_size() <= buffer.remaining_capacity() {
467 buffer.encode(&value);
468 }
469 }
470}
471
472#[derive(Clone, Debug)]
473pub struct Frame;
474
475impl Strategy for Frame {
476 #[inline]
477 fn havoc<R: Random>(&mut self, rand: &mut R, buffer: &mut EncoderBuffer) {
478 type GenFrame<R> = for<'a> fn(
479 rand: &'a mut R,
480 payload: &'a mut [u8],
481 remaining_capacity: usize,
482 ) -> frame::Frame<'a, AckRanges<'a, R>, &'a mut [u8]>;
483
484 let frames: &[GenFrame<R>] = &[
485 |rand, _data, cap| {
486 frame::Padding {
487 length: rand.gen_range(1..cap as _) as _,
488 }
489 .into()
490 },
491 |_rand, _data, _cap| frame::Ping.into(),
492 |rand, _data, _cap| {
494 frame::ResetStream {
495 stream_id: rand.gen_varint(),
496 application_error_code: rand.gen_varint(),
497 final_size: rand.gen_varint(),
498 }
499 .into()
500 },
501 |rand, _data, _cap| {
502 frame::StopSending {
503 stream_id: rand.gen_varint(),
504 application_error_code: rand.gen_varint(),
505 }
506 .into()
507 },
508 |rand, data, cap| {
509 let data = rand.gen_slice(&mut data[..cap]);
510 frame::Crypto {
511 offset: rand.gen_varint(),
512 data,
513 }
514 .into()
515 },
516 |rand, data, cap| {
517 let token = rand.gen_slice(&mut data[..cap]);
518 frame::NewToken { token }.into()
519 },
520 |rand, data, cap| {
521 let data = rand.gen_slice(&mut data[..cap]);
522 frame::Stream {
523 stream_id: rand.gen_varint(),
524 offset: rand.gen_varint(),
525 data,
526 is_last_frame: rand.gen_bool(),
527 is_fin: rand.gen_bool(),
528 }
529 .into()
530 },
531 |rand, _data, _cap| {
532 frame::MaxData {
533 maximum_data: rand.gen_varint(),
534 }
535 .into()
536 },
537 |rand, _data, _cap| {
538 frame::MaxStreamData {
539 stream_id: rand.gen_varint(),
540 maximum_stream_data: rand.gen_varint(),
541 }
542 .into()
543 },
544 |rand, _data, _cap| {
545 frame::MaxStreams {
546 stream_type: if rand.gen_bool() {
547 StreamType::Unidirectional
548 } else {
549 StreamType::Bidirectional
550 },
551 maximum_streams: rand.gen_varint(),
552 }
553 .into()
554 },
555 |rand, _data, _cap| {
556 frame::DataBlocked {
557 data_limit: rand.gen_varint(),
558 }
559 .into()
560 },
561 |rand, _data, _cap| {
562 frame::StreamDataBlocked {
563 stream_id: rand.gen_varint(),
564 stream_data_limit: rand.gen_varint(),
565 }
566 .into()
567 },
568 |rand, _data, _cap| {
569 frame::StreamsBlocked {
570 stream_type: if rand.gen_bool() {
571 StreamType::Unidirectional
572 } else {
573 StreamType::Bidirectional
574 },
575 stream_limit: rand.gen_varint(),
576 }
577 .into()
578 },
579 |rand, data, cap| {
580 let (stateless_reset_token, data) = data.split_at_mut(STATELESS_RESET_TOKEN_LEN);
581
582 rand.fill(stateless_reset_token);
583 let stateless_reset_token = (&*stateless_reset_token).try_into().unwrap();
584
585 let cap = cap.min(u8::MAX as usize);
587 let connection_id = rand.gen_slice(&mut data[..cap]);
588
589 frame::NewConnectionId {
590 sequence_number: rand.gen_varint(),
591 retire_prior_to: rand.gen_varint(),
592 connection_id,
593 stateless_reset_token,
594 }
595 .into()
596 },
597 |rand, _data, _cap| {
598 frame::RetireConnectionId {
599 sequence_number: rand.gen_varint(),
600 }
601 .into()
602 },
603 |rand, data, _cap| {
604 let data = &mut data[..frame::path_challenge::DATA_LEN];
605 rand.fill(data);
606 let data = (&*data).try_into().unwrap();
607 frame::PathChallenge { data }.into()
608 },
609 |rand, data, _cap| {
610 let data = &mut data[..frame::path_challenge::DATA_LEN];
611 rand.fill(data);
612 let data = (&*data).try_into().unwrap();
613 frame::PathResponse { data }.into()
614 },
615 |rand, data, cap| {
616 frame::ConnectionClose {
617 error_code: rand.gen_varint(),
618 frame_type: if rand.gen_bool() {
619 Some(rand.gen_varint())
620 } else {
621 None
622 },
623 reason: if rand.gen_bool() {
624 let reason = rand.gen_slice(&mut data[..cap]);
625 Some(reason)
626 } else {
627 None
628 },
629 }
630 .into()
631 },
632 |_rand, _data, _cap| frame::HandshakeDone.into(),
633 |rand, data, cap| {
634 let data = rand.gen_slice(&mut data[..cap]);
635 frame::Datagram {
636 is_last_frame: rand.gen_bool(),
637 data,
638 }
639 .into()
640 },
641 ];
642
643 let index = rand.gen_range(0..frames.len() as u64) as usize;
644 let mut payload = [0u8; 16_000];
645 let frame = frames[index](rand, &mut payload, buffer.remaining_capacity());
646
647 if frame.encoding_size() <= buffer.remaining_capacity() {
648 buffer.encode(&frame);
649 }
650 }
651}
652
653struct AckRanges<'a, R> {
655 #[allow(dead_code)]
656 rand: &'a mut R,
657}
658
659impl<'a, R> frame::ack::AckRanges for AckRanges<'a, R> {
660 type Iter = frame::ack::AckRangesIter<'a>;
661
662 fn ack_ranges(&self) -> Self::Iter {
663 todo!()
664 }
665
666 fn largest_acknowledged(&self) -> crate::varint::VarInt {
667 todo!()
668 }
669}
670
671#[cfg(any(test, feature = "testing"))]
672pub mod testing {
673 use super::*;
674
675 pub struct RandomSlice<'a>(core::iter::Cycle<core::slice::Iter<'a, u8>>);
676
677 impl<'a> RandomSlice<'a> {
678 pub fn new(slice: &'a [u8]) -> Self {
679 Self(slice.iter().cycle())
680 }
681 }
682
683 impl Random for RandomSlice<'_> {
684 #[inline]
685 fn fill(&mut self, bytes: &mut [u8]) {
686 for byte in bytes.iter_mut() {
687 *byte = *self.0.next().unwrap_or(&0);
688 }
689 }
690
691 #[inline]
692 fn gen_range(&mut self, range: Range<u64>) -> u64 {
693 let start = range.start.min(range.end);
694 let end = range.start.max(range.end);
695
696 let variance = end - start;
699
700 if variance == 0 {
702 return start;
703 }
704
705 let value = self.gen_u64();
706 start + value % variance
707 }
708 }
709}
710
711#[cfg(test)]
712mod tests {
713 use super::{testing::RandomSlice, *};
714 use bolero::check;
715
716 macro_rules! test {
717 ($name:ident, $strategy:expr) => {
718 #[test]
719 #[cfg_attr(miri, ignore)] fn $name() {
721 check!().for_each(|bytes| {
722 let mut rand = RandomSlice::new(bytes);
723 let mut buffer = [0u8; 256];
724 let buffer = &mut buffer[..rand.gen_u8() as usize];
725 let mut buffer = EncoderBuffer::new(buffer);
726
727 let mut strategy = $strategy;
728
729 for _ in 0..rand.gen_range(1..10) {
730 strategy.havoc(&mut rand, &mut buffer);
731 }
732 });
733 }
734 };
735 }
736
737 test!(disabled_test, Disabled);
738 test!(truncate_test, Truncate);
739 test!(reset_test, Reset);
740 test!(zero_test, Zero);
741 test!(swap_test, Swap);
742 test!(shuffle_test, Shuffle);
743 test!(mutate_test, Mutate);
744 test!(alternate_test, Disabled.alternate(Disabled, 1..5));
745 test!(and_then_test, Disabled.and_then(Disabled));
746 test!(repeat_test, Disabled.repeat(0..5));
747 test!(varint_test, VarInt::new(0u8.into()..42u8.into()));
748 test!(frame_test, Frame);
749 test!(while_has_capacity_test, Frame.while_has_capacity());
750 test!(toggle_test, Disabled.toggle(1..5));
751 test!(randomly_test, Disabled.randomly());
752 test!(hold_test, Disabled.hold(0..5));
753}