diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /js/src/fuzz-tests/differential-parsing.js | |
parent | Initial commit. (diff) | |
download | firefox-esr-upstream.tar.xz firefox-esr-upstream.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/fuzz-tests/differential-parsing.js')
-rw-r--r-- | js/src/fuzz-tests/differential-parsing.js | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/js/src/fuzz-tests/differential-parsing.js b/js/src/fuzz-tests/differential-parsing.js new file mode 100644 index 0000000000..1a61175721 --- /dev/null +++ b/js/src/fuzz-tests/differential-parsing.js @@ -0,0 +1,148 @@ +/* -*- Mode: javascript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// This file is used to detect and find cases where the Visage's parser is +// accepting more inputs than SpiderMonkey's parser. +// +// 1. Find new cases: +// +// To find new cases, we have to build with libFuzzer. The JS Shell can easily +// be built with libFuzzer by adding --enable-fuzzing to the configure script +// command line. +// +// Create a directory, and copy all test cases from the JS shell to this +// directory: +// +// $ mkdir fuzzer-input +// $ cd fuzzer-input +// $ find ../ -name \*.js -print0 | xargs -I '{}' -0 -n1 cp '{}' $(pwd) +// +// Once the JS Shell is built, set the FUZZER environment variable to this +// script location. +// +// $ FUZZER="./fuzz-tests/differential-parsing.js" build.dir/dist/bin/js -- \ +// -use_value_profile=1 -print_pcs=1 -timeout=5 -max_len=32 -only_ascii=1 \ +// ./fuzzer-input +// +// 2. Test a crashing test case: +// +// Once a new crashing test case is found, this script can be used to +// reproduce the crashing conditions. +// +// To do so, you need a JS Shell and to load this script and use the testFile +// function with the location of the crashing file. +// +// $ build.dir/dist/bin/js +// js> load("./fuzz-tests/differential-parsing.js"); +// js> testFile("./crash-42"); +// Parse Script C++: fail +// Parse Module C++: fail +// Parse Script Rust: succeed +// Parse Module Rust: fail +// Hit MOZ_CRASH(Rust accept more than C++) +// + +/* global crash, os, parse, timeout */ + +// This global will hold the current fuzzing buffer for each iteration. +var fuzzBuf; + +function timed(sec, f) { + // If the function `f` takes more than 3 seconds, then the evaluation ends + // prematurely and returns in libFuzzer handler without considering this + // test case as interesting. + timeout(sec, function() { + return false; + }); + f(); + + // Remove the timeout handler, to not kill future executions. + timeout(-1); +} + +var parseScriptCpp = { module: false, smoosh: false }; +var parseScriptRust = { module: false, smoosh: true }; +var parseModuleRust = { module: true, smoosh: true }; +var parseModuleCpp = { module: true, smoosh: false }; +function test(code, verbose = false) { + var isScriptCpp = false, + isModuleCpp = false, + isScriptRust = false, + isModuleRust = false; + try { + parse(code, parseScriptCpp); + isScriptCpp = true; + if (verbose) { + console.log("Parse Script C++: succeed"); + } + } catch (exc) { + if (verbose) { + console.log("Parse Script C++: fail"); + } + } + try { + parse(code, parseModuleCpp); + isModuleCpp = true; + if (verbose) { + console.log("Parse Module C++: succeed"); + } + } catch (exc) { + if (verbose) { + console.log("Parse Module C++: fail"); + } + } + try { + parse(code, parseScriptRust); + isScriptRust = true; + if (verbose) { + console.log("Parse Script Rust: succeed"); + } + } catch (exc) { + if (verbose) { + console.log("Parse Script Rust: fail"); + } + } + try { + parse(code, parseModuleRust); + isModuleRust = true; + if (verbose) { + console.log("Parse Module Rust: succeed"); + } + } catch (exc) { + if (verbose) { + console.log("Parse Module Rust: fail"); + } + } + if ((isScriptRust && !isScriptCpp) || (isModuleRust && !isModuleCpp)) { + crash("Rust accept more than C++"); + } +} + +function JSFuzzIterate() { + // This function is called per iteration. You must ensure that: + // + // 1) Each of your actions/decisions is only based on fuzzBuf, + // in particular not on Math.random(), Date/Time or other + // external inputs. + // + // 2) Your actions should be deterministic. The same fuzzBuf + // should always lead to the same set of actions/decisions. + // + // 3) You can modify the global where needed, but ensure that + // each iteration is isolated from one another by cleaning + // any modifications to the global after each iteration. + // In particular, iterations must not depend on or influence + // each other in any way (see also 1)). + // + // 4) You must catch all exceptions. + let code = String.fromCharCode(...fuzzBuf); + timed(3, _ => test(code)); + return 0; +} + +function testFile(file) { + let content = os.file.readFile(file); + test(content, true); +} |