use criterion::{BenchmarkId, Criterion, black_box, criterion_group, criterion_main};
use wafrift_encoding::encoding::{encode_layered, strategy::Strategy};
const SQL_PAYLOAD: &str = "' OR 1=1 UNION SELECT NULL,NULL,NULL--";
const XSS_PAYLOAD: &str = "<script>alert(document.cookie)</script>";
const LONG_SPACED: &str = "SELECT id, username, password FROM users WHERE username='admin' OR 1=1 \
UNION SELECT table_name, column_name, NULL FROM information_schema.columns--";
const UNRESERVED_PAYLOAD: &str = "username=admin&password=letmein123";
fn bench_url_encode(c: &mut Criterion) {
let mut group = c.benchmark_group("url_encode");
let cases: &[(&str, &str)] = &[
("sql_40b", SQL_PAYLOAD),
("xss_50b", XSS_PAYLOAD),
("long_200b", LONG_SPACED),
("unreserved_30b", UNRESERVED_PAYLOAD),
];
for (name, payload) in cases {
group.bench_with_input(BenchmarkId::new("encode", name), payload, |b, p| {
b.iter(|| {
let r = wafrift_encoding::encoding::strategy::encode(
black_box(p.as_bytes()),
black_box(Strategy::UrlEncode),
);
black_box(r)
});
});
group.bench_with_input(BenchmarkId::new("encode_lower", name), payload, |b, p| {
b.iter(|| {
let r = wafrift_encoding::encoding::strategy::encode(
black_box(p.as_bytes()),
black_box(Strategy::UrlEncodeLower),
);
black_box(r)
});
});
group.bench_with_input(BenchmarkId::new("double_encode", name), payload, |b, p| {
b.iter(|| {
let r = wafrift_encoding::encoding::strategy::encode(
black_box(p.as_bytes()),
black_box(Strategy::DoubleUrlEncode),
);
black_box(r)
});
});
}
group.finish();
}
fn bench_case_alternation(c: &mut Criterion) {
let mut group = c.benchmark_group("case_alternation");
for (name, payload) in &[("sql_40b", SQL_PAYLOAD), ("long_200b", LONG_SPACED)] {
group.bench_with_input(BenchmarkId::new("case_alternate", name), payload, |b, p| {
b.iter(|| {
let r = wafrift_encoding::encoding::strategy::encode(
black_box(p.as_bytes()),
black_box(Strategy::CaseAlternation),
);
black_box(r)
});
});
group.bench_with_input(BenchmarkId::new("random_case", name), payload, |b, p| {
b.iter(|| {
let r = wafrift_encoding::encoding::strategy::encode(
black_box(p.as_bytes()),
black_box(Strategy::RandomCase),
);
black_box(r)
});
});
}
group.finish();
}
fn bench_space_replacement(c: &mut Criterion) {
let mut group = c.benchmark_group("space_replacement");
for (name, payload) in &[("sql_40b", SQL_PAYLOAD), ("long_200b", LONG_SPACED)] {
group.bench_with_input(
BenchmarkId::new("space_to_comment", name),
payload,
|b, p| {
b.iter(|| {
let r = wafrift_encoding::encoding::strategy::encode(
black_box(p.as_bytes()),
black_box(Strategy::SpaceToComment),
);
black_box(r)
});
},
);
group.bench_with_input(
BenchmarkId::new("space_to_random_blank", name),
payload,
|b, p| {
b.iter(|| {
let r = wafrift_encoding::encoding::strategy::encode(
black_box(p.as_bytes()),
black_box(Strategy::SpaceToRandomBlank),
);
black_box(r)
});
},
);
}
group.finish();
}
fn bench_encode_layered(c: &mut Criterion) {
let mut group = c.benchmark_group("encode_layered");
let chains: &[(&str, &[Strategy])] = &[
(
"url_case",
&[Strategy::UrlEncode, Strategy::CaseAlternation],
),
(
"case_url",
&[Strategy::CaseAlternation, Strategy::UrlEncode],
),
(
"case_space_url",
&[
Strategy::CaseAlternation,
Strategy::SpaceToComment,
Strategy::UrlEncode,
],
),
(
"url_double_url",
&[Strategy::UrlEncode, Strategy::DoubleUrlEncode],
),
];
for (chain_name, chain) in chains {
group.bench_with_input(
BenchmarkId::new("sql_40b", chain_name),
&(SQL_PAYLOAD, *chain),
|b, (payload, chain)| {
b.iter(|| {
let r = encode_layered(black_box(payload.as_bytes()), black_box(chain));
black_box(r)
});
},
);
group.bench_with_input(
BenchmarkId::new("long_200b", chain_name),
&(LONG_SPACED, *chain),
|b, (payload, chain)| {
b.iter(|| {
let r = encode_layered(black_box(payload.as_bytes()), black_box(chain));
black_box(r)
});
},
);
}
group.finish();
}
criterion_group!(
benches,
bench_url_encode,
bench_case_alternation,
bench_space_replacement,
bench_encode_layered,
);
criterion_main!(benches);