Skip to content

Commit 9a13a0c

Browse files
committed
Add a max_size parameter to fuzzer_mutate
This allows users to force libfuzzer to only perform shrinking mutations.
1 parent b5dfd80 commit 9a13a0c

File tree

2 files changed

+21
-9
lines changed

2 files changed

+21
-9
lines changed

example_mutator/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ fuzz_mutator!(
2424
let len = decompressed.len();
2525
let cap = decompressed.capacity();
2626
decompressed.resize(cap, 0);
27-
let new_decompressed_size = libfuzzer_sys::fuzzer_mutate(&mut decompressed, len);
27+
let new_decompressed_size = libfuzzer_sys::fuzzer_mutate(&mut decompressed, len, cap);
2828

2929
// Recompress the mutated data.
3030
let compressed = compress(&decompressed[..new_decompressed_size]);

src/lib.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ macro_rules! fuzz_target {
285285
/// let len = decompressed.len();
286286
/// let cap = decompressed.capacity();
287287
/// decompressed.resize(cap, 0);
288-
/// let new_decompressed_size = libfuzzer_sys::fuzzer_mutate(&mut decompressed, len);
288+
/// let new_decompressed_size = libfuzzer_sys::fuzzer_mutate(&mut decompressed, len, cap);
289289
///
290290
/// // Recompress the mutated data.
291291
/// let compressed = compress(&decompressed[..new_decompressed_size]);
@@ -374,25 +374,37 @@ macro_rules! fuzz_mutator {
374374
/// You generally don't have to use this at all unless you're defining a
375375
/// custom mutator with [the `fuzz_mutator!` macro][crate::fuzz_mutator].
376376
///
377-
/// Mutates `data[..size]` in place and returns the new size of the mutated
378-
/// data.
377+
/// Mutates `data[..size]` in place such that the mutated data is no larger than
378+
/// `max_size` and returns the new size of the mutated data.
379+
///
380+
/// To only allow shrinking mutations, make `max_size < size`.
381+
///
382+
/// To additionally allow mutations that grow the size of the data, make
383+
/// `max_size > size`.
384+
///
385+
/// Both `size` and `max_size` must be less than or equal to `data.len()`.
379386
///
380387
/// # Example
381388
///
382389
/// ```no_run
383390
/// // Create some data in a buffer.
384391
/// let mut data = vec![0; 128];
385-
/// data[..5].copy_from_slice(b"hello");
392+
/// data[..b"hello".len()].copy_from_slice(b"hello");
386393
///
387-
/// // Ask `libFuzzer` to mutate the data.
388-
/// let new_size = libfuzzer_sys::fuzzer_mutate(&mut data, 5);
394+
/// // Ask `libFuzzer` to mutate the data. By setting `max_size` to our buffer's
395+
/// // full length, we are allowing `libFuzzer` to perform mutations that grow
396+
/// // the size of the data, such as insertions.
397+
/// let size = b"hello".len();
398+
/// let max_size = data.len();
399+
/// let new_size = libfuzzer_sys::fuzzer_mutate(&mut data, size, max_size);
389400
///
390401
/// // Get the mutated data out of the buffer.
391402
/// let mutated_data = &data[..new_size];
392403
/// ```
393-
pub fn fuzzer_mutate(data: &mut [u8], size: usize) -> usize {
404+
pub fn fuzzer_mutate(data: &mut [u8], size: usize, max_size: usize) -> usize {
394405
assert!(size <= data.len());
395-
let new_size = unsafe { LLVMFuzzerMutate(data.as_mut_ptr(), size, data.len()) };
406+
assert!(max_size <= data.len());
407+
let new_size = unsafe { LLVMFuzzerMutate(data.as_mut_ptr(), size, max_size) };
396408
assert!(new_size <= data.len());
397409
new_size
398410
}

0 commit comments

Comments
 (0)