[![](https://docs.rs/bufrng/badge.svg)](https://docs.rs/bufrng/)
[![](https://img.shields.io/crates/v/bufrng.svg)](https://crates.io/crates/bufrng)
[![](https://img.shields.io/crates/d/bufrng.svg)](https://crates.io/crates/bufrng)
[![Build Status](https://dev.azure.com/fitzgen/bufrng/_apis/build/status/fitzgen.bufrng?branchName=master)](https://dev.azure.com/fitzgen/bufrng/_build/latest?definitionId=2&branchName=master)
# `bufrng`
`BufRng` is a "random" number generator that simply yields pre-determined values
from a buffer, and yields `0`s once the buffer is exhausted.
⚠⚠⚠
This RNG is not suitable for anything other than testing and
fuzzing! It is not suitable for cryptography! It is not suitable for
generating pseudo-random numbers!
⚠⚠⚠
### Why?
`BufRng` is useful for reinterpreting raw input bytes from
[libFuzzer](https://rust-fuzz.github.io/book/cargo-fuzz.html) or
[AFL](https://rust-fuzz.github.io/book/afl.html) as an RNG that is used with
structure-aware test case generators (e.g.
[`quickcheck::Arbitrary`](https://docs.rs/quickcheck/0.9.0/quickcheck/trait.Arbitrary.html)). This
combines the power of coverage-guided fuzzing with structure-aware fuzzing.
### Example
Let's say we are developing a crate to convert back and forth between RGB and
HSL color representations.
First, we can implement `quickcheck::Arbitrary` for our color types to get
structure-aware test case generators. Then, we can use these with `quickcheck`'s
own test runner infrastructure to assert various properties about our code (such
as it never panics, or that RGB -> HSL -> RGB is the identity function) and
`quickcheck` will generate random instances of `Rgb` and `Hsl` to check this
property against.
```rust
/// A color represented with RGB.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Rgb {
pub r: u8,
pub g: u8,
pub b: u8,
}
impl Rgb {
pub fn to_hsl(&self) -> Hsl {
// ...
}
}
/// A color represented with HSL.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Hsl {
pub h: f64,
pub s: f64,
pub l: f64,
}
impl Hsl {
pub fn to_rgb(&self) -> Rgb {
// ...
}
}
// Implementations of `quickcheck::Arbitrary` to create structure-aware test
// case generators for `Rgb` and `Hsl`.
use rand::prelude::*;
use quickcheck::{Arbitrary, Gen};
impl Arbitrary for Rgb {
fn arbitrary(g: &mut G) -> Self {
Rgb {
r: g.gen(),
g: g.gen(),
b: g.gen(),
}
}
}
impl Arbitrary for Hsl {
fn arbitrary(g: &mut G) -> Self {
Hsl {
h: g.gen_range(0.0, 360.0),
s: g.gen_range(0.0, 1.0),
l: g.gen_range(0.0, 1.0),
}
}
}
// Properties that we can have `quickcheck` assert for us.
pub fn rgb_to_hsl_doesnt_panic(rgb: Rgb) {
let _ = rgb.to_hsl();
}
pub fn rgb_to_hsl_to_rgb_is_identity(rgb: Rgb) {
assert_eq!(rgb, rgb.to_hsl().to_rgb());
}
#[cfg(test)]
mod tests {
quickcheck::quickcheck! {
fn rgb_to_hsl_doesnt_panic(rgb: Rgb) -> bool {
super::rgb_to_hsl_doesnt_panic(rgb);
true
}
}
quickcheck::quickcheck! {
fn rgb_to_hsl_to_rgb_is_identity(rgb: Rgb) -> bool {
super::rgb_to_hsl_to_rgb_is_identity(rgb);
true
}
}
}
```
Finally, we can *reuse* our existing structure-aware test case generators (the
`Arbitrary` impls) with libFuzzer of AFL inputs with `BufRng`. Thus we can
leverage coverage-guided fuzzing — where the fuzzer is observing code
coverage while tests are running, and trying to maximize the paths the inputs
cover — with our existing structure-aware generators.
The following snippet is with [`cargo fuzz` and
libFuzzer](https://rust-fuzz.github.io/book/cargo-fuzz.html), but the concepts
would apply equally well to AFL, for example.
```rust
// my-rgb-to-hsl-crate/fuzz/fuzz_targets/rgb.rs
#![no_main]
#[macro_use]
extern crate libfuzzer_sys;
use bufrng::BufRng;
use my_rgb_to_hsl_crate::{rgb_to_hsl_doesnt_panic, rgb_to_hsl_to_rgb_is_identity, Rgb};
use quickcheck::Arbitrary;
fuzz_target!(|data: &[u8]| {
// Create a `BufRng` from the raw data given to us by the fuzzer.
let mut rng = BufRng::new(data);
// Generate an `Rgb` instance with it.
let rgb = Rgb::arbitrary(&mut rng);
// Assert our properties!
rgb_to_hsl_doesnt_panic(rgb);
rgb_to_hsl_to_rgb_is_identity(rgb);
});
```