Skip to content

Commit

Permalink
make a more stable exit strategy for fuzzing with loops
Browse files Browse the repository at this point in the history
  • Loading branch information
addisoncrump committed Nov 6, 2022
1 parent 7a1cbd5 commit 828a4c4
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 12 deletions.
23 changes: 23 additions & 0 deletions boa_engine/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,17 @@ impl JsNativeError {
Self::new(JsNativeErrorKind::Uri, Box::default(), None)
}

/// Creates a new `JsNativeError` that indicates that the context hit its execution limit. This
/// is only used in a fuzzing context.
#[cfg(feature = "fuzz")]
pub fn no_instructions_remain() -> Self {
Self::new(
JsNativeErrorKind::NoInstructionsRemain,
Box::default(),
None,
)
}

/// Sets the message of this error.
///
/// # Examples
Expand Down Expand Up @@ -619,6 +630,12 @@ impl JsNativeError {
}
JsNativeErrorKind::Type => (constructors.type_error().prototype(), ErrorKind::Type),
JsNativeErrorKind::Uri => (constructors.uri_error().prototype(), ErrorKind::Uri),
#[cfg(feature = "fuzz")]
JsNativeErrorKind::NoInstructionsRemain => {
// we can propagate out from try/catch since the catch block will also perform some
// operation
(constructors.error().prototype(), ErrorKind::Error)
}
};

let o = JsObject::from_proto_and_data(prototype, ObjectData::error(tag));
Expand Down Expand Up @@ -747,6 +764,10 @@ pub enum JsNativeErrorKind {
/// [e_uri]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI
/// [d_uri]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURI
Uri,
/// Error thrown when no instructions remain. Only used in a fuzzing context; not a valid JS
/// error variant.
#[cfg(feature = "fuzz")]
NoInstructionsRemain,
}

impl std::fmt::Display for JsNativeErrorKind {
Expand All @@ -760,6 +781,8 @@ impl std::fmt::Display for JsNativeErrorKind {
JsNativeErrorKind::Syntax => "SyntaxError",
JsNativeErrorKind::Type => "TypeError",
JsNativeErrorKind::Uri => "UriError",
#[cfg(feature = "fuzz")]
JsNativeErrorKind::NoInstructionsRemain => "NoInstructionsRemain",
}
.fmt(f)
}
Expand Down
4 changes: 2 additions & 2 deletions boa_engine/src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use crate::{
builtins::async_generator::{AsyncGenerator, AsyncGeneratorState},
vm::{call_frame::CatchAddresses, code_block::Readable},
Context, JsResult, JsValue,
Context, JsError, JsNativeError, JsResult, JsValue,
};
use boa_interner::ToInternedString;
use boa_profiler::Profiler;
Expand Down Expand Up @@ -114,7 +114,7 @@ impl Context {
fn execute_instruction(&mut self) -> JsResult<ShouldExit> {
#[cfg(feature = "fuzz")]
if self.insns_remaining == 0 {
return Ok(ShouldExit::True);
return Err(JsError::from_native(JsNativeError::no_instructions_remain()));
} else {
self.insns_remaining -= 1;
}
Expand Down
28 changes: 18 additions & 10 deletions fuzz/fuzz_targets/vm-implied.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,30 @@
mod common;

use crate::common::FuzzSource;
use boa_engine::{Context, JsResult, JsValue};
use boa_engine::{Context, JsNativeErrorKind};
use libfuzzer_sys::fuzz_target;
use libfuzzer_sys::Corpus;

fn do_fuzz(original: FuzzSource) -> JsResult<JsValue> {
fn do_fuzz(original: FuzzSource) -> Corpus {
let mut ctx = Context::builder()
.interner(original.interner)
.insns_remaining(1 << 16)
.build();
ctx.eval(&original.source)
match ctx.eval(&original.source) {
Ok(_) => Corpus::Keep,
Err(e) => match e.try_native(&mut ctx) {
Ok(e) => {
if matches!(e.kind, JsNativeErrorKind::NoInstructionsRemain) {
// most interesting loops will initially cause an infinite loop
// this is okay as long as it is explicitly handled
Corpus::Keep
} else {
Corpus::Reject
}
}
Err(_) => Corpus::Reject,
},
}
}

fuzz_target!(|original: FuzzSource| -> Corpus {
if do_fuzz(original).is_ok() {
Corpus::Keep
} else {
Corpus::Reject
}
});
fuzz_target!(|original: FuzzSource| -> Corpus { do_fuzz(original) });

0 comments on commit 828a4c4

Please sign in to comment.