p6: add untrusted-input pipeline fuzz target
swadhinbiswas committed 3 months ago
98a4821
1 parent f85aaeb
commit 98a4821
3 files changed
+66 -0
Showing 3 changed files+66-0
▼fuzz/Cargo.lock
+12-0
| @@ -1702,6 +1702,7 @@ dependencies = [ | ||
1702 | 1702 | "arc-swap", |
1703 | 1703 | "async-graphql", |
1704 | 1704 | "async-trait", |
1705 | + "base64", | |
1705 | 1706 | "bytes", |
1706 | 1707 | "flate2", |
1707 | 1708 | "futures", |
| @@ -1722,6 +1723,7 @@ dependencies = [ | ||
1722 | 1723 | "opentelemetry-stdout", |
1723 | 1724 | "opentelemetry_sdk", |
1724 | 1725 | "prost 0.14.4", |
1726 | + "quick-xml", | |
1725 | 1727 | "rand 0.8.6", |
1726 | 1728 | "redis", |
1727 | 1729 | "serde", |
| @@ -2504,6 +2506,16 @@ dependencies = [ | ||
2504 | 2506 | "winapi", |
2505 | 2507 | ] |
2506 | 2508 | |
2509 | +[[package]] | |
2510 | +name = "quick-xml" | |
2511 | +version = "0.36.2" | |
2512 | +source = "registry+https://github.com/rust-lang/crates.io-index" | |
2513 | +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" | |
2514 | +dependencies = [ | |
2515 | + "memchr", | |
2516 | + "serde", | |
2517 | +] | |
2518 | + | |
2507 | 2519 | [[package]] |
2508 | 2520 | name = "quote" |
2509 | 2521 | version = "1.0.46" |
2510 | 2522 | |
▼fuzz/Cargo.toml
+8-0
| @@ -65,3 +65,11 @@ path = "fuzz_targets/fuzz_jwt.rs" | ||
65 | 65 | test = false |
66 | 66 | doc = false |
67 | 67 | bench = false |
68 | + | |
69 | +[[bin]] | |
70 | +name = "fuzz_pipeline" | |
71 | +path = "fuzz_targets/fuzz_pipeline.rs" | |
72 | +test = false | |
73 | +doc = false | |
74 | +bench = false | |
75 | + | |
68 | 76 | |
▼fuzz/fuzz_targets/fuzz_pipeline.rs
+46-0
| @@ -0,0 +1,46 @@ | ||
1 | +#![no_main] | |
2 | + | |
3 | +use libfuzzer_sys::fuzz_target; | |
4 | + | |
5 | +fuzz_target!(|data: &[u8]| { | |
6 | + if data.len() < 2 { | |
7 | + return; | |
8 | + } | |
9 | + | |
10 | + // 1. Fuzz JSON Schema validation with arbitrary input bytes | |
11 | + let schema = r#"{ | |
12 | + "type": "object", | |
13 | + "properties": { | |
14 | + "name": {"type": "string", "minLength": 1, "maxLength": 100}, | |
15 | + "age": {"type": "integer", "minimum": 0, "maximum": 150}, | |
16 | + "email": {"type": "string", "format": "email"}, | |
17 | + "website": {"type": "string", "format": "uri"}, | |
18 | + "id": {"type": "string", "format": "uuid"}, | |
19 | + "tags": {"type": "array", "items": {"type": "string"}} | |
20 | + }, | |
21 | + "required": ["name"] | |
22 | + }"#; | |
23 | + | |
24 | + let _ = justapi_core::validate::validate_json_schema(data, schema); | |
25 | + | |
26 | + // 2. Fuzz precompiled validator execution | |
27 | + if let Ok(compiled) = justapi_core::validate::compile_schema(schema) { | |
28 | + let _ = compiled.validate(data); | |
29 | + } | |
30 | + | |
31 | + // 3. Fuzz query string parsing | |
32 | + if let Ok(s) = std::str::from_utf8(data) { | |
33 | + let _ = justapi_core::validate::parse_query::<serde_json::Value>(s); | |
34 | + } | |
35 | + | |
36 | + // 4. Fuzz route matching with dynamic paths | |
37 | + use http::Method; | |
38 | + let mut router = justapi_core::router::Router::<usize>::new(); | |
39 | + let _ = router.insert(Method::GET, "/users/{id}", 1); | |
40 | + let _ = router.insert(Method::POST, "/api/v1/{*rest}", 2); | |
41 | + | |
42 | + if let Ok(path) = std::str::from_utf8(data) { | |
43 | + let _ = router.at(&Method::GET, path); | |
44 | + let _ = router.at(&Method::POST, path); | |
45 | + } | |
46 | +}); | |
0 | 47 | |