Skip to content

Commit 56679d8

Browse files
authored
Merge pull request #68 from pascalkuthe/better_fuzzing
Add a second fuzzer that uses a smaller internal chunk size for the Rope to help catch certain issues more easily.
2 parents 8947f9a + 9be20bf commit 56679d8

File tree

4 files changed

+79
-4
lines changed

4 files changed

+79
-4
lines changed

Cargo.toml

+5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ cr_lines = [] # Enable recognizing carriage returns as line breaks.
1717
unicode_lines = ["cr_lines"] # Enable recognizing all Unicode line breaks.
1818
simd = ["str_indices/simd"]
1919

20+
# Internal feature: Not part of public stable API
21+
# enables a much smaller chunk size that makes it
22+
# easier to catch bugs without requiring huge text sizes during fuzzing.
23+
small_chunks = []
24+
2025
[dependencies]
2126
smallvec = "1.0.0"
2227
str_indices = { version = "0.4.0", default-features = false }

fuzz/Cargo.toml

+11
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,23 @@ libfuzzer-sys = { version = "0.4", features = ["arbitrary-derive"] }
1515
[dependencies.ropey]
1616
path = ".."
1717

18+
[features]
19+
small_chunks = ["ropey/small_chunks"]
20+
1821
# Prevent this from interfering with workspaces
1922
[workspace]
2023
members = ["."]
2124

25+
2226
[[bin]]
2327
name = "mutation"
2428
path = "fuzz_targets/mutation.rs"
2529
test = false
2630
doc = false
31+
32+
[[bin]]
33+
name = "mutation_small_chunks"
34+
path = "fuzz_targets/mutation_small_chunks.rs"
35+
test = false
36+
doc = false
37+
required-features = ["small_chunks"]
+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#![no_main]
2+
3+
use libfuzzer_sys::{
4+
arbitrary::{self, Arbitrary},
5+
fuzz_target,
6+
};
7+
use ropey::Rope;
8+
9+
const SMALL_TEXT: &str = include_str!("small.txt");
10+
11+
#[derive(Arbitrary, Copy, Clone, Debug)]
12+
enum Op<'a> {
13+
Insert(usize, &'a str),
14+
InsertChar(usize, char),
15+
Remove(usize, usize),
16+
SplitOff(usize, bool),
17+
Append(&'a str),
18+
}
19+
20+
#[derive(Arbitrary, Copy, Clone, Debug)]
21+
enum StartingText<'a> {
22+
Small,
23+
Custom(&'a str),
24+
}
25+
26+
fuzz_target!(|data: (StartingText, Vec<Op>)| {
27+
let mut r = Rope::from_str(match data.0 {
28+
StartingText::Small => SMALL_TEXT,
29+
StartingText::Custom(s) => s,
30+
});
31+
32+
for op in data.1 {
33+
match op {
34+
Op::Insert(idx, s) => {
35+
let _ = r.try_insert(idx, s);
36+
}
37+
Op::InsertChar(idx, c) => {
38+
let _ = r.try_insert_char(idx, c);
39+
}
40+
Op::Remove(idx_1, idx_2) => {
41+
let _ = r.try_remove(idx_1..idx_2);
42+
}
43+
Op::SplitOff(idx, keep_right) => match r.try_split_off(idx) {
44+
Ok(right) => {
45+
if keep_right {
46+
r = right;
47+
}
48+
}
49+
Err(_) => {}
50+
},
51+
Op::Append(s) => {
52+
r.append(Rope::from_str(s));
53+
}
54+
}
55+
}
56+
57+
r.assert_integrity();
58+
r.assert_invariants();
59+
});

src/tree/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub(crate) use self::text_info::TextInfo;
1212
pub(crate) type Count = u64;
1313

1414
// Real constants used in release builds.
15-
#[cfg(not(test))]
15+
#[cfg(not(any(test, feature = "small_chunks")))]
1616
mod constants {
1717
use super::{Node, TextInfo};
1818
use smallvec::SmallVec;
@@ -90,7 +90,7 @@ mod constants {
9090
// Smaller constants used in debug builds. These are different from release
9191
// in order to trigger deeper trees without having to use huge text data in
9292
// the tests.
93-
#[cfg(test)]
93+
#[cfg(any(test, feature = "small_chunks"))]
9494
mod test_constants {
9595
pub(crate) const MAX_CHILDREN: usize = 5;
9696
pub(crate) const MIN_CHILDREN: usize = MAX_CHILDREN / 2;
@@ -100,8 +100,8 @@ mod test_constants {
100100
pub(crate) const MIN_BYTES: usize = (MAX_BYTES / 2) - (MAX_BYTES / 32);
101101
}
102102

103-
#[cfg(not(test))]
103+
#[cfg(not(any(test, feature = "small_chunks")))]
104104
pub(crate) use self::constants::{MAX_BYTES, MAX_CHILDREN, MIN_BYTES, MIN_CHILDREN};
105105

106-
#[cfg(test)]
106+
#[cfg(any(test, feature = "small_chunks"))]
107107
pub(crate) use self::test_constants::{MAX_BYTES, MAX_CHILDREN, MIN_BYTES, MIN_CHILDREN};

0 commit comments

Comments
 (0)