/rust/registry/src/index.crates.io-6f17d22bba15001f/rav1e-0.7.1/src/fuzzing.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2019-2022, The rav1e contributors. All rights reserved |
2 | | // |
3 | | // This source code is subject to the terms of the BSD 2 Clause License and |
4 | | // the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
5 | | // was not distributed with this source code in the LICENSE file, you can |
6 | | // obtain it at www.aomedia.org/license/software. If the Alliance for Open |
7 | | // Media Patent License 1.0 was not distributed with this source code in the |
8 | | // PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
9 | | |
10 | | use std::marker::PhantomData; |
11 | | use std::sync::Arc; |
12 | | |
13 | | use libfuzzer_sys::arbitrary::{Arbitrary, Error, Unstructured}; |
14 | | |
15 | | use crate::prelude::*; |
16 | | |
17 | | // Adding new fuzz targets |
18 | | // |
19 | | // 1. Add a function to this file which looks like this: |
20 | | // |
21 | | // pub fn fuzz_something(data: Data) { |
22 | | // // Invoke everything you need. |
23 | | // // |
24 | | // // Your function may accept a value of any type that implements |
25 | | // // Arbitrary [1]. This is how fuzzer affects the execution—by |
26 | | // // feeding in different bytes, which result in different |
27 | | // // arbitrary values being generated. |
28 | | // // [1]: https://docs.rs/arbitrary/0.3.3/arbitrary/trait.Arbitrary.html |
29 | | // // |
30 | | // // Derive Debug for the structures you create with arbitrary data. |
31 | | // } |
32 | | // |
33 | | // 2. cargo fuzz add something |
34 | | // 3. Copy the contents of any other .rs file from fuzz/fuzz_targets/ into the |
35 | | // newly created fuzz/fuzz_targets/something.rs and change the function |
36 | | // being called to fuzz_something. |
37 | | // |
38 | | // Now you can fuzz the new target with cargo fuzz. |
39 | | |
40 | | #[derive(Debug)] |
41 | | pub struct ArbitraryConfig { |
42 | | config: Config, |
43 | | } |
44 | | |
45 | | #[inline] |
46 | 0 | fn arbitrary_rational(u: &mut Unstructured<'_>) -> Result<Rational, Error> { |
47 | 0 | Ok(Rational::new(Arbitrary::arbitrary(u)?, Arbitrary::arbitrary(u)?)) |
48 | 0 | } |
49 | | |
50 | | #[inline] |
51 | 0 | fn arbitrary_color_description( |
52 | 0 | u: &mut Unstructured<'_>, |
53 | 0 | ) -> Result<Option<ColorDescription>, Error> { |
54 | 0 | if Arbitrary::arbitrary(u)? { |
55 | 0 | return Ok(None); |
56 | 0 | } |
57 | 0 | Ok(Some(ColorDescription { |
58 | 0 | color_primaries: *u.choose(&[ |
59 | 0 | ColorPrimaries::BT709, |
60 | 0 | ColorPrimaries::Unspecified, |
61 | 0 | ColorPrimaries::BT470M, |
62 | 0 | ColorPrimaries::BT470BG, |
63 | 0 | ColorPrimaries::BT601, |
64 | 0 | ColorPrimaries::SMPTE240, |
65 | 0 | ColorPrimaries::GenericFilm, |
66 | 0 | ColorPrimaries::BT2020, |
67 | 0 | ColorPrimaries::XYZ, |
68 | 0 | ColorPrimaries::SMPTE431, |
69 | 0 | ColorPrimaries::SMPTE432, |
70 | 0 | ColorPrimaries::EBU3213, |
71 | 0 | ])?, |
72 | 0 | transfer_characteristics: *u.choose(&[ |
73 | 0 | TransferCharacteristics::BT709, |
74 | 0 | TransferCharacteristics::Unspecified, |
75 | 0 | TransferCharacteristics::BT470M, |
76 | 0 | TransferCharacteristics::BT470BG, |
77 | 0 | TransferCharacteristics::BT601, |
78 | 0 | TransferCharacteristics::SMPTE240, |
79 | 0 | TransferCharacteristics::Linear, |
80 | 0 | TransferCharacteristics::Log100, |
81 | 0 | TransferCharacteristics::Log100Sqrt10, |
82 | 0 | TransferCharacteristics::IEC61966, |
83 | 0 | TransferCharacteristics::BT1361, |
84 | 0 | TransferCharacteristics::SRGB, |
85 | 0 | TransferCharacteristics::BT2020_10Bit, |
86 | 0 | TransferCharacteristics::BT2020_12Bit, |
87 | 0 | TransferCharacteristics::SMPTE2084, |
88 | 0 | TransferCharacteristics::SMPTE428, |
89 | 0 | TransferCharacteristics::HLG, |
90 | 0 | ])?, |
91 | 0 | matrix_coefficients: *u.choose(&[ |
92 | 0 | MatrixCoefficients::Identity, |
93 | 0 | MatrixCoefficients::BT709, |
94 | 0 | MatrixCoefficients::Unspecified, |
95 | 0 | MatrixCoefficients::FCC, |
96 | 0 | MatrixCoefficients::BT470BG, |
97 | 0 | MatrixCoefficients::BT601, |
98 | 0 | MatrixCoefficients::SMPTE240, |
99 | 0 | MatrixCoefficients::YCgCo, |
100 | 0 | MatrixCoefficients::BT2020NCL, |
101 | 0 | MatrixCoefficients::BT2020CL, |
102 | 0 | MatrixCoefficients::SMPTE2085, |
103 | 0 | MatrixCoefficients::ChromatNCL, |
104 | 0 | MatrixCoefficients::ChromatCL, |
105 | 0 | MatrixCoefficients::ICtCp, |
106 | 0 | ])?, |
107 | | })) |
108 | 0 | } |
109 | | |
110 | | #[inline] |
111 | 0 | fn arbitrary_chromacity_point( |
112 | 0 | u: &mut Unstructured<'_>, |
113 | 0 | ) -> Result<ChromaticityPoint, Error> { |
114 | 0 | Ok(ChromaticityPoint { |
115 | 0 | x: Arbitrary::arbitrary(u)?, |
116 | 0 | y: Arbitrary::arbitrary(u)?, |
117 | | }) |
118 | 0 | } |
119 | | |
120 | | #[inline] |
121 | 0 | fn arbitrary_mastering_display( |
122 | 0 | u: &mut Unstructured<'_>, |
123 | 0 | ) -> Result<Option<MasteringDisplay>, Error> { |
124 | 0 | if Arbitrary::arbitrary(u)? { |
125 | 0 | return Ok(None); |
126 | 0 | } |
127 | 0 | Ok(Some(MasteringDisplay { |
128 | 0 | primaries: [ |
129 | 0 | arbitrary_chromacity_point(u)?, |
130 | 0 | arbitrary_chromacity_point(u)?, |
131 | 0 | arbitrary_chromacity_point(u)?, |
132 | | ], |
133 | 0 | white_point: arbitrary_chromacity_point(u)?, |
134 | 0 | max_luminance: Arbitrary::arbitrary(u)?, |
135 | 0 | min_luminance: Arbitrary::arbitrary(u)?, |
136 | | })) |
137 | 0 | } |
138 | | |
139 | | #[inline] |
140 | 0 | fn arbitrary_content_light( |
141 | 0 | u: &mut Unstructured<'_>, |
142 | 0 | ) -> Result<Option<ContentLight>, Error> { |
143 | 0 | if Arbitrary::arbitrary(u)? { |
144 | 0 | return Ok(None); |
145 | 0 | } |
146 | 0 | Ok(Some(ContentLight { |
147 | 0 | max_content_light_level: Arbitrary::arbitrary(u)?, |
148 | 0 | max_frame_average_light_level: Arbitrary::arbitrary(u)?, |
149 | | })) |
150 | 0 | } |
151 | | |
152 | | impl Arbitrary<'_> for ArbitraryConfig { |
153 | 0 | fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self, Error> { |
154 | 0 | let mut enc = EncoderConfig::with_speed_preset(Arbitrary::arbitrary(u)?); |
155 | 0 | enc.width = Arbitrary::arbitrary(u)?; |
156 | 0 | enc.height = Arbitrary::arbitrary(u)?; |
157 | 0 | enc.bit_depth = u.int_in_range(0..=16)?; |
158 | 0 | enc.still_picture = Arbitrary::arbitrary(u)?; |
159 | 0 | enc.time_base = arbitrary_rational(u)?; |
160 | 0 | enc.min_key_frame_interval = Arbitrary::arbitrary(u)?; |
161 | 0 | enc.max_key_frame_interval = Arbitrary::arbitrary(u)?; |
162 | 0 | enc.reservoir_frame_delay = Arbitrary::arbitrary(u)?; |
163 | 0 | enc.low_latency = Arbitrary::arbitrary(u)?; |
164 | 0 | enc.quantizer = Arbitrary::arbitrary(u)?; |
165 | 0 | enc.min_quantizer = Arbitrary::arbitrary(u)?; |
166 | 0 | enc.bitrate = Arbitrary::arbitrary(u)?; |
167 | 0 | enc.tile_cols = Arbitrary::arbitrary(u)?; |
168 | 0 | enc.tile_rows = Arbitrary::arbitrary(u)?; |
169 | 0 | enc.tiles = Arbitrary::arbitrary(u)?; |
170 | 0 | enc.speed_settings.rdo_lookahead_frames = Arbitrary::arbitrary(u)?; |
171 | 0 | let config = Config::new().with_encoder_config(enc).with_threads(1); |
172 | 0 | Ok(Self { config }) |
173 | 0 | } |
174 | | } |
175 | | |
176 | 0 | pub fn fuzz_construct_context(arbitrary: ArbitraryConfig) { |
177 | 0 | let _: Result<Context<u16>, _> = arbitrary.config.new_context(); |
178 | 0 | } |
179 | | |
180 | 0 | fn encode_frames( |
181 | 0 | ctx: &mut Context<u8>, mut frames: impl Iterator<Item = Frame<u8>>, |
182 | 0 | ) -> Result<(), EncoderStatus> { |
183 | | loop { |
184 | 0 | let rv = ctx.receive_packet(); |
185 | 0 | debug!("ctx.receive_packet() = {:#?}", rv); |
186 | | |
187 | 0 | match rv { |
188 | 0 | Ok(_packet) => {} |
189 | 0 | Err(EncoderStatus::Encoded) => {} |
190 | | Err(EncoderStatus::LimitReached) => { |
191 | 0 | break; |
192 | | } |
193 | | Err(EncoderStatus::NeedMoreData) => { |
194 | 0 | ctx.send_frame(frames.next().map(Arc::new))?; |
195 | | } |
196 | | Err(EncoderStatus::EnoughData) => { |
197 | 0 | unreachable!(); |
198 | | } |
199 | | Err(EncoderStatus::NotReady) => { |
200 | 0 | unreachable!(); |
201 | | } |
202 | | Err(EncoderStatus::Failure) => { |
203 | 0 | return Err(EncoderStatus::Failure); |
204 | | } |
205 | | } |
206 | | } |
207 | | |
208 | 0 | Ok(()) |
209 | 0 | } |
210 | | |
211 | | #[derive(Debug)] |
212 | | pub struct ArbitraryEncoder { |
213 | | config: Config, |
214 | | frame_count: u8, |
215 | | pixels: Box<[u8]>, |
216 | | } |
217 | | |
218 | | impl Arbitrary<'_> for ArbitraryEncoder { |
219 | 0 | fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self, Error> { |
220 | 0 | let enc = EncoderConfig { |
221 | 0 | speed_settings: SpeedSettings::from_preset(u.int_in_range(0..=10)?), |
222 | 0 | width: u.int_in_range(1..=256)?, |
223 | 0 | height: u.int_in_range(1..=256)?, |
224 | 0 | still_picture: Arbitrary::arbitrary(u)?, |
225 | 0 | time_base: arbitrary_rational(u)?, |
226 | 0 | min_key_frame_interval: u.int_in_range(0..=3)?, |
227 | 0 | max_key_frame_interval: u.int_in_range(1..=4)?, |
228 | 0 | low_latency: Arbitrary::arbitrary(u)?, |
229 | 0 | quantizer: Arbitrary::arbitrary(u)?, |
230 | 0 | min_quantizer: Arbitrary::arbitrary(u)?, |
231 | 0 | bitrate: Arbitrary::arbitrary(u)?, |
232 | 0 | tile_cols: u.int_in_range(0..=2)?, |
233 | 0 | tile_rows: u.int_in_range(0..=2)?, |
234 | 0 | tiles: u.int_in_range(0..=16)?, |
235 | | |
236 | 0 | chroma_sampling: *u.choose(&[ |
237 | 0 | ChromaSampling::Cs420, |
238 | 0 | ChromaSampling::Cs422, |
239 | 0 | ChromaSampling::Cs444, |
240 | 0 | ChromaSampling::Cs400, |
241 | 0 | ])?, |
242 | 0 | chroma_sample_position: *u.choose(&[ |
243 | 0 | ChromaSamplePosition::Unknown, |
244 | 0 | ChromaSamplePosition::Vertical, |
245 | 0 | ChromaSamplePosition::Colocated, |
246 | 0 | ])?, |
247 | 0 | pixel_range: *u.choose(&[PixelRange::Limited, PixelRange::Full])?, |
248 | 0 | error_resilient: Arbitrary::arbitrary(u)?, |
249 | 0 | reservoir_frame_delay: Arbitrary::arbitrary(u)?, |
250 | | |
251 | 0 | sample_aspect_ratio: arbitrary_rational(u)?, |
252 | | bit_depth: 8, |
253 | 0 | color_description: arbitrary_color_description(u)?, |
254 | 0 | mastering_display: arbitrary_mastering_display(u)?, |
255 | 0 | content_light: arbitrary_content_light(u)?, |
256 | 0 | level_idx: Some(31), |
257 | 0 | enable_timing_info: Arbitrary::arbitrary(u)?, |
258 | 0 | switch_frame_interval: u.int_in_range(0..=3)?, |
259 | 0 | tune: *u.choose(&[Tune::Psnr, Tune::Psychovisual])?, |
260 | 0 | film_grain_params: None, |
261 | | }; |
262 | | |
263 | 0 | let frame_count = |
264 | 0 | if enc.still_picture { 1 } else { u.int_in_range(1..=3)? }; |
265 | 0 | if u.is_empty() { |
266 | 0 | return Err(Error::NotEnoughData); |
267 | 0 | } |
268 | 0 | let pixels = u.bytes(u.len())?.to_vec().into_boxed_slice(); |
269 | 0 | let config = Config::new().with_encoder_config(enc).with_threads(1); |
270 | 0 | Ok(Self { config, frame_count, pixels }) |
271 | 0 | } |
272 | | } |
273 | | |
274 | 0 | pub fn fuzz_encode(arbitrary: ArbitraryEncoder) { |
275 | 0 | let res = arbitrary.config.new_context(); |
276 | 0 | if res.is_err() { |
277 | 0 | return; |
278 | 0 | } |
279 | 0 | let mut context: Context<u8> = res.unwrap(); |
280 | 0 |
|
281 | 0 | let mut pixels = arbitrary.pixels.iter().cycle(); |
282 | 0 | let mut frame = context.new_frame(); |
283 | 0 | let frames = (0..arbitrary.frame_count).map(|_| { |
284 | 0 | for plane in &mut frame.planes { |
285 | 0 | let stride = plane.cfg.stride; |
286 | 0 | for row in plane.data_origin_mut().chunks_mut(stride) { |
287 | 0 | for pixel in row { |
288 | 0 | *pixel = *pixels.next().unwrap(); |
289 | 0 | } |
290 | | } |
291 | | } |
292 | | |
293 | 0 | frame.clone() |
294 | 0 | }); |
295 | 0 |
|
296 | 0 | let _ = encode_frames(&mut context, frames); |
297 | 0 | } |
298 | | |
299 | | #[derive(Debug)] |
300 | | pub struct DecodeTestParameters<T: Pixel> { |
301 | | w: usize, |
302 | | h: usize, |
303 | | speed: u8, |
304 | | q: usize, |
305 | | limit: usize, |
306 | | bit_depth: usize, |
307 | | chroma_sampling: ChromaSampling, |
308 | | min_keyint: u64, |
309 | | max_keyint: u64, |
310 | | switch_frame_interval: u64, |
311 | | low_latency: bool, |
312 | | error_resilient: bool, |
313 | | bitrate: i32, |
314 | | tile_cols_log2: usize, |
315 | | tile_rows_log2: usize, |
316 | | still_picture: bool, |
317 | | pixel: PhantomData<T>, |
318 | | } |
319 | | |
320 | | impl<T: Pixel> Arbitrary<'_> for DecodeTestParameters<T> { |
321 | 0 | fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self, Error> { |
322 | 0 | let mut p = Self { |
323 | 0 | w: u.int_in_range(16..=16 + 255)?, |
324 | 0 | h: u.int_in_range(16..=16 + 255)?, |
325 | 0 | speed: u.int_in_range(0..=10)?, |
326 | 0 | q: u8::arbitrary(u)?.into(), |
327 | 0 | limit: u.int_in_range(1..=3)?, |
328 | | bit_depth: 8, |
329 | 0 | chroma_sampling: *u.choose(&[ |
330 | 0 | ChromaSampling::Cs420, |
331 | 0 | ChromaSampling::Cs422, |
332 | 0 | ChromaSampling::Cs444, |
333 | 0 | ChromaSampling::Cs400, |
334 | 0 | ])?, |
335 | 0 | min_keyint: u.int_in_range(0..=3)?, |
336 | 0 | max_keyint: u.int_in_range(1..=4)?, |
337 | 0 | switch_frame_interval: u.int_in_range(0..=3)?, |
338 | 0 | low_latency: bool::arbitrary(u)?, |
339 | 0 | error_resilient: bool::arbitrary(u)?, |
340 | 0 | bitrate: u16::arbitrary(u)?.into(), |
341 | 0 | tile_cols_log2: u.int_in_range(0..=2)?, |
342 | 0 | tile_rows_log2: u.int_in_range(0..=2)?, |
343 | 0 | still_picture: bool::arbitrary(u)?, |
344 | 0 | pixel: PhantomData, |
345 | | }; |
346 | 0 | if matches!(T::type_enum(), PixelType::U16) { |
347 | 0 | p.bit_depth = *u.choose(&[8, 10, 12])?; |
348 | 0 | } |
349 | 0 | if !p.low_latency { |
350 | 0 | p.switch_frame_interval = 0; |
351 | 0 | } |
352 | 0 | if p.still_picture { |
353 | 0 | p.limit = 1 |
354 | 0 | } |
355 | 0 | Ok(p) |
356 | 0 | } |
357 | | } |
358 | | |
359 | | #[cfg(feature = "decode_test_dav1d")] |
360 | | pub fn fuzz_encode_decode<T: Pixel>(p: DecodeTestParameters<T>) { |
361 | | use crate::test_encode_decode::*; |
362 | | |
363 | | let mut dec = get_decoder::<T>("dav1d", p.w, p.h); |
364 | | dec.encode_decode( |
365 | | true, |
366 | | p.w, |
367 | | p.h, |
368 | | p.speed, |
369 | | p.q, |
370 | | p.limit, |
371 | | p.bit_depth, |
372 | | p.chroma_sampling, |
373 | | p.min_keyint, |
374 | | p.max_keyint, |
375 | | p.switch_frame_interval, |
376 | | p.low_latency, |
377 | | p.error_resilient, |
378 | | p.bitrate, |
379 | | p.tile_cols_log2, |
380 | | p.tile_rows_log2, |
381 | | p.still_picture, |
382 | | None, |
383 | | ); |
384 | | } |