3 个稳定版本
1.0.2 | 2019年10月17日 |
---|---|
1.0.1 | 2019年8月30日 |
#16 在 #generates-random
每月90 次下载
13KB
bufrng
BufRng
是一个简单的“随机”数字生成器,从缓冲区中输出预先确定的值,并在缓冲区耗尽后输出 0
。
⚠⚠⚠
此 RNG 仅适用于测试和模糊测试!它不适用于密码学!它不适用于生成伪随机数!
⚠⚠⚠
为什么?
BufRng
对于将 libFuzzer 或 AFL 的原始输入字节重新解释为结构感知测试用例生成器(例如,quickcheck::Arbitrary
)的 RNG 很有用。这结合了覆盖率引导模糊测试与结构感知模糊测试的力量。
示例
假设我们正在开发一个可以将 RGB 和 HSL 颜色表示相互转换的 crate。
首先,我们可以为我们的颜色类型实现 quickcheck::Arbitrary
以获取结构感知测试用例生成器。然后,我们可以使用这些生成器与 quickcheck
自身的测试运行器基础设施一起使用,以断言代码的各种属性(例如,它永远不会崩溃,或者 RGB -> HSL -> RGB 是恒等函数),并且 quickcheck
将生成 Rgb
和 Hsl
的随机实例以检查此属性。
/// 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: Gen>(g: &mut G) -> Self {
Rgb {
r: g.gen(),
g: g.gen(),
b: g.gen(),
}
}
}
impl Arbitrary for Hsl {
fn arbitrary<G: Gen>(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
}
}
}
最后,我们可以 重用 现有的结构感知测试用例生成器(Arbitrary
实现)与 BufRng
一起使用 libFuzzer 或 AFL 输入。因此,我们可以利用覆盖率引导模糊测试——模糊测试器在测试运行时观察代码覆盖率,并尝试最大化输入覆盖的路径——以及我们现有的结构感知生成器。
以下片段使用 cargo fuzz
和 libFuzzer,但概念同样适用于 AFL 等。
// 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);
});
依赖项
~61KB