Skip to content

Commit 612b388

Browse files
authored
Fuzzing (#3, #4)
- fix panic on escaping character with width more than 1 byte - organize fuzzing targets in a `cucumber-expressions-fuzz` sub-crate - add `fuzz` command to `Makefile` - add `fuzz` job to CI pipeline
1 parent 9cb8206 commit 612b388

File tree

13 files changed

+147
-12
lines changed

13 files changed

+147
-12
lines changed

.github/workflows/ci.yml

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,40 @@ jobs:
7979

8080
- run: cargo +nightly update -Z minimal-versions
8181

82-
- run: cargo check --no-default-features
82+
- run: cargo check -p cucumber-expressions --no-default-features
8383
${{ matrix.feature != '<none>'
8484
&& format('--features {0}', matrix.feature)
8585
|| '' }}
8686
env:
8787
RUSTFLAGS: -D warnings
8888

89+
fuzz:
90+
name: Fuzzing
91+
if: ${{ github.ref == 'refs/heads/main'
92+
|| startsWith(github.ref, 'refs/tags/v')
93+
|| !contains(github.event.head_commit.message, '[skip ci]') }}
94+
strategy:
95+
fail-fast: false
96+
matrix:
97+
target:
98+
- alternation
99+
- expression
100+
- into-regex
101+
- optional
102+
- parameter
103+
runs-on: ubuntu-latest
104+
steps:
105+
- uses: actions/checkout@v2
106+
- uses: actions-rs/toolchain@v1
107+
with:
108+
profile: minimal
109+
toolchain: nightly
110+
111+
- run: cargo install cargo-fuzz
112+
113+
- name: Fuzz for 1 minute
114+
run: make cargo.fuzz target=${{ matrix.target }} time=60
115+
89116
msrv:
90117
name: MSRV
91118
if: ${{ github.ref == 'refs/heads/main'
@@ -144,7 +171,6 @@ jobs:
144171

145172

146173

147-
148174
#################
149175
# Documentation #
150176
#################

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ All user visible changes to `cucumber-expressions` crate will be documented in t
1313

1414
- [Cucumber Expressions] AST and parser. ([#1])
1515
- Expansion of [Cucumber Expressions] AST into [`Regex`] behind `into-regex` feature flag. ([#2])
16+
- Fuzzzing. ([#3])
1617

1718
[#1]: /../../pull/1
1819
[#2]: /../../pull/2
20+
[#3]: /../../pull/3
1921

2022

2123

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,6 @@ regex = { version = "1.5", optional = true }
3636

3737
# TODO: Remove once `derive_more` 0.99.17 is released.
3838
syn = "1.0.81"
39+
40+
[workspace]
41+
members = ["fuzz"]

Makefile

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ docs: cargo.doc
2222
fmt: cargo.fmt
2323

2424

25+
fuzz: cargo.fuzz
26+
27+
2528
lint: cargo.lint
2629

2730

@@ -44,7 +47,7 @@ cargo.doc:
4447
ifeq ($(clean),yes)
4548
@rm -rf target/doc/
4649
endif
47-
cargo doc --all-features \
50+
cargo doc -p cucumber-expressions --all-features \
4851
$(if $(call eq,$(private),no),,--document-private-items) \
4952
$(if $(call eq,$(open),no),,--open)
5053

@@ -55,7 +58,17 @@ endif
5558
# make cargo.fmt [check=(no|yes)]
5659

5760
cargo.fmt:
58-
cargo +nightly fmt $(if $(call eq,$(check),yes),-- --check,)
61+
cargo +nightly fmt --all $(if $(call eq,$(check),yes),-- --check,)
62+
63+
64+
# Fuzz Rust sources with cargo-fuzz.
65+
#
66+
# Usage:
67+
# make cargo.fuzz target=<fuzz-target> [time=<timeout>]
68+
69+
cargo.fuzz:
70+
cargo +nightly fuzz run $(target) \
71+
$(if $(call eq,$(time),),,-- -max_total_time=$(time))
5972

6073

6174
# Lint Rust sources with Clippy.
@@ -64,7 +77,7 @@ cargo.fmt:
6477
# make cargo.lint
6578

6679
cargo.lint:
67-
cargo clippy --all-features -- -D warnings
80+
cargo clippy -p cucumber-expressions --all-features -- -D warnings
6881

6982

7083
cargo.test: test.cargo
@@ -82,7 +95,7 @@ cargo.test: test.cargo
8295
# make test.cargo
8396

8497
test.cargo:
85-
cargo test --all-features
98+
cargo test -p cucumber-expressions --all-features
8699

87100

88101

@@ -91,6 +104,6 @@ test.cargo:
91104
# .PHONY section #
92105
##################
93106

94-
.PHONY: docs fmt lint test \
95-
cargo.doc cargo.fmt cargo.lint cargo.test \
107+
.PHONY: docs fmt fuzz lint test \
108+
cargo.doc cargo.fmt cargo.fuzz cargo.lint cargo.test \
96109
test.cargo

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ name-to-escape = '{' | '}' | '(' | '/' | '\'
7171

7272
## [`Regex`] Production Rules
7373

74-
Follows original [production rules].
74+
Follows original [production rules][2].
7575

7676

7777

fuzz/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/artifacts/
2+
/corpus/

fuzz/Cargo.toml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
[package]
2+
name = "cucumber-expressions-fuzz"
3+
version = "0.0.0"
4+
edition = "2021"
5+
rust-version = "1.56"
6+
description = "Fuzz testing for `cucumber-expressions` crate."
7+
license = "MIT OR Apache-2.0"
8+
authors = [
9+
"Ilya Solovyiov <ilya.solovyiov@gmail.com>",
10+
"Kai Ren <tyranron@gmail.com>",
11+
]
12+
publish = false
13+
14+
[package.metadata]
15+
cargo-fuzz = true
16+
17+
[dependencies]
18+
cucumber-expressions = { path = "..", features = ["into-regex"] }
19+
libfuzzer-sys = "0.4"
20+
21+
[[bin]]
22+
name = "expression"
23+
path = "fuzz_targets/expression.rs"
24+
test = false
25+
doc = false
26+
27+
[[bin]]
28+
name = "parameter"
29+
path = "fuzz_targets/parameter.rs"
30+
test = false
31+
doc = false
32+
33+
[[bin]]
34+
name = "optional"
35+
path = "fuzz_targets/optional.rs"
36+
test = false
37+
doc = false
38+
39+
[[bin]]
40+
name = "alternation"
41+
path = "fuzz_targets/alternation.rs"
42+
test = false
43+
doc = false
44+
45+
[[bin]]
46+
name = "into-regex"
47+
path = "fuzz_targets/into_regex.rs"
48+
test = false
49+
doc = false

fuzz/fuzz_targets/alternation.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![no_main]
2+
3+
use cucumber_expressions::parse;
4+
use libfuzzer_sys::fuzz_target;
5+
6+
fuzz_target!(|data: &str| {
7+
let _ = parse::alternation(data);
8+
});

fuzz/fuzz_targets/expression.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![no_main]
2+
3+
use cucumber_expressions::parse;
4+
use libfuzzer_sys::fuzz_target;
5+
6+
fuzz_target!(|data: &str| {
7+
let _ = parse::expression(data);
8+
});

fuzz/fuzz_targets/into_regex.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![no_main]
2+
3+
use cucumber_expressions::Expression;
4+
use libfuzzer_sys::fuzz_target;
5+
6+
fuzz_target!(|data: &str| {
7+
let _ = Expression::regex(data);
8+
});

0 commit comments

Comments
 (0)