Rust模糊测试库fuzzt的使用,fuzzt提供高效灵活的模糊测试工具以增强代码安全性
Rust模糊测试库fuzzt的使用,fuzzt提供高效灵活的模糊测试工具以增强代码安全性
Fuzzt是一个Rust实现的字符串相似度度量库,提供多种算法来计算字符串之间的相似度。这些算法可以帮助开发者进行模糊测试,增强代码的安全性。
主要功能
Fuzzt实现了以下字符串相似度度量算法:
- Hamming
- Levenshtein (距离和归一化版本)
- Optimal string alignment
- Damerau-Levenshtein (距离和归一化版本)
- Jaro和Jaro-Winkler
- Sørensen-Dice
- Gestalt pattern matching
归一化版本返回0.0到1.0之间的值,其中1.0表示完全匹配。
新增功能
Fuzzt基于strsim-rs库,并添加了以下新功能:
- Gestalt pattern matching:Python difflib SequenceMatcher使用的算法
- Top-N matching:从选择集合中检索最佳N个匹配的方法
- Feature selection:允许选择仅需要的功能(度量),减少应用程序的内存占用
Top-N Matching
get_top_n
方法从选择字符串集合中获取最佳匹配列表。这个方法受到Python fuzzywuzzy包(现在称为thefuzz)中extractBests
方法的启发。
以下是get_top_n
方法的示例:
extern crate fuzzt;
use fuzzt::{algorithms::NormalizedLevenshtein, get_top_n, processors::NullStringProcessor};
fn main() {
let matches = get_top_n(
"apple",
&["apply", "apples", "ape", "applet", "applesauce"],
Some(0.8),
Some(3),
Some(&NullStringProcessor),
Some(&NormalizedLevenshtein),
);
assert_eq!(matches, ["apples", "applet", "apply"]);
}
功能选择
Fuzzt设计灵活,允许根据需要选择特定功能,有助于减少应用程序的占用空间并优化性能。
库包含以下功能:
- damerau_levenshtein
- gestalt
- hamming
- jaro
- levenshtein
- optimal_string_alignment
- sorensen_dice
默认情况下,所有功能都包含在内。但可以通过在Cargo.toml中指定所需功能来选择:
[dependencies]
fuzzt = { version = "*", default-features = false, features = ["levenshtein", "jaro"] }
安装
将Fuzzt添加到项目中:
cargo add fuzzt
使用示例
extern crate fuzzt;
use fuzzt::{
damerau_levenshtein, hamming, jaro, jaro_winkler, levenshtein, normalized_damerau_levenshtein,
normalized_levenshtein, osa_distance, sequence_matcher, sorensen_dice,
};
fn main() {
match hamming("hamming", "hammers") {
Ok(distance) => assert_eq!(3, distance),
Err(why) => panic!("{:?}", why),
}
assert_eq!(levenshtein("kitten", "sitting"), 3);
assert!((normalized_levenshtein("kitten", "sitting") - 0.571).abs() < 0.001);
assert_eq!(osa_distance("ac", "cba"), 3);
assert_eq!(damerau_levenshtein("ac", "cba"), 2);
assert!((normalized_damerau_levenshtein("levenshtein", "löwenbräu") - 0.272).abs() < 0.001);
assert_eq!(jaro("Friedrich Nietzsche", "Jean-Paul Sartre"), 0.3918859649122807);
assert_eq!(
jaro_winkler("cheeseburger", "cheese fries"),
0.8666666666666666
);
assert_eq!(
sorensen_dice("web applications", "applications of the web"),
0.7878787878787878
);
assert_eq!(
sequence_matcher("this is a test", "this is a test!"),
0.965517241
1 回复
Rust模糊测试库fuzzt使用指南
介绍
fuzzt是一个Rust语言的模糊测试库,它提供了高效且灵活的模糊测试工具,帮助开发者发现代码中的潜在安全问题。fuzzt通过生成大量随机输入来测试程序的边界条件,特别适合用于测试解析器、协议实现和其他输入处理相关的代码。
主要特性
- 高效的输入生成和变异策略
- 支持结构化模糊测试
- 可定制的测试策略
- 与Rust测试框架良好集成
- 提供崩溃重现功能
完整示例
下面是一个完整的fuzzt使用示例,展示了从基本使用到结构化测试的全过程:
use fuzzt::{FuzzMutator, FuzzRunner, FuzzStrategy, StructuredFuzz};
use rand::Rng;
// 1. 基本使用示例
fn basic_fuzzing_example() {
fn test_input_parser(input: &[u8]) {
// 测试输入解析器
if input.len() > 5 && input[0] == b'A' && input[1] == b'B' && input[2] == b'C' {
panic!("Detected vulnerable input pattern");
}
}
let mut runner = FuzzRunner::new(test_input_parser);
runner.set_max_len(512); // 限制输入最大长度
match runner.fuzz(5000) {
Some(crash_input) => println!("Crash found with input: {:?}", crash_input),
None => println!("No crashes detected in basic test"),
}
}
// 2. 结构化模糊测试示例
#[derive(Clone, Debug)]
struct HttpRequest {
method: String,
path: String,
headers: Vec<(String, String)>,
body: Vec<u8>,
}
impl StructuredFuzz for HttpRequest {
fn fuzz(&mut self, mutator: &mut FuzzMutator) {
mutator.fuzz(&mut self.method);
mutator.fuzz(&mut self.path);
mutator.fuzz(&mut self.headers);
mutator.fuzz(&mut self.body);
}
}
fn structured_fuzzing_example() {
fn test_http_handler(request: &HttpRequest) {
// 测试HTTP请求处理器
if request.method == "GET" && request.path.contains("../") {
panic!("Potential path traversal attack detected");
}
if request.headers.iter().any(|(k, v)| k.len() > 1024 || v.len() > 8192) {
panic!("Oversized header detected");
}
}
let initial = HttpRequest {
method: "GET".to_string(),
path: "/".to_string(),
headers: vec![("Host".to_string(), "localhost".to_string())],
body: vec![],
};
let mut runner = FuzzRunner::new(test_http_handler)
.with_structured_input(initial);
runner.fuzz(3000);
}
// 3. 自定义变异策略示例
struct ByteFlipStrategy;
impl FuzzStrategy for ByteFlipStrategy {
fn mutate(&self, data: &mut Vec<u8>, mutator: &mut FuzzMutator) {
// 随机翻转字节中的位
if !data.is_empty() {
let index = mutator.rng.gen_range(0..data.len());
let bit = mutator.rng.gen_range(0..8);
data[index] ^= 1 << bit;
}
}
}
fn custom_strategy_example() {
fn test_buffer_overflow(input: &[u8]) {
// 测试缓冲区处理
if input.len() > 128 {
panic!("Potential buffer overflow detected");
}
}
let mut runner = FuzzRunner::new(test_buffer_overflow)
.with_strategy(ByteFlipStrategy);
runner.fuzz(2000);
}
// 4. 集成测试示例
#[cfg(test)]
mod integration_tests {
use super::*;
#[test]
fn fuzz_json_parser() {
let mut runner = FuzzRunner::new(|data| {
// 简单模拟JSON解析器测试
if data.starts_with(b"{") && data.ends_with(b"}") {
if data.len() > 1000 {
panic!("Oversized JSON input");
}
// 模拟检查JSON深度
let depth = data.iter().filter(|&&b| b == b'{' || b == b'}').count();
if depth > 20 {
panic!("Excessive JSON nesting depth");
}
}
});
assert!(runner.fuzz(1000).is_none(), "Found crashing JSON input");
}
}
fn main() {
println!("Running basic fuzzing example...");
basic_fuzzing_example();
println!("\nRunning structured fuzzing example...");
structured_fuzzing_example();
println!("\nRunning custom strategy example...");
custom_strategy_example();
println!("\nAll fuzzing examples completed!");
}
最佳实践
- 从简单输入开始:初始使用小的、简单的输入样本
- 逐步增加复杂性:随着测试进展增加输入大小和复杂度
- 关注代码覆盖率:确保模糊测试能覆盖大部分代码路径
- 重现崩溃:保存导致崩溃的输入以便调试
- 持续运行:将模糊测试集成到CI/CD流程中
这个完整示例展示了fuzzt的主要功能,包括基本使用、结构化测试、自定义变异策略和测试集成。你可以根据实际需求调整和扩展这些示例。