Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: basic fuzzing #407

Merged
merged 13 commits into from
Aug 9, 2024
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@
/book/book
**/*.rs.bk
Cargo.lock

# ignore output fuzzing
out
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["logos-cli", "logos-codegen", "logos-derive", "tests"]
members = ["logos-cli", "logos-codegen", "logos-derive", "tests", "fuzz"]
resolver = "2"

[workspace.package]
Expand All @@ -12,7 +12,7 @@ keywords = ["lexer", "lexical", "tokenizer", "parser", "no_std"]
license = "MIT OR Apache-2.0"
readme = "README.md"
repository = "https://github.com/maciejhirsz/logos"
rust-version = "1.65.0"
rust-version = "1.70.0"
version = "0.14.1"

[package]
Expand All @@ -30,7 +30,7 @@ rust-version.workspace = true
version.workspace = true

[package.metadata]
msrv = "1.65.0" # Needed to duplicate, because cargo-msrv does not support workspace
msrv = "1.70.0" # Needed to duplicate, because cargo-msrv does not support workspace

[package.metadata.release]
pre-release-replacements = [
Expand Down
1 change: 1 addition & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@
+ [Contributing](./contributing.md)
+ [Setup](./contributing/setup.md)
+ [Internals](./contributing/internals.md)
+ [Fuzzing](./contributing/fuzzing.md)
51 changes: 51 additions & 0 deletions book/src/contributing/fuzzing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Fuzzing


Fuzzing is a technique to test a piece of software by injecting randomly generated inputs. This can be pretty useful to discover bugs, as pointed out in [#407](https://github.com/maciejhirsz/logos/pull/407).

**Logos**' fuzzing crate is powered by [afl.rs](https://github.com/rust-fuzz/afl.rs) that
finds panics in **Logos**' methods.

## Usage

First, make sure you have `cargo-afl` installed,
[see the rust-fuzz afl setup guide for installation information](https://rust-fuzz.github.io/book/afl/setup.html).

Next, change your current working directory to be the `fuzz` folder.

### Building

Before fuzzing, you need to build the target with:

```bash
cargo afl build
```

### Fuzzy testing

The recommended way the run tests is with:

```bash
cargo afl fuzz -i in -o out ../target/debug/logos-fuzz
```

Note that it may run for a (very) long time before
it encounter any bug.

## Replaying a Crash

If you happen to find a bug that crashes the program,
you can reply it with

```bash
cargo afl run logos-fuzz < out/default/crashes/crash_file
```

### Reporting a Bug

If you encounter a crash and you feel the error message
is not appropriate,
please report it by opening
[an issue](https://github.com/maciejhirsz/logos/issues/new).
Don't forget to include your crash file so we can later
reproduce it.
3 changes: 3 additions & 0 deletions book/src/contributing/internals.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@
and usage help can be obtained through the `logos-cli --help` command.
This tool can be useful if your tokens definition stays is constant, and
you want to reduce compilatio time overhead caused by derive macros.
+ `logos-fuzz` is an internal crate that uses [afl.rs](https://github.com/rust-fuzz/afl.rs)
to find confusing panics before they reach the developer.
To use this tool, see the [Fuzzing guide]('./fuzzing.md')
22 changes: 22 additions & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
name = "logos-fuzz"
authors.workspace = true
categories.workspace = true
description.workspace = true
edition.workspace = true
homepage.workspace = true
keywords.workspace = true
license.workspace = true
readme.workspace = true
repository.workspace = true
rust-version.workspace = true
version.workspace = true
publish = false

[dependencies]
afl = "0.15"
arbitrary = "1.3"
logos-codegen = { path = "../logos-codegen", features = ["fuzzing"] }

[package.metadata.release]
shared-version = true
1 change: 1 addition & 0 deletions fuzz/in/literal
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
literal
1 change: 1 addition & 0 deletions fuzz/in/regex
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a+b[cd-h]+?
16 changes: 16 additions & 0 deletions fuzz/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use afl::fuzz;
use logos_codegen::{
graph::{Graph, Node},
mir::Mir,
};

fn main() {
fuzz!(|regex: String| {
let mut graph = Graph::new();

if let Ok(mir) = Mir::utf8(&regex) {
let leaf = graph.push(Node::Leaf("LEAF"));
let _ = graph.regex(mir, leaf);
}
});
}
2 changes: 2 additions & 0 deletions logos-codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ rstest = "0.18.2"
[features]
# Enables debug messages
debug = []
# Exports out internal methods for fuzzing
fuzzing = []

[lib]
bench = false
Expand Down
6 changes: 6 additions & 0 deletions logos-codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,15 @@

mod error;
mod generator;
#[cfg(not(feature = "fuzzing"))]
mod graph;
#[cfg(feature = "fuzzing")]
pub mod graph;
mod leaf;
#[cfg(not(feature = "fuzzing"))]
mod mir;
#[cfg(feature = "fuzzing")]
pub mod mir;
mod parser;
mod util;

Expand Down
Loading