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

Create a structure-aware JavaScript fuzzer to find deep bugs #1902

Closed
wants to merge 40 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
95c8623
init fuzzer
addisoncrump Mar 6, 2022
bba1252
appease the mighty rustfmt
addisoncrump Mar 6, 2022
6134df0
fix clippy errors by simply allowing it!
addisoncrump Mar 6, 2022
1550ce4
fix clippy + build by using spin and iter_mut
addisoncrump Mar 6, 2022
b7c7caa
simplify fuzzer input generation
addisoncrump Mar 6, 2022
0e5ad66
fix compile errors when not in feature fuzzer
addisoncrump Mar 6, 2022
c6ed17b
add missing cfg
addisoncrump Mar 6, 2022
377f55f
better clippy lint control
addisoncrump Mar 6, 2022
0d500b9
standardise arbitrary impl for Name
addisoncrump Mar 6, 2022
e56192c
final touches
addisoncrump Mar 6, 2022
00cbbb1
fix issue caused by a previous bad merge
addisoncrump Mar 6, 2022
4b17781
update deps for inputgen
addisoncrump Mar 6, 2022
53ca1a6
Merge branch 'main' of github.com:boa-dev/boa into experimental-fuzzer
addisoncrump Mar 6, 2022
186be92
Merge branch 'main' of github.com:boa-dev/boa into experimental-fuzzer
addisoncrump Mar 8, 2022
ea9540b
fix various updates w.r.t. assigntarget
addisoncrump Mar 8, 2022
621838f
fix some of the tree walking (string disappeared fixes)
addisoncrump Mar 8, 2022
ca9d0ab
Merge branch 'main' of github.com:boa-dev/boa into experimental-fuzzer
addisoncrump Mar 12, 2022
30dc27c
explicitly handle this and empty in case new cases are introduced later
addisoncrump Mar 12, 2022
4b65c4d
remove the pesky comma preventing rustfmt from succeeding
addisoncrump Mar 12, 2022
1ee7813
Merge branch 'main' of github.com:boa-dev/boa into experimental-fuzzer
addisoncrump Mar 14, 2022
4f82142
mergeup
addisoncrump Mar 17, 2022
d38fef5
update cargo information to be consistent with others
addisoncrump Mar 17, 2022
da91d86
split inputgen
addisoncrump Mar 17, 2022
6abaa1b
explain max_insns
addisoncrump Mar 17, 2022
750d166
docs
addisoncrump Mar 17, 2022
c1bd554
whoops, remove testing file
addisoncrump Mar 17, 2022
990740b
whoops, missed a docs addition
addisoncrump Mar 17, 2022
ed7eae6
fix clippy warnings + errors
addisoncrump Mar 17, 2022
6b52c4d
Merge branch 'main' of github.com:boa-dev/boa into experimental-fuzzer
addisoncrump Mar 17, 2022
e053e29
remove unnecessary excludes
addisoncrump Mar 17, 2022
61855a5
fix clippy, again
addisoncrump Mar 17, 2022
3ece1e4
Make extend_lifetime unsafe + give it explicit lifetimes
addisoncrump Mar 17, 2022
47d484a
whoops, explicit lifetime on replace_inner
addisoncrump Mar 17, 2022
d4bfe84
fix clippy lints
addisoncrump Mar 17, 2022
7826bac
remove irrelevant comment
addisoncrump Mar 17, 2022
ba98b69
Add fuzzing docs
addisoncrump Mar 17, 2022
0910729
typo + link for de-arbitrary
addisoncrump Mar 17, 2022
d18ed44
update command
addisoncrump Mar 17, 2022
a615901
formatter time
addisoncrump Mar 17, 2022
dd85b72
clarify character generation in Name
addisoncrump Mar 17, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ members = [
"boa_cli",
"boa_engine",
"boa_gc",
"boa_inputgen",
"boa_interner",
"boa_profiler",
"boa_tester",
Expand Down
3 changes: 3 additions & 0 deletions boa_engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ deser = ["boa_interner/serde"]
# Enable Boa's WHATWG console object implementation.
console = []

fuzzer = ["arbitrary", "boa_interner/fuzzer", "num-bigint/arbitrary"]

[dependencies]
arbitrary = { version = "1", features = ["derive"], optional = true }
boa_unicode = { path = "../boa_unicode", version = "0.14.0" }
boa_interner = { path = "../boa_interner", version = "0.14.0" }
boa_gc = { path = "../boa_gc", version = "0.14.0" }
Expand Down
12 changes: 12 additions & 0 deletions boa_engine/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ pub struct Context {
/// Whether or not global strict mode is active.
strict: bool,

/// The maximum number of instructions which will be executed in this context.
#[cfg(feature = "fuzzer")]
pub(crate) max_insns: usize,

pub(crate) vm: Vm,
}

Expand All @@ -97,6 +101,8 @@ impl Default for Context {
console: Console::default(),
intrinsics: Intrinsics::default(),
strict: false,
#[cfg(feature = "fuzzer")]
max_insns: 1 << 20,
vm: Vm {
frame: None,
stack: Vec::with_capacity(1024),
Expand Down Expand Up @@ -723,4 +729,10 @@ impl Context {
pub fn set_trace(&mut self, trace: bool) {
self.vm.trace = trace;
}

/// Set the maximum number of instructions for this context
#[cfg(feature = "fuzzer")]
pub fn set_max_insns(&mut self, max_insns: usize) {
self.max_insns = max_insns;
Razican marked this conversation as resolved.
Show resolved Hide resolved
}
}
3 changes: 2 additions & 1 deletion boa_engine/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
html_favicon_url = "https://raw.githubusercontent.com/boa-dev/boa/main/assets/logo.svg"
)]
#![cfg_attr(not(test), forbid(clippy::unwrap_used))]
#![cfg_attr(feature = "fuzzer", allow(clippy::use_self))] // false-positive on derive(Arbitrary)
#![cfg_attr(not(feature = "fuzzer"), deny(clippy::use_self))]
#![warn(
clippy::perf,
clippy::single_match_else,
Expand All @@ -26,7 +28,6 @@
clippy::all,
clippy::cast_lossless,
clippy::redundant_closure_for_method_calls,
clippy::use_self,
clippy::unnested_or_patterns,
clippy::trivially_copy_pass_by_ref,
clippy::needless_pass_by_value,
Expand Down
1 change: 1 addition & 0 deletions boa_engine/src/syntax/ast/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use serde::{Deserialize, Serialize};
/// [spec]: https://tc39.es/ecma262/#sec-primary-expression-literals
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Literals
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "fuzzer", derive(arbitrary::Arbitrary))]
#[derive(Clone, Debug, Finalize, PartialEq)]
pub enum Const {
/// A string literal is zero or more characters enclosed in double (`"`) or single (`'`) quotation marks.
Expand Down
8 changes: 8 additions & 0 deletions boa_engine/src/syntax/ast/node/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ mod tests;
/// [spec]: https://tc39.es/ecma262/#prod-ArrayLiteral
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "fuzzer", derive(arbitrary::Arbitrary))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct ArrayDecl {
#[cfg_attr(feature = "deser", serde(flatten))]
Expand Down Expand Up @@ -59,6 +60,13 @@ impl AsRef<[Node]> for ArrayDecl {
}
}

#[cfg(feature = "fuzzer")]
impl AsMut<[Node]> for ArrayDecl {
fn as_mut(&mut self) -> &mut [Node] {
&mut self.arr
}
}

impl<T> From<T> for ArrayDecl
where
T: Into<Box<[Node]>>,
Expand Down
8 changes: 8 additions & 0 deletions boa_engine/src/syntax/ast/node/await_expr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,19 @@ mod tests;
/// [spec]: https://tc39.es/ecma262/#prod-AwaitExpression
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "fuzzer", derive(arbitrary::Arbitrary))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct AwaitExpr {
expr: Box<Node>,
}

impl AwaitExpr {
#[cfg(feature = "fuzzer")]
pub fn expr_mut(&mut self) -> &mut Node {
&mut self.expr
}
}

impl<T> From<T> for AwaitExpr
where
T: Into<Box<Node>>,
Expand Down
6 changes: 6 additions & 0 deletions boa_engine/src/syntax/ast/node/block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ mod tests;
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "deser", serde(transparent))]
#[cfg_attr(feature = "fuzzer", derive(arbitrary::Arbitrary))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct Block {
#[cfg_attr(feature = "deser", serde(flatten))]
Expand All @@ -40,6 +41,11 @@ impl Block {
self.statements.items()
}

#[cfg(feature = "fuzzer")]
pub fn items_mut(&mut self) -> &mut [Node] {
self.statements.items_mut()
}

pub(crate) fn lexically_declared_names(&self, interner: &Interner) -> FxHashSet<Sym> {
self.statements.lexically_declared_names(interner)
}
Expand Down
11 changes: 11 additions & 0 deletions boa_engine/src/syntax/ast/node/call/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ mod tests;
/// [spec]: https://tc39.es/ecma262/#prod-CallExpression
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions#Calling_functions
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "fuzzer", derive(arbitrary::Arbitrary))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct Call {
expr: Box<Node>,
Expand Down Expand Up @@ -51,6 +52,16 @@ impl Call {
pub fn args(&self) -> &[Node] {
&self.args
}

#[cfg(feature = "fuzzer")]
pub fn expr_mut(&mut self) -> &mut Node {
&mut self.expr
}

#[cfg(feature = "fuzzer")]
pub fn args_mut(&mut self) -> &mut [Node] {
&mut self.args
}
}

impl ToInternedString for Call {
Expand Down
16 changes: 16 additions & 0 deletions boa_engine/src/syntax/ast/node/conditional/conditional_op/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use serde::{Deserialize, Serialize};
/// [spec]: https://tc39.es/ecma262/#prod-ConditionalExpression
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Literals
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "fuzzer", derive(arbitrary::Arbitrary))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct ConditionalOp {
condition: Box<Node>,
Expand All @@ -40,6 +41,21 @@ impl ConditionalOp {
&self.if_false
}

#[cfg(feature = "fuzzer")]
pub fn cond_mut(&mut self) -> &mut Node {
&mut self.condition
}

#[cfg(feature = "fuzzer")]
pub fn if_true_mut(&mut self) -> &mut Node {
&mut self.if_true
}

#[cfg(feature = "fuzzer")]
pub fn if_false_mut(&mut self) -> &mut Node {
&mut self.if_false
}

/// Creates a `ConditionalOp` AST node.
pub fn new<C, T, F>(condition: C, if_true: T, if_false: F) -> Self
where
Expand Down
16 changes: 16 additions & 0 deletions boa_engine/src/syntax/ast/node/conditional/if_node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use serde::{Deserialize, Serialize};
/// [falsy]: https://developer.mozilla.org/en-US/docs/Glossary/falsy
/// [expression]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Expressions
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "fuzzer", derive(arbitrary::Arbitrary))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct If {
cond: Box<Node>,
Expand All @@ -42,6 +43,21 @@ impl If {
self.else_node.as_ref().map(Box::as_ref)
}

#[cfg(feature = "fuzzer")]
pub fn cond_mut(&mut self) -> &mut Node {
&mut self.cond
}

#[cfg(feature = "fuzzer")]
pub fn body_mut(&mut self) -> &mut Node {
&mut self.body
}

#[cfg(feature = "fuzzer")]
pub fn else_node_mut(&mut self) -> Option<&mut Node> {
self.else_node.as_deref_mut()
}

/// Creates an `If` AST node.
pub fn new<C, B, E, OE>(condition: C, body: B, else_node: OE) -> Self
where
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use serde::{Deserialize, Serialize};
/// [spec]: https://tc39.es/ecma262/#prod-ArrowFunction
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "fuzzer", derive(arbitrary::Arbitrary))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct ArrowFunctionDecl {
name: Option<Sym>,
Expand Down Expand Up @@ -61,6 +62,21 @@ impl ArrowFunctionDecl {
&self.body
}

#[cfg(feature = "fuzzer")]
pub fn name_mut(&mut self) -> Option<&mut Sym> {
self.name.as_mut()
}

#[cfg(feature = "fuzzer")]
pub fn params_mut(&mut self) -> &mut FormalParameterList {
&mut self.params
}

#[cfg(feature = "fuzzer")]
pub fn body_mut(&mut self) -> &mut StatementList {
&mut self.body
}

/// Implements the display formatting with indentation.
pub(in crate::syntax::ast::node) fn to_indented_string(
&self,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use serde::{Deserialize, Serialize};
/// [spec]: https://tc39.es/ecma262/#sec-async-function-prototype-properties
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "fuzzer", derive(arbitrary::Arbitrary))]
#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
pub struct AsyncFunctionDecl {
name: Sym,
Expand Down Expand Up @@ -52,6 +53,21 @@ impl AsyncFunctionDecl {
self.body.items()
}

#[cfg(feature = "fuzzer")]
pub fn name_mut(&mut self) -> &mut Sym {
&mut self.name
}

#[cfg(feature = "fuzzer")]
pub fn parameters_mut(&mut self) -> &mut FormalParameterList {
&mut self.parameters
}

#[cfg(feature = "fuzzer")]
pub fn body_mut(&mut self) -> &mut StatementList {
&mut self.body
}

/// Implements the display formatting with indentation.
pub(in crate::syntax::ast::node) fn to_indented_string(
&self,
Expand Down
Loading