Skip to content

Commit

Permalink
Merge pull request #182 from martinling/fuzzer
Browse files Browse the repository at this point in the history
Fuzzer
  • Loading branch information
miek committed Aug 29, 2024
2 parents 68e7dfb + 1050840 commit 7e14897
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 9 deletions.
18 changes: 18 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ serde = { version = "1.0.196", features = ["derive"] }
serde_json = "1.0.113"
rand = "0.8.5"
rand_xorshift = "0.3.0"
libfuzzer-sys = "0.4.7"

[target.'cfg(target_os = "macos")'.dev-dependencies]
procspawn = "1.0.0"
Expand Down Expand Up @@ -116,6 +117,26 @@ record-ui-test = ["serde", "serde_json"]
#
debug-region-map = []

# fuzzer:
#
# Used for fuzzing the decoder. Does not affect the main binary, but enables
# an example target named 'fuzzer'.
#
# Build the fuzzer with:
#
# cargo +nightly rustc --features fuzzer --example fuzzer -- \
# -C passes='sancov-module' \
# -C llvm-args='-sanitizer-coverage-level=3' \
# -C llvm-args='-sanitizer-coverage-inline-8bit-counters' \
# -Z sanitizer=address
#
# Run with:
#
# target/debug/examples/fuzzer
#
# Not currently working on Windows.
fuzzer = []

[[bin]]
name = "packetry"
path = "src/main.rs"
Expand All @@ -124,5 +145,10 @@ path = "src/main.rs"
name = "packetry-cli"
path = "src/cli.rs"

[[example]]
name = "fuzzer"
path = "src/fuzzer.rs"
required-features = ["fuzzer"]

[package.metadata.cargo-all-features]
skip_optional_dependencies = true
21 changes: 12 additions & 9 deletions src/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -598,10 +598,11 @@ impl Decoder {
let dev_addr = token.device_address();
let ep_num = token.endpoint_number();
let direction = match (ep_num.0, pid) {
(0, _) => Direction::Out,
(_, PID::IN) => Direction::In,
(_, PID::OUT) => Direction::Out,
(_, PID::PING) => Direction::Out,
(0, _) => Direction::Out,
(_, PID::SETUP) => Direction::Out,
(_, PID::IN) => Direction::In,
(_, PID::OUT) => Direction::Out,
(_, PID::PING) => Direction::Out,
_ => bail!("PID {pid} does not indicate a direction")
};
let key = EndpointKey {
Expand Down Expand Up @@ -682,11 +683,13 @@ impl Decoder {
use PID::*;
use TransactionStyle::*;
let transaction_id = self.capture.transaction_index.push(packet_id)?;
let (style, endpoint_id) = if pid == SPLIT {
let split = SplitFields::from_packet(packet);
(Split(split.sc(), split.endpoint_type(), None), None)
} else {
(Simple(pid), Some(self.packet_endpoint(pid, packet)?))
let (style, endpoint_id) = match pid {
Malformed => (Simple(pid), Some(INVALID_EP_ID)),
SPLIT => {
let split = SplitFields::from_packet(packet);
(Split(split.sc(), split.endpoint_type(), None), None)
},
pid => (Simple(pid), Some(self.packet_endpoint(pid, packet)?))
};
let mut state = TransactionState {
style,
Expand Down
37 changes: 37 additions & 0 deletions src/fuzzer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//! Fuzz the USB packet decoder.

#![allow(dead_code)]
#![no_main]

#[macro_use]
extern crate bitfield;

use libfuzzer_sys::{arbitrary::{Arbitrary, Unstructured}, fuzz_target};

mod capture;
mod compact_index;
mod data_stream;
mod decoder;
mod id;
mod index_stream;
mod pcap;
mod rcu;
mod stream;
mod usb;
mod util;
mod vec_map;

use capture::create_capture;
use decoder::Decoder;

fuzz_target!(|data: &[u8]| {
let mut input = Unstructured::new(data);
let packets = Vec::<(Vec::<u8>, u32)>::arbitrary(&mut input).unwrap();
let mut timestamp = u32::arbitrary(&mut input).unwrap() as u64;
let (writer, _reader) = create_capture().unwrap();
let mut decoder = Decoder::new(writer).unwrap();
for (packet, time_delta) in packets {
timestamp += time_delta as u64;
decoder.handle_raw_packet(&packet, timestamp).unwrap();
}
});
Binary file added tests/bad-crcs/capture.pcap
Binary file not shown.
13 changes: 13 additions & 0 deletions tests/bad-crcs/reference.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Polling 1 times for unidentified transfer on endpoint 7.1 IN
IN transaction on 7.1, NAK
IN packet on 7.1, CRC 1B
NAK packet
1 invalid groups
1 malformed packet
Malformed packet (possibly IN, but bad CRC) of 3 bytes: [69, B7, DB]
1 invalid groups
1 malformed packet
Malformed packet (possibly IN, but bad CRC) of 3 bytes: [69, B7, DB]
1 invalid groups
1 malformed packet
Malformed packet (possibly SOF, but bad CRC) of 3 bytes: [A5, BB, CE]
1 change: 1 addition & 0 deletions tests/tests.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
analyzer-test-bad-cable
bad-crcs
emf2022-badge
hackrf-connect
hackrf-dfu-enum
Expand Down

0 comments on commit 7e14897

Please sign in to comment.