/src/textwrap/fuzz/fuzz_targets/wrap_optimal_fit.rs
Line | Count | Source |
1 | | #![no_main] |
2 | | use arbitrary::Arbitrary; |
3 | | use libfuzzer_sys::fuzz_target; |
4 | | use textwrap::wrap_algorithms::wrap_optimal_fit; |
5 | | use textwrap::{core, wrap_algorithms}; |
6 | | |
7 | | #[derive(Arbitrary, Debug)] |
8 | | struct Penalties { |
9 | | nline_penalty: usize, |
10 | | overflow_penalty: usize, |
11 | | short_last_line_fraction: usize, |
12 | | short_last_line_penalty: usize, |
13 | | hyphen_penalty: usize, |
14 | | } |
15 | | |
16 | | impl Into<wrap_algorithms::Penalties> for Penalties { |
17 | 637 | fn into(self) -> wrap_algorithms::Penalties { |
18 | 637 | wrap_algorithms::Penalties { |
19 | 637 | nline_penalty: self.nline_penalty, |
20 | 637 | overflow_penalty: self.overflow_penalty, |
21 | 637 | short_last_line_fraction: std::cmp::max(1, self.short_last_line_fraction), |
22 | 637 | short_last_line_penalty: self.short_last_line_penalty, |
23 | 637 | hyphen_penalty: self.hyphen_penalty, |
24 | 637 | } |
25 | 637 | } |
26 | | } |
27 | | |
28 | | #[derive(Arbitrary, Debug, PartialEq)] |
29 | | struct Word { |
30 | | width: f64, |
31 | | whitespace_width: f64, |
32 | | penalty_width: f64, |
33 | | } |
34 | | |
35 | | #[rustfmt::skip] |
36 | | impl core::Fragment for Word { |
37 | 1.50M | fn width(&self) -> f64 { self.width } |
38 | 16.7M | fn whitespace_width(&self) -> f64 { self.whitespace_width } |
39 | 30.5M | fn penalty_width(&self) -> f64 { self.penalty_width } |
40 | | } |
41 | | |
42 | | // Check wrapping fragments with mostly arbitrary widths. Infinite |
43 | | // widths are not supported since they instantly trigger an overflow |
44 | | // in the cost computation. Similarly for very large values: the 1e100 |
45 | | // bound used here is somewhat conservative, the real bound seems to |
46 | | // be around 1e170. |
47 | | fuzz_target!(|input: (usize, Vec<Word>, Penalties)| { |
48 | | let width = input.0; |
49 | | let words = input.1; |
50 | | let penalties = input.2.into(); |
51 | | |
52 | | for word in &words { |
53 | | for width in [word.width, word.whitespace_width, word.penalty_width] { |
54 | | if !width.is_finite() || width.abs() > 1e100 { |
55 | | return; |
56 | | } |
57 | | } |
58 | | } |
59 | | |
60 | | let _ = wrap_optimal_fit(&words, &[width as f64], &penalties); |
61 | | }); |