Skip to content

Commit 2bb4986

Browse files
authored
Auto merge of servo#284 - servo:fuzzing, r=BorisChiou
Add fuzzing support.
2 parents 0212922 + d2dc268 commit 2bb4986

File tree

5 files changed

+394
-0
lines changed

5 files changed

+394
-0
lines changed

fuzz/.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
target
3+
corpus
4+
artifacts

fuzz/Cargo.lock

+266
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

fuzz/Cargo.toml

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
2+
[package]
3+
name = "cssparser-fuzz"
4+
version = "0.0.0"
5+
authors = ["Automatically generated"]
6+
publish = false
7+
edition = "2018"
8+
9+
[package.metadata]
10+
cargo-fuzz = true
11+
12+
[dependencies]
13+
libfuzzer-sys = "0.4"
14+
15+
[dependencies.cssparser]
16+
path = ".."
17+
18+
# Prevent this from interfering with workspaces
19+
[workspace]
20+
members = ["."]
21+
22+
[[bin]]
23+
name = "cssparser"
24+
path = "fuzz_targets/cssparser.rs"
25+
test = false
26+
doc = false

fuzz/fuzz_targets/cssparser.rs

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#![no_main]
2+
3+
use cssparser::*;
4+
5+
const DEBUG: bool = false;
6+
7+
fn parse_and_serialize(input: &str, preserving_comments: bool) -> String {
8+
let mut input = ParserInput::new(input);
9+
let mut parser = Parser::new(&mut input);
10+
let mut serialization = String::new();
11+
let result = do_parse_and_serialize(
12+
&mut parser,
13+
preserving_comments,
14+
TokenSerializationType::nothing(),
15+
&mut serialization,
16+
0,
17+
);
18+
if result.is_err() {
19+
return String::new();
20+
}
21+
serialization
22+
}
23+
24+
fn do_parse_and_serialize<'i>(
25+
input: &mut Parser<'i, '_>,
26+
preserving_comments: bool,
27+
mut previous_token_type: TokenSerializationType,
28+
serialization: &mut String,
29+
indent_level: usize,
30+
) -> Result<(), ParseError<'i, ()>> {
31+
loop {
32+
let token = if preserving_comments {
33+
input.next_including_whitespace_and_comments()
34+
} else {
35+
input.next_including_whitespace()
36+
};
37+
let token = match token {
38+
Ok(token) => token,
39+
Err(..) => break,
40+
};
41+
if DEBUG {
42+
for _ in 0..indent_level {
43+
print!(" ");
44+
}
45+
println!("{:?}", token);
46+
}
47+
if token.is_parse_error() {
48+
let token = token.clone();
49+
return Err(input.new_unexpected_token_error(token))
50+
}
51+
let token_type = token.serialization_type();
52+
if previous_token_type.needs_separator_when_before(token_type) {
53+
serialization.push_str("/**/");
54+
}
55+
previous_token_type = token_type;
56+
token.to_css(serialization).unwrap();
57+
let closing_token = match token {
58+
Token::Function(_) | Token::ParenthesisBlock => Token::CloseParenthesis,
59+
Token::SquareBracketBlock => Token::CloseSquareBracket,
60+
Token::CurlyBracketBlock => Token::CloseCurlyBracket,
61+
_ => continue,
62+
};
63+
64+
input.parse_nested_block(|input| -> Result<_, ParseError<()>> {
65+
do_parse_and_serialize(input, preserving_comments, previous_token_type, serialization, indent_level + 1)
66+
})?;
67+
68+
closing_token.to_css(serialization).unwrap();
69+
}
70+
Ok(())
71+
}
72+
73+
fn fuzz(data: &str, preserving_comments: bool) {
74+
let serialization = parse_and_serialize(data, preserving_comments);
75+
let reserialization = parse_and_serialize(&serialization, preserving_comments);
76+
if DEBUG {
77+
println!("IN: {:?}", serialization);
78+
println!("OUT: {:?}", reserialization);
79+
}
80+
// TODO: This should ideally pass, but it doesn't for numbers near our
81+
// precision limits, so parsing e.g., 9999995e-45 generates a serialization
82+
// of 10e-39 because of dtoa rounding, and parsing _that_ generates a
83+
// serialization of 1e-38.
84+
//
85+
// assert_eq!(
86+
// serialization, reserialization,
87+
// "Serialization should be idempotent"
88+
// );
89+
}
90+
91+
libfuzzer_sys::fuzz_target!(|data: &str| {
92+
fuzz(data, false);
93+
// TODO(emilio): Serialization when preserving comments is not idempotent.
94+
// But in browsers we never preserve comments so that's ok...
95+
// fuzz(data, true);
96+
});

0 commit comments

Comments
 (0)