index : static-web-server.git

ascending towards madness

author Jose Quintana <1700322+joseluisq@users.noreply.github.com> 2024-02-09 5:53:38.0 +00:00:00
committer GitHub <noreply@github.com> 2024-02-09 5:53:38.0 +00:00:00
commit
370d2888b6294cf433f30b9fa59ff2d7dea654cc [patch]
tree
33b3bf416f23d7da6e2b1cea4351f299e3235c7f
parent
80af0aa34f12f5eabf939bd4072d5a2d78d770d7
download
370d2888b6294cf433f30b9fa59ff2d7dea654cc.tar.gz

chore: base fuzz and micro-benchmark testing for static files module (#310)

it just introduces fuzzing and micro-benchmark tests for the static files module. As a way to continue enhancing the performance and security of SWS in general. It is expected to be improved over time including other modules as well.

Diff

 benches/Cargo.toml       |  5 +++++
 benches/static_files.rs  | 29 +++++++++++++++++++++++++++++
 fuzz/.gitignore          |  6 ++++++
 fuzz/Cargo.toml          | 22 ++++++++++++++++++++++
 fuzz/src/static_files.rs | 17 +++++++++++++++++
 src/static_files.rs      | 12 ++++++++++++
 6 files changed, 91 insertions(+)

diff --git a/benches/Cargo.toml b/benches/Cargo.toml
index a2d0406..69ac104 100644
--- a/benches/Cargo.toml
+++ b/benches/Cargo.toml
@@ -13,3 +13,8 @@ hyper = { version = "0.14", features = ["stream", "http1", "http2", "tcp", "serv
name = "control_headers"
path = "control_headers.rs"
harness = false

[[bench]]
name = "static_files"
path = "static_files.rs"
harness = false
diff --git a/benches/static_files.rs b/benches/static_files.rs
new file mode 100644
index 0000000..12f1897
--- /dev/null
+++ b/benches/static_files.rs
@@ -0,0 +1,29 @@
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};

use static_web_server::static_files;

#[derive(Debug)]
struct Inputs<'a> {
    base_path: &'a std::path::Path,
    uri_path: &'a str,
}
impl std::fmt::Display for Inputs<'_> {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
        write!(fmt, "{:?}", self)
    }
}

fn sanitize_path_benchmark(c: &mut Criterion) {
    let base_path = std::path::Path::new("root/../");
    let uri_path: &str = "../assets/../../.../image.jpg";
    let inputs = Inputs {
        base_path,
        uri_path,
    };
    c.bench_with_input(BenchmarkId::new("path_inputs", &inputs), &inputs, |b, s| {
        b.iter(|| static_files::sanitize_path(s.base_path, s.uri_path))
    });
}

criterion_group!(static_files_bench, sanitize_path_benchmark);
criterion_main!(static_files_bench);
diff --git a/fuzz/.gitignore b/fuzz/.gitignore
new file mode 100644
index 0000000..e7c4f16
--- /dev/null
+++ b/fuzz/.gitignore
@@ -0,0 +1,6 @@
target
corpus
artifacts
coverage
Cargo.lock
crash*
diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml
new file mode 100644
index 0000000..6b6bab9
--- /dev/null
+++ b/fuzz/Cargo.toml
@@ -0,0 +1,22 @@
[package]
name = "static-web-server-fuzz"
version = "0.0.0"
publish = false
edition = "2021"
rust-version = "1.70.0"

[package.metadata]
cargo-fuzz = true

[dependencies]
arbitrary = { version = "1",  features = ["derive"] }
libfuzzer-sys = { version = "0.4", features = ["arbitrary-derive"] }
static-web-server = { path = ".." }
hyper = { version = "0.14", features = ["stream", "http1", "http2", "tcp", "server"] }

[profile.release]
debug = 1

[[bin]]
name = "static_files"
path = "src/static_files.rs"
diff --git a/fuzz/src/static_files.rs b/fuzz/src/static_files.rs
new file mode 100644
index 0000000..3a80a95
--- /dev/null
+++ b/fuzz/src/static_files.rs
@@ -0,0 +1,17 @@
#![no_main]

use libfuzzer_sys::arbitrary::Arbitrary;
use libfuzzer_sys::fuzz_target;
use static_web_server::static_files;

#[derive(Debug, Arbitrary)]
struct RequestPath {
    base: Vec<u8>,
    uri: Vec<u8>,
}

fuzz_target!(|input: RequestPath| {
    let uri = unsafe { std::str::from_utf8_unchecked(&input.uri[..]) };
    let base = unsafe { std::str::from_utf8_unchecked(&input.base[..]) };
    let _ = static_files::sanitize_path(std::path::Path::new(base), uri);
});
diff --git a/src/static_files.rs b/src/static_files.rs
index 82423a7..10fa84f 100644
--- a/src/static_files.rs
+++ b/src/static_files.rs
@@ -751,6 +751,18 @@ mod tests {
            sanitize_path(base_dir, "/../foo.html").unwrap(),
            root_dir().join("foo.html"),
        );
        assert_eq!(
            sanitize_path(base_dir, "/../W�foo.html").unwrap(),
            root_dir().join("W�foo.html"),
        );
        assert_eq!(
            sanitize_path(base_dir, "/%EF%BF%BD/../bar.html").unwrap(),
            root_dir().join("�/bar.html"),
        );
        assert_eq!(
            sanitize_path(base_dir, "àí/é%20/öüñ").unwrap(),
            root_dir().join("àí/é /öüñ"),
        );

        #[cfg(unix)]
        let expected_path = root_dir().join("C:\\/foo.html");