Commit 320d9870 authored by Michael Achenbach's avatar Michael Achenbach Committed by Commit Bot

Open source js-fuzzer

This is a JavaScript fuzzer originally authored by Oliver Chang. It
is a mutation based fuzzer using Babel code transformations. For more
information see the included README.md.

The original code was altered:
- Add new V8 copyright headers.
- Make the test expectation generator aware of the headers.
- Fix file endings for presubmit checks.
- Fix `npm test` on fresh checkout with a new fake DB.
- Make test skipping work with new v8/tools location.
- OWNERS file.
- New title section in README.md.

No-Try: true
Bug: chromium:1109770
Change-Id: Ie71752c0a37491a50500c49060a3c526716ef933
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2320330
Commit-Queue: Michael Achenbach <machenbach@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#69164}
parent 8130e54d
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module.exports = {
"env": {
"node": true,
"commonjs": true,
"es6": true,
"mocha": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018
},
"rules": {
}
};
/node_modules
/ochang_js_fuzzer*
/db/
/output.zip
/output/
/workdir/
set noparent
file:../../../INFRA_OWNERS
msarms@chromium.org
mslekova@chromium.org
ochang@chromium.org
# COMPONENT: Infra>Client>V8
# JS-Fuzzer
Javascript fuzzer for stand-alone shells like D8, Chakra, JSC or Spidermonkey.
Original author: Oliver Chang
# Building
This fuzzer may require versions of node that are newer than available on
ClusterFuzz, so we use [pkg](https://github.com/zeit/pkg) to create a self
contained binary) out of this.
## Prereqs
You need to intall nodejs and npm. Run `npm install` in this directory.
## Fuzzing DB
This fuzzer requires a fuzzing DB. To build one, get the latest web_tests.zip
from `gs://clusterfuzz-data/web_tests.zip` and run:
```bash
$ mkdir db
$ node build_db.js -i /path/to/web_tests -o db chakra v8 spidermonkey WebKit/JSTests
```
This may take a while. Optionally test the fuzzing DB with:
```bash
$ node test_db.js -i db
```
## Building fuzzer
Then, to build the fuzzer,
```bash
$ ./node_modules/.bin/pkg -t node10-linux-x64 .
```
Replace "linux" with either "win" or "macos" for those platforms.
This builds a binary named `ochang_js_fuzzer` for Linux / macOS OR
`ochang_js_fuzzer.exe` for Windows.
## Packaging
Use `./package.sh`, `./package.sh win` or `./package.sh macos` to build and
create the `output.zip` archive or use these raw commands:
```bash
$ mkdir output
$ cd output
$ ln -s ../db db
$ ln -s ../ochang_js_fuzzer run
$ zip -r /path/output.zip *
```
**NOTE**: Add `.exe` to `ochang_js_fuzzer` and `run` filename above if archiving
for Windows platform.
# Development
Run the tests with:
```bash
$ npm test
```
When test expectations change, generate them with:
```bash
$ GENERATE=1 npm test
```
# Generating exceptional configurations
Tests that fail to parse or show very bad performance can be automatically
skipped or soft-skipped with the following script (takes >1h):
```bash
$ WEB_TESTS=/path/to/web_tests OUTPUT=/path/to/output/folder ./gen_exceptions.sh
```
# Experimenting (limited to differential fuzzing)
To locally evaluate the fuzzer, setup a work directory as follows:
```bash
$ workdir/
$ workdir/app_dir
$ workdir/fuzzer
$ workdir/input
$ workdir/output
```
The `app_dir` folder can be a symlink or should contain the bundled
version of `d8` with all files required for execution.
The copy the packaged `ochang_js_fuzzer` executable and the `db` folder
to the `fuzzer` directory or use a symlink.
The `input` directory is the root folder of the corpus, i.e. pointing
to the unzipped data of `gs://clusterfuzz-data/web_tests.zip`.
The `output` directory is expected to be empty. It'll contain all
output of the fuzzing session. Start the experiments with:
```bash
$ # Around ~40000 corresponds to 24h of fuzzing on a workstation.
$ NUM_RUNS = 40000
$ python tools/workbench.py $NUM_RUNS
```
You can check current stats with:
```bash
$ cat workdir/output/stats.json | python -m json.tool
```
When failures are found, you can forge minimization command lines with:
```bash
$ MINIMIZER_PATH = path/to/minimizer
$ python tools/minimize.py $MINIMIZER_PATH
```
The path should point to a local checkout of the [minimizer](https://chrome-internal.googlesource.com/chrome/tools/clusterfuzz/+/refs/heads/master/src/python/bot/minimizer/).
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Collect JS nodes.
*/
const program = require('commander');
const corpus = require('./corpus.js');
const db = require('./db.js');
const path = require('path');
const sourceHelpers = require('./source_helpers.js');
function main() {
Error.stackTraceLimit = Infinity;
program
.version('0.0.1')
.option('-i, --input_dir <path>', 'Input directory.')
.option('-o, --output_dir <path>', 'Output directory.')
.parse(process.argv);
if (!program.args.length) {
console.log('Need to specify corpora.');
return;
}
if (!program.output_dir) {
console.log('Need to specify output dir.');
return;
}
const mutateDb = new db.MutateDbWriter(program.output_dir);
const expressions = new Set();
const inputDir = path.resolve(program.input_dir);
for (const corpusName of program.args) {
const curCorpus = new corpus.Corpus(inputDir, corpusName);
for (const relPath of curCorpus.relFiles()) {
let source;
try {
source = sourceHelpers.loadSource(inputDir, relPath);
} catch (e) {
console.log(e);
continue;
}
if (!source) {
continue;
}
try{
mutateDb.process(source, expressions);
} catch (e) {
console.log(e);
}
}
}
mutateDb.writeIndex();
}
main();
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Corpus
*/
const program = require('commander');
const fs = require('fs');
const path = require('path');
const exceptions = require('./exceptions.js');
const random = require('./random.js');
const sourceHelpers = require('./source_helpers.js');
function* walkDirectory(directory, filter) {
// Generator for recursively walk a directory.
for (const filePath of fs.readdirSync(directory)) {
const currentPath = path.join(directory, filePath);
const stat = fs.lstatSync(currentPath);
if (stat.isFile()) {
if (!filter || filter(currentPath)) {
yield currentPath;
}
continue;
}
if (stat.isDirectory()) {
for (let childFilePath of walkDirectory(currentPath, filter)) {
yield childFilePath;
}
}
}
}
class Corpus {
// Input corpus.
constructor(inputDir, corpusName, extraStrict=false) {
this.inputDir = inputDir;
this.extraStrict = extraStrict;
// Filter for permitted JS files.
function isPermittedJSFile(absPath) {
return (absPath.endsWith('.js') &&
!exceptions.isTestSkippedAbs(absPath));
}
// Cache relative paths of all files in corpus.
this.skippedFiles = [];
this.softSkippedFiles = [];
this.permittedFiles = [];
const directory = path.join(inputDir, corpusName);
for (const absPath of walkDirectory(directory, isPermittedJSFile)) {
const relPath = path.relative(this.inputDir, absPath);
if (exceptions.isTestSkippedRel(relPath)) {
this.skippedFiles.push(relPath);
} else if (exceptions.isTestSoftSkippedAbs(absPath) ||
exceptions.isTestSoftSkippedRel(relPath)) {
this.softSkippedFiles.push(relPath);
} else {
this.permittedFiles.push(relPath);
}
}
random.shuffle(this.softSkippedFiles);
random.shuffle(this.permittedFiles);
}
// Relative paths of all files in corpus.
*relFiles() {
for (const relPath of this.permittedFiles) {
yield relPath;
}
for (const relPath of this.softSkippedFiles) {
yield relPath;
}
}
// Relative paths of all files in corpus including generated skipped.
*relFilesForGenSkipped() {
for (const relPath of this.relFiles()) {
yield relPath;
}
for (const relPath of this.skippedFiles) {
yield relPath;
}
}
/**
* Returns "count" relative test paths, randomly selected from soft-skipped
* and permitted files. Permitted files have a 4 times higher chance to
* be chosen.
*/
getRandomTestcasePaths(count) {
return random.twoBucketSample(
this.softSkippedFiles, this.permittedFiles, 4, count);
}
loadTestcase(relPath, strict, label) {
const start = Date.now();
try {
const source = sourceHelpers.loadSource(this.inputDir, relPath, strict);
if (program.verbose) {
const duration = Date.now() - start;
console.log(`Parsing ${relPath} ${label} took ${duration} ms.`);
}
return source;
} catch (e) {
console.log(`WARNING: failed to ${label} parse ${relPath}`);
console.log(e);
}
return undefined;
}
*loadTestcases(relPaths) {
for (const relPath of relPaths) {
if (this.extraStrict) {
// When re-generating the files marked sloppy, we additionally test if
// the file parses in strict mode.
this.loadTestcase(relPath, true, 'strict');
}
const source = this.loadTestcase(relPath, false, 'sloppy');
if (source) {
yield source;
}
}
}
getRandomTestcases(count) {
return Array.from(this.loadTestcases(this.getRandomTestcasePaths(count)));
}
getAllTestcases() {
return this.loadTestcases(this.relFilesForGenSkipped());
}
}
module.exports = {
Corpus: Corpus,
walkDirectory: walkDirectory,
}
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Mutation Db.
*/
const crypto = require('crypto');
const fs = require('fs');
const fsPath = require('path');
const babelGenerator = require('@babel/generator').default;
const babelTraverse = require('@babel/traverse').default;
const babelTypes = require('@babel/types');
const globals = require('globals');
const random = require('./random.js');
const globalIdentifiers = new Set(Object.keys(globals.builtin));
const propertyNames = new Set([
// Parsed from https://github.com/tc39/ecma262/blob/master/spec.html
'add',
'anchor',
'apply',
'big',
'bind',
'blink',
'bold',
'buffer',
'byteLength',
'byteOffset',
'BYTES_PER_ELEMENT',
'call',
'catch',
'charAt',
'charCodeAt',
'clear',
'codePointAt',
'compile',
'concat',
'constructor',
'copyWithin',
'__defineGetter__',
'__defineSetter__',
'delete',
'endsWith',
'entries',
'every',
'exec',
'fill',
'filter',
'find',
'findIndex',
'fixed',
'flags',
'fontcolor',
'fontsize',
'forEach',
'get',
'getDate',
'getDay',
'getFloat32',
'getFloat64',
'getFullYear',
'getHours',
'getInt16',
'getInt32',
'getInt8',
'getMilliseconds',
'getMinutes',
'getMonth',
'getSeconds',
'getTime',
'getTimezoneOffset',
'getUint16',
'getUint32',
'getUint8',
'getUTCDate',
'getUTCDay',
'getUTCFullYear',
'getUTCHours',
'getUTCMilliseconds',
'getUTCMinutes',
'getUTCMonth',
'getUTCSeconds',
'getYear',
'global',
'has',
'hasInstance',
'hasOwnProperty',
'ignoreCase',
'includes',
'indexOf',
'isConcatSpreadable',
'isPrototypeOf',
'italics',
'iterator',
'join',
'keys',
'lastIndexOf',
'length',
'link',
'localeCompare',
'__lookupGetter__',
'__lookupSetter__',
'map',
'match',
'match',
'message',
'multiline',
'name',
'next',
'normalize',
'padEnd',
'padStart',
'pop',
'propertyIsEnumerable',
'__proto__',
'prototype',
'push',
'reduce',
'reduceRight',
'repeat',
'replace',
'replace',
'return',
'reverse',
'search',
'search',
'set',
'set',
'setDate',
'setFloat32',
'setFloat64',
'setFullYear',
'setHours',
'setInt16',
'setInt32',
'setInt8',
'setMilliseconds',
'setMinutes',
'setMonth',
'setSeconds',
'setTime',
'setUint16',
'setUint32',
'setUint8',
'setUTCDate',
'setUTCFullYear',
'setUTCHours',
'setUTCMilliseconds',
'setUTCMinutes',
'setUTCMonth',
'setUTCSeconds',
'setYear',
'shift',
'size',
'slice',
'slice',
'small',
'some',
'sort',
'source',
'species',
'splice',
'split',
'split',
'startsWith',
'sticky',
'strike',
'sub',
'subarray',
'substr',
'substring',
'sup',
'test',
'then',
'throw',
'toDateString',
'toExponential',
'toFixed',
'toGMTString',
'toISOString',
'toJSON',
'toLocaleDateString',
'toLocaleLowerCase',
'toLocaleString',
'toLocaleTimeString',
'toLocaleUpperCase',
'toLowerCase',
'toPrecision',
'toPrimitive',
'toString',
'toStringTag',
'toTimeString',
'toUpperCase',
'toUTCString',
'trim',
'unicode',
'unscopables',
'unshift',
'valueOf',
'values',
]);
const MAX_DEPENDENCIES = 2;
class Expression {
constructor(type, source, isStatement, originalPath,
dependencies, needsSuper) {
this.type = type;
this.source = source;
this.isStatement = isStatement;
this.originalPath = originalPath;
this.dependencies = dependencies;
this.needsSuper = needsSuper;
}
}
function dedupKey(expression) {
if (!expression.dependencies) {
return expression.source;
}
let result = expression.source;
for (let dependency of expression.dependencies) {
result = result.replace(new RegExp(dependency, 'g'), 'ID');
}
return result;
}
function _markSkipped(path) {
while (path) {
path.node.__skipped = true;
path = path.parentPath;
}
}
class MutateDbWriter {
constructor(outputDir) {
this.seen = new Set();
this.outputDir = fsPath.resolve(outputDir);
this.index = {
statements: [],
superStatements: [],
all: [],
};
}
process(source) {
let self = this;
let varIndex = 0;
// First pass to collect dependency information.
babelTraverse(source.ast, {
Super(path) {
while (path) {
path.node.__needsSuper = true;
path = path.parentPath;
}
},
YieldExpression(path) {
// Don't include yield expressions in DB.
_markSkipped(path);
},
Identifier(path) {
if (globalIdentifiers.has(path.node.name) &&
path.node.name != 'eval') {
// Global name.
return;
}
if (propertyNames.has(path.node.name) &&
path.parentPath.isMemberExpression() &&
path.parentKey !== 'object') {
// Builtin property name.
return;
}
let binding = path.scope.getBinding(path.node.name);
if (!binding) {
// Unknown dependency. Don't handle this.
_markSkipped(path);
return;
}
let newName;
if (path.node.name.startsWith('VAR_')) {
newName = path.node.name;
} else if (babelTypes.isFunctionDeclaration(binding.path.node) ||
babelTypes.isFunctionExpression(binding.path.node) ||
babelTypes.isDeclaration(binding.path.node) ||
babelTypes.isFunctionExpression(binding.path.node)) {
// Unknown dependency. Don't handle this.
_markSkipped(path);
return;
} else {
newName = 'VAR_' + varIndex++;
path.scope.rename(path.node.name, newName);
}
// Mark all parents as having a dependency.
while (path) {
path.node.__idDependencies = path.node.__idDependencies || [];
if (path.node.__idDependencies.length <= MAX_DEPENDENCIES) {
path.node.__idDependencies.push(newName);
}
path = path.parentPath;
}
}
});
babelTraverse(source.ast, {
Expression(path) {
if (!path.parentPath.isExpressionStatement()) {
return;
}
if (path.node.__skipped ||
(path.node.__idDependencies &&
path.node.__idDependencies.length > MAX_DEPENDENCIES)) {
return;
}
if (path.isIdentifier() || path.isMemberExpression() ||
path.isConditionalExpression() ||
path.isBinaryExpression() || path.isDoExpression() ||
path.isLiteral() ||
path.isObjectExpression() || path.isArrayExpression()) {
// Skip:
// - Identifiers.
// - Member expressions (too many and too context dependent).
// - Conditional expressions (too many and too context dependent).
// - Binary expressions (too many).
// - Literals (too many).
// - Object/array expressions (too many).
return;
}
if (path.isAssignmentExpression()) {
if (!babelTypes.isMemberExpression(path.node.left)) {
// Skip assignments that aren't to properties.
return;
}
if (babelTypes.isIdentifier(path.node.left.object)) {
if (babelTypes.isNumericLiteral(path.node.left.property)) {
// Skip VAR[\d+] = ...;
// There are too many and they generally aren't very useful.
return;
}
if (babelTypes.isStringLiteral(path.node.left.property) &&
!propertyNames.has(path.node.left.property.value)) {
// Skip custom properties. e.g.
// VAR["abc"] = ...;
// There are too many and they generally aren't very useful.
return;
}
}
}
if (path.isCallExpression() &&
babelTypes.isIdentifier(path.node.callee) &&
!globalIdentifiers.has(path.node.callee.name)) {
// Skip VAR(...) calls since there's too much context we're missing.
return;
}
if (path.isUnaryExpression() && path.node.operator == '-') {
// Skip -... since there are too many.
return;
}
// Make the template.
let generated = babelGenerator(path.node, { concise: true }).code;
let expression = new Expression(
path.node.type,
generated,
path.parentPath.isExpressionStatement(),
source.relPath,
path.node.__idDependencies,
Boolean(path.node.__needsSuper));
// Try to de-dupe similar expressions.
let key = dedupKey(expression);
if (self.seen.has(key)) {
return;
}
// Write results.
let dirPath = fsPath.join(self.outputDir, expression.type);
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath);
}
let sha1sum = crypto.createHash('sha1');
sha1sum.update(key);
let filePath = fsPath.join(dirPath, sha1sum.digest('hex') + '.json');
fs.writeFileSync(filePath, JSON.stringify(expression));
let relPath = fsPath.relative(self.outputDir, filePath);
// Update index.
self.seen.add(key);
self.index.all.push(relPath);
if (expression.needsSuper) {
self.index.superStatements.push(relPath);
} else {
self.index.statements.push(relPath);
}
}
});
}
writeIndex() {
fs.writeFileSync(
fsPath.join(this.outputDir, 'index.json'),
JSON.stringify(this.index));
}
}
class MutateDb {
constructor(outputDir) {
this.outputDir = fsPath.resolve(outputDir);
this.index = JSON.parse(
fs.readFileSync(fsPath.join(outputDir, 'index.json'), 'utf-8'));
}
getRandomStatement({canHaveSuper=false} = {}) {
let choices;
if (canHaveSuper) {
choices = random.randInt(0, 1) ?
this.index.all : this.index.superStatements;
} else {
choices = this.index.statements;
}
let path = fsPath.join(
this.outputDir, choices[random.randInt(0, choices.length - 1)]);
return JSON.parse(fs.readFileSync(path), 'utf-8');
}
}
module.exports = {
MutateDb: MutateDb,
MutateDbWriter: MutateDbWriter,
}
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Script mutator for differential fuzzing.
*/
'use strict';
const assert = require('assert');
const fs = require('fs');
const path = require('path');
const common = require('./mutators/common.js');
const random = require('./random.js');
const sourceHelpers = require('./source_helpers.js');
const { filterDifferentialFuzzFlags } = require('./exceptions.js');
const { DifferentialFuzzMutator, DifferentialFuzzSuppressions } = require(
'./mutators/differential_fuzz_mutator.js');
const { ScriptMutator } = require('./script_mutator.js');
const USE_ORIGINAL_FLAGS_PROB = 0.2;
/**
* Randomly chooses a configuration from experiments. The configuration
* parameters are expected to be passed from a bundled V8 build. Constraints
* mentioned below are enforced by PRESUBMIT checks on the V8 side.
*
* @param {Object[]} experiments List of tuples (probability, first config name,
* second config name, second d8 name). The probabilities are integers in
* [0,100]. We assume the sum of all probabilities is 100.
* @param {Object[]} additionalFlags List of tuples (probability, flag strings).
* Probability is in [0,1).
* @return {string[]} List of flags for v8_foozzie.py.
*/
function chooseRandomFlags(experiments, additionalFlags) {
// Add additional flags to second config based on experiment percentages.
const extra_flags = [];
for (const [p, flags] of additionalFlags) {
if (random.choose(p)) {
for (const flag of flags.split(' ')) {
extra_flags.push('--second-config-extra-flags=' + flag);
}
}
}
// Calculate flags determining the experiment.
let acc = 0;
const threshold = random.random() * 100;
for (let [prob, first_config, second_config, second_d8] of experiments) {
acc += prob;
if (acc > threshold) {
return [
'--first-config=' + first_config,
'--second-config=' + second_config,
'--second-d8=' + second_d8,
].concat(extra_flags);
}
}
// Unreachable.
assert(false);
}
function loadJSONFromBuild(name) {
assert(process.env.APP_DIR);
const fullPath = path.join(path.resolve(process.env.APP_DIR), name);
return JSON.parse(fs.readFileSync(fullPath, 'utf-8'));
}
function hasMjsunit(dependencies) {
return dependencies.some(dep => dep.relPath.endsWith('mjsunit.js'));
}
function hasJSTests(dependencies) {
return dependencies.some(dep => dep.relPath.endsWith('jstest_stubs.js'));
}
class DifferentialScriptMutator extends ScriptMutator {
constructor(settings, db_path) {
super(settings, db_path);
// Mutators for differential fuzzing.
this.differential = [
new DifferentialFuzzSuppressions(settings),
new DifferentialFuzzMutator(settings),
];
// Flag configurations from the V8 build directory.
this.experiments = loadJSONFromBuild('v8_fuzz_experiments.json');
this.additionalFlags = loadJSONFromBuild('v8_fuzz_flags.json');
}
/**
* Performes the high-level mutation and afterwards adds flags for the
* v8_foozzie.py harness.
*/
mutateMultiple(inputs) {
const result = super.mutateMultiple(inputs);
const originalFlags = [];
// Keep original JS flags in some cases. Let the harness pass them to
// baseline _and_ comparison run.
if (random.choose(USE_ORIGINAL_FLAGS_PROB)) {
for (const flag of filterDifferentialFuzzFlags(result.flags)) {
originalFlags.push('--first-config-extra-flags=' + flag);
originalFlags.push('--second-config-extra-flags=' + flag);
}
}
// Add flags for the differnetial-fuzzing settings.
const fuzzFlags = chooseRandomFlags(this.experiments, this.additionalFlags);
result.flags = fuzzFlags.concat(originalFlags);
return result;
}
/**
* Mutatates a set of inputs.
*
* Additionally we prepare inputs by tagging each with the original source
* path for later printing. The mutated sources are post-processed by the
* differential-fuzz mutators, adding extra printing and other substitutions.
*/
mutateInputs(inputs) {
inputs.forEach(input => common.setOriginalPath(input, input.relPath));
const result = super.mutateInputs(inputs);
this.differential.forEach(mutator => mutator.mutate(result));
return result;
}
/**
* Adds extra dependencies for differential fuzzing.
*/
resolveDependencies(inputs) {
const dependencies = super.resolveDependencies(inputs);
// The suppression file neuters functions not working with differential
// fuzzing. It can also be used to temporarily silence some functionality
// leading to dupes of an active bug.
dependencies.push(
sourceHelpers.loadResource('differential_fuzz_suppressions.js'));
// Extra printing and tracking functionality.
dependencies.push(
sourceHelpers.loadResource('differential_fuzz_library.js'));
// Make Chakra tests print more.
dependencies.push(
sourceHelpers.loadResource('differential_fuzz_chakra.js'));
if (hasMjsunit(dependencies)) {
// Make V8 tests print more. We guard this as the functionality
// relies on mjsunit.js.
dependencies.push(sourceHelpers.loadResource('differential_fuzz_v8.js'));
}
if (hasJSTests(dependencies)) {
dependencies.push(
sourceHelpers.loadResource('differential_fuzz_jstest.js'));
}
return dependencies;
}
}
module.exports = {
DifferentialScriptMutator: DifferentialScriptMutator,
};
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Blacklists for fuzzer.
*/
'use strict';
const fs = require('fs');
const path = require('path');
const random = require('./random.js');
const {generatedSloppy, generatedSoftSkipped, generatedSkipped} = require(
'./generated/exceptions.js');
const SKIPPED_FILES = [
// Disabled for unexpected test behavior, specific to d8 shell.
'd8-os.js',
'd8-readbuffer.js',
// Passes JS flags.
'd8-arguments.js',
// Slow tests or tests that are too large to be used as input.
/numops-fuzz-part.*.js/,
'regexp-pcre.js',
'unicode-test.js',
'unicodelctest.js',
'unicodelctest-no-optimization.js',
// Unsupported modules.
/^modules.*\.js/,
// Unsupported property escapes.
/^regexp-property-.*\.js/,
// Bad testcases that just loads a script that always throws errors.
'regress-444805.js',
'regress-crbug-489597.js',
'regress-crbug-620253.js',
// Just recursively loads itself.
'regress-8510.js',
];
const SKIPPED_DIRECTORIES = [
// Slow tests or tests that are too large to be used as input.
'embenchen',
'poppler',
'sqlite',
// Causes lots of failures.
'test262',
// Unavailable debug.Debug.
'v8/test/debugger',
'v8/test/inspector',
// Unsupported modules.
'v8/test/js-perf-test/Modules',
// Contains tests expected to error out on parsing.
'v8/test/message',
// Needs specific dependencies for load of various tests.
'v8/test/mjsunit/tools',
// Unsupported e4x standard.
'mozilla/data/e4x',
// Bails out fast without ReadableStream support.
'spidermonkey/non262/ReadableStream',
];
// Files used with a lower probability.
const SOFT_SKIPPED_FILES = [
// Tests with large binary content.
/^binaryen.*\.js/,
// Tests slow to parse.
// CrashTests:
/^jquery.*\.js/,
// Spidermonkey:
'regress-308085.js',
'regress-74474-002.js',
'regress-74474-003.js',
// V8:
'object-literal.js',
];
// Flags that lead to false positives or that are already passed by default.
const DISALLOWED_FLAGS = [
// Disallowed because features prefixed with "experimental" are not
// stabilized yet and would cause too much noise when enabled.
/^--experimental-.*/,
// Disallowed due to noise. We explicitly add --es-staging to job
// definitions, and all of these features are staged before launch.
/^--harmony-.*/,
// Disallowed because they are passed explicitly on the command line.
'--allow-natives-syntax',
'--debug-code',
'--es-staging',
'--wasm-staging',
'--expose-gc',
'--expose_gc',
'--icu-data-file',
'--random-seed',
// Disallowed due to false positives.
'--check-handle-count',
'--expose-debug-as',
'--expose-natives-as',
'--expose-trigger-failure',
'--mock-arraybuffer-allocator',
'natives', // Used in conjuction with --expose-natives-as.
/^--trace-path.*/,
];
// Flags only used with 25% probability.
const LOW_PROB_FLAGS_PROB = 0.25;
const LOW_PROB_FLAGS = [
// Flags that lead to slow test performance.
/^--gc-interval.*/,
/^--deopt-every-n-times.*/,
];
// Flags printing data, leading to false positives in differential fuzzing.
const DISALLOWED_DIFFERENTIAL_FUZZ_FLAGS = [
/^--gc-interval.*/,
/^--perf.*/,
/^--print.*/,
/^--stress-runs.*/,
/^--trace.*/,
'--expose-externalize-string',
'--interpreted-frames-native-stack',
'--stress-opt',
'--validate-asm',
];
const ALLOWED_RUNTIME_FUNCTIONS = new Set([
// List of allowed runtime functions. Others will be replaced with no-ops.
'ArrayBufferDetach',
'DeoptimizeFunction',
'DeoptimizeNow',
'EnableCodeLoggingForTesting',
'GetUndetectable',
'HeapObjectVerify',
'IsBeingInterpreted',
'NeverOptimizeFunction',
'OptimizeFunctionOnNextCall',
'OptimizeOsr',
'PrepareFunctionForOptimization',
'SetAllocationTimeout',
'SimulateNewspaceFull',
]);
const MAX_FILE_SIZE_BYTES = 128 * 1024; // 128KB
const MEDIUM_FILE_SIZE_BYTES = 32 * 1024; // 32KB
function _findMatch(iterable, candidate) {
for (const entry of iterable) {
if (typeof entry === 'string') {
if (entry === candidate) {
return true;
}
} else {
if (entry.test(candidate)) {
return true;
}
}
}
return false;
}
function _doesntMatch(iterable, candidate) {
return !_findMatch(iterable, candidate);
}
// Convert Windows path separators.
function normalize(testPath) {
return path.normalize(testPath).replace(/\\/g, '/');
}
function isTestSkippedAbs(absPath) {
const basename = path.basename(absPath);
if (_findMatch(SKIPPED_FILES, basename)) {
return true;
}
const normalizedTestPath = normalize(absPath);
for (const entry of SKIPPED_DIRECTORIES) {
if (normalizedTestPath.includes(entry)) {
return true;
}
}
// Avoid OOM/hangs through huge inputs.
const stat = fs.statSync(absPath);
return (stat && stat.size >= MAX_FILE_SIZE_BYTES);
}
function isTestSkippedRel(relPath) {
return generatedSkipped.has(normalize(relPath));
}
// For testing.
function getSoftSkipped() {
return SOFT_SKIPPED_FILES;
}
// For testing.
function getGeneratedSoftSkipped() {
return generatedSoftSkipped;
}
// For testing.
function getGeneratedSloppy() {
return generatedSloppy;
}
function isTestSoftSkippedAbs(absPath) {
const basename = path.basename(absPath);
if (_findMatch(this.getSoftSkipped(), basename)) {
return true;
}
// Graylist medium size files.
const stat = fs.statSync(absPath);
return (stat && stat.size >= MEDIUM_FILE_SIZE_BYTES);
}
function isTestSoftSkippedRel(relPath) {
return this.getGeneratedSoftSkipped().has(normalize(relPath));
}
function isTestSloppyRel(relPath) {
return this.getGeneratedSloppy().has(normalize(relPath));
}
function filterFlags(flags) {
return flags.filter(flag => {
return (
_doesntMatch(DISALLOWED_FLAGS, flag) &&
(_doesntMatch(LOW_PROB_FLAGS, flag) ||
random.choose(LOW_PROB_FLAGS_PROB)));
});
}
function filterDifferentialFuzzFlags(flags) {
return flags.filter(
flag => _doesntMatch(DISALLOWED_DIFFERENTIAL_FUZZ_FLAGS, flag));
}
function isAllowedRuntimeFunction(name) {
if (process.env.APP_NAME != 'd8') {
return false;
}
return ALLOWED_RUNTIME_FUNCTIONS.has(name);
}
module.exports = {
filterDifferentialFuzzFlags: filterDifferentialFuzzFlags,
filterFlags: filterFlags,
getGeneratedSoftSkipped: getGeneratedSoftSkipped,
getGeneratedSloppy: getGeneratedSloppy,
getSoftSkipped: getSoftSkipped,
isAllowedRuntimeFunction: isAllowedRuntimeFunction,
isTestSkippedAbs: isTestSkippedAbs,
isTestSkippedRel: isTestSkippedRel,
isTestSoftSkippedAbs: isTestSoftSkippedAbs,
isTestSoftSkippedRel: isTestSoftSkippedRel,
isTestSloppyRel: isTestSloppyRel,
}
#!/usr/bin/env python
# Copyright 2020 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
Launcher for the foozzie differential-fuzzing harness. Wraps foozzie
with Python2 for backwards-compatibility when bisecting.
"""
import os
import re
import subprocess
import sys
if __name__ == '__main__':
# In some cases or older versions, the python executable is passed as
# first argument. Let's be robust either way, with or without full
# path or version.
if re.match(r'.*python.*', sys.argv[1]):
args = sys.argv[2:]
else:
args = sys.argv[1:]
process = subprocess.Popen(['python2'] + args)
process.communicate()
sys.exit(process.returncode)
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Generate exceptions from full corpus test report.
*/
const program = require('commander');
const assert = require('assert');
const babelGenerator = require('@babel/generator').default;
const babelTemplate = require('@babel/template').default;
const babelTypes = require('@babel/types');
const fs = require('fs');
const p = require('path');
const prettier = require("prettier");
const SPLIT_LINES_RE = /^.*([\n\r]+|$)/gm;
const PARSE_RE = /^Parsing (.*) sloppy took (\d+) ms\.\n$/;
const MUTATE_RE = /^Mutating (.*) took (\d+) ms\.\n$/;
const PARSE_FAILED_RE = /^WARNING: failed to sloppy parse (.*)\n$/;
const PARSE_STRICT_FAILED_RE = /^WARNING: failed to strict parse (.*)\n$/;
const MUTATE_FAILED_RE = /^ERROR: Exception during mutate: (.*)\n$/;
// Add tests matching error regexp to result array.
function matchError(regexp, line, resultArray){
const match = line.match(regexp);
if (!match) return false;
const relPath = match[1];
assert(relPath);
resultArray.push(relPath);
return true;
}
// Sum up total duration of tests matching the duration regexp and
// map test -> duration in result map.
function matchDuration(regexp, line, resultMap){
const match = line.match(regexp);
if (!match) return false;
const relPath = match[1];
assert(relPath);
resultMap[relPath] = (resultMap[relPath] || 0) + parseInt(match[2]);
return true;
}
// Create lists of failed and slow tests from stdout of a fuzzer run.
function processFuzzOutput(outputFile){
const text = fs.readFileSync(outputFile, 'utf-8');
const lines = text.match(SPLIT_LINES_RE);
const failedParse = [];
const failedParseStrict = [];
const failedMutate = [];
const durationsMap = {};
for (const line of lines) {
if (matchError(PARSE_FAILED_RE, line, failedParse))
continue;
if (matchError(PARSE_STRICT_FAILED_RE, line, failedParseStrict))
continue;
if (matchError(MUTATE_FAILED_RE, line, failedMutate))
continue;
if (matchDuration(PARSE_RE, line, durationsMap))
continue;
if (matchDuration(MUTATE_RE, line, durationsMap))
continue;
}
// Tuples (absPath, duration).
const total = Object.entries(durationsMap);
// Tuples (absPath, duration) with 2s < duration <= 10s.
const slow = total.filter(t => t[1] > 2000 && t[1] <= 10000);
// Tuples (absPath, duration) with 10s < duration.
const verySlow = total.filter(t => t[1] > 10000);
// Assert there's nothing horribly wrong with the results.
// We have at least 2500 tests in the output.
assert(total.length > 2500);
// No more than 5% parse/mutation errors.
assert(failedParse.length + failedMutate.length < total.length / 20);
// No more than 10% slow tests
assert(slow.length < total.length / 10);
// No more than 2% very slow tests.
assert(verySlow.length < total.length / 50);
// Sort everything.
failedParse.sort();
failedParseStrict.sort();
failedMutate.sort();
function slowestFirst(a, b) {
return b[1] - a[1];
}
slow.sort(slowestFirst);
verySlow.sort(slowestFirst);
return [failedParse, failedParseStrict, failedMutate, slow, verySlow];
}
// List of string literals of failed tests.
function getLiteralsForFailed(leadingComment, failedList) {
const result = failedList.map(path => babelTypes.stringLiteral(path));
if (result.length) {
babelTypes.addComment(result[0], 'leading', leadingComment);
}
return result;
}
// List of string literals of slow tests with duration comments.
function getLiteralsForSlow(leadingComment, slowList) {
const result = slowList.map(([path, duration]) => {
const literal = babelTypes.stringLiteral(path);
babelTypes.addComment(
literal, 'trailing', ` ${duration / 1000}s`, true);
return literal;
});
if (result.length) {
babelTypes.addComment(result[0], 'leading', leadingComment);
}
return result;
}
function main() {
program
.version('0.0.1')
.parse(process.argv);
if (!program.args.length) {
console.log('Need to specify stdout reports of fuzz runs.');
return;
}
let skipped = [];
let softSkipped = [];
let sloppy = [];
for (const outputFile of program.args) {
const [failedParse, failedParseStrict, failedMutate, slow, verySlow] = (
processFuzzOutput(outputFile));
const name = p.basename(outputFile, p.extname(outputFile));
// Skip tests that fail to parse/mutate or are very slow.
skipped = skipped.concat(getLiteralsForFailed(
` Tests with parse errors from ${name} `, failedParse));
skipped = skipped.concat(getLiteralsForFailed(
` Tests with mutation errors from ${name} `, failedMutate));
skipped = skipped.concat(getLiteralsForSlow(
` Very slow tests from ${name} `, verySlow));
// Soft-skip slow but not very slow tests.
softSkipped = softSkipped.concat(getLiteralsForSlow(
` Slow tests from ${name} `, slow));
// Mark sloppy tests.
sloppy = sloppy.concat(getLiteralsForFailed(
` Tests requiring sloppy mode from ${name} `, failedParseStrict));
}
const fileTemplate = babelTemplate(`
/**
* @fileoverview Autogenerated exceptions. Created with gen_exceptions.js.
*/
'use strict';
const skipped = SKIPPED;
const softSkipped = SOFTSKIPPED;
const sloppy = SLOPPY;
module.exports = {
generatedSkipped: new Set(skipped),
generatedSoftSkipped: new Set(softSkipped),
generatedSloppy: new Set(sloppy),
}
`, {preserveComments: true});
const skippedArray = babelTypes.arrayExpression(skipped);
const softSkippedArray = babelTypes.arrayExpression(softSkipped);
const sloppyArray = babelTypes.arrayExpression(sloppy);
const statements = fileTemplate({
SKIPPED: skippedArray,
SOFTSKIPPED: softSkippedArray,
SLOPPY: sloppyArray,
});
const resultProgram = babelTypes.program(statements);
const code = babelGenerator(resultProgram, { comments: true }).code;
const prettyCode = prettier.format(code, { parser: "babel" });
fs.writeFileSync('generated/exceptions.js', prettyCode);
}
main();
#!/bin/bash
# Copyright 2020 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
APP_NAME=d8 node run.js -i $WEB_TESTS -o $OUTPUT -z -v -e -c chakra > chakra.log
APP_NAME=d8 node run.js -i $WEB_TESTS -o $OUTPUT -z -v -e -c v8 > v8.log
APP_NAME=d8 node run.js -i $WEB_TESTS -o $OUTPUT -z -v -e -c spidermonkey > spidermonkey.log
APP_NAME=d8 node run.js -i $WEB_TESTS -o $OUTPUT -z -v -e -c WebKit/JSTests > jstests.log
APP_NAME=d8 node run.js -i $WEB_TESTS -o $OUTPUT -z -v -e -c CrashTests > crashtests.log
node gen_exceptions.js v8.log spidermonkey.log chakra.log jstests.log crashtests.log
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Autogenerated exceptions. Created with gen_exceptions.js.
*/
"use strict";
const skipped = [
/* Tests with parse errors from v8 */
"v8/test/mjsunit/es6/block-let-contextual-sloppy.js",
"v8/test/mjsunit/es6/generators-parsing.js",
"v8/test/mjsunit/es6/object-literals-property-shorthand.js",
"v8/test/mjsunit/es6/sloppy-restrictive-block-function.js",
"v8/test/mjsunit/es7/exponentiation-operator.js",
"v8/test/mjsunit/harmony/bigint/property-names.js",
"v8/test/mjsunit/harmony/import-from-compilation-errored.js",
"v8/test/mjsunit/harmony/import-from-evaluation-errored.js",
"v8/test/mjsunit/harmony/import-from-fetch-errored.js",
"v8/test/mjsunit/harmony/import-from-instantiation-errored.js",
"v8/test/mjsunit/harmony/numeric-separator.js",
"v8/test/mjsunit/harmony/private-fields-special-object.js",
"v8/test/mjsunit/html-comments.js",
"v8/test/mjsunit/ignition/dead-code-source-position.js",
"v8/test/mjsunit/regress/regress-436893.js",
"v8/test/mjsunit/regress/regress-5692.js",
"v8/test/mjsunit/regress/regress-740694.js",
"v8/test/mjsunit/regress/regress-744292.js",
"v8/test/mjsunit/regress/regress-797581.js",
"v8/test/mjsunit/regress/regress-800651.js",
"v8/test/mjsunit/regress/regress-crbug-412208.js",
"v8/test/mjsunit/regress/regress-crbug-934166.js",
"v8/test/mjsunit/serialize-embedded-error.js",
"v8/test/mjsunit/switch.js",
/* Tests with mutation errors from v8 */
"v8/test/mjsunit/harmony/private-accessors.js",
"v8/test/mjsunit/harmony/private-methods-empty-inner.js",
"v8/test/mjsunit/harmony/private-methods.js",
"v8/test/mjsunit/harmony/static-private-methods.js",
/* Very slow tests from v8 */
"v8/test/mjsunit/regress/wasm/regress-810973b.js", // 12.121s
/* Tests with parse errors from spidermonkey */
"spidermonkey/non262/BigInt/property-name-guessed-name.js",
"spidermonkey/non262/BigInt/property-name.js",
"spidermonkey/non262/Exceptions/catchguard-002-n.js",
"spidermonkey/non262/Exceptions/catchguard-003-n.js",
"spidermonkey/non262/Function/rest-parameter-names.js",
"spidermonkey/non262/Unicode/regress-352044-02-n.js",
"spidermonkey/non262/arrow-functions/arrow-not-as-end-of-statement.js",
"spidermonkey/non262/arrow-functions/arrow-returning-arrow-with-block-body-followed-by-regexp.js",
"spidermonkey/non262/async-functions/duplicate-__proto__.js",
"spidermonkey/non262/destructuring/bug1396261.js",
"spidermonkey/non262/destructuring/duplicate-__proto__.js",
"spidermonkey/non262/destructuring/yield-in-object-destr-function.js",
"spidermonkey/non262/destructuring/yield-in-object-destr-script.js",
"spidermonkey/non262/destructuring/yield-with-escape-in-object-destr-function.js",
"spidermonkey/non262/destructuring/yield-with-escape-in-object-destr-script.js",
"spidermonkey/non262/extensions/inc-dec-functioncall.js",
"spidermonkey/non262/extensions/regress-406572.js",
"spidermonkey/non262/fields/await-identifier-module-1.js",
"spidermonkey/non262/fields/await-identifier-module-2.js",
"spidermonkey/non262/fields/await-identifier-script.js",
"spidermonkey/non262/generators/syntax.js",
"spidermonkey/non262/generators/yield-non-regexp.js",
"spidermonkey/non262/jit/regress-451673.js",
"spidermonkey/non262/lexical-environment/block-scoped-functions-annex-b-if.js",
"spidermonkey/non262/lexical-environment/block-scoped-functions-annex-b-parameter.js",
"spidermonkey/non262/module/bug1488117-import-namespace.js",
"spidermonkey/non262/module/bug1488117.js",
"spidermonkey/non262/regress/regress-243389-n.js",
"spidermonkey/non262/regress/regress-319391.js",
"spidermonkey/non262/regress/regress-350253.js",
"spidermonkey/non262/regress/regress-351515.js",
"spidermonkey/non262/regress/regress-452498-168-2.js",
"spidermonkey/non262/regress/regress-462292.js",
"spidermonkey/non262/regress/regress-467495-03.js",
"spidermonkey/non262/regress/regress-467495-04.js",
"spidermonkey/non262/regress/regress-467495-05.js",
"spidermonkey/non262/regress/regress-467495-06.js",
"spidermonkey/non262/regress/regress-609617.js",
"spidermonkey/non262/regress/regress-98901.js",
"spidermonkey/non262/statements/for-of-iterator-close.js",
"spidermonkey/test/expected/export/multi-header.js",
"spidermonkey/test/expected/export/reftest-error-syntaxerror.js",
"spidermonkey/test/expected/export/regular.js",
"spidermonkey/test/expected/import/files/local/smTempBranch/language/export/escaped-foobarbaz.js",
"spidermonkey/test/fixtures/export/.ignore.js",
"spidermonkey/test/fixtures/export/multi-header.js",
"spidermonkey/test/fixtures/export/reftest-error-syntaxerror.js",
"spidermonkey/test/fixtures/export/regular.js",
/* Very slow tests from spidermonkey */
"spidermonkey/non262/regress/regress-308085.js", // 14.519s
/* Tests with parse errors from chakra */
"chakra/Basics/keyword.js",
"chakra/Bugs/OS_4341640.js",
"chakra/Bugs/SuperAccessInGlobalLambda.js",
"chakra/Closures/bug_OS_2525694.js",
"chakra/Function/callsideeffects.js",
"chakra/Function/crosssite_bind_main.js",
"chakra/Function/deferredBadContinue.js",
"chakra/LetConst/defer1.js",
"chakra/LetConst/letlet.js",
"chakra/LetConst/tdz2.js",
"chakra/Optimizer/test115.js",
"chakra/Optimizer/test135.js",
"chakra/Optimizer/test146.js",
"chakra/Scanner/InvalidCharacter.js",
"chakra/Strings/long_concatstr.js",
"chakra/benchmarks/ARES-6/Babylon/babylon-blob.js",
"chakra/es6/DeferParseMethods.js",
"chakra/es6/ES6Iterators-forof.js",
"chakra/es6/blockscope-functionbinding.js",
"chakra/es6/bug_OS17895855.js",
"chakra/es6/bug_issue_3247_dep.js",
"chakra/es6/bug_issue_5994.js",
"chakra/es6/forInEdgeCases.js",
"chakra/es6/generators-syntax.js",
"chakra/es6/globalCatchNewTargetSyntaxError.js",
"chakra/es6/globalNewTargetSyntaxError.js",
"chakra/es6/globalParamCatchNewTargetSyntaxError.js",
"chakra/es6/lambda-expr.js",
"chakra/es6/objlit.js",
"chakra/es6/supersyntax02.js",
"chakra/es6/supersyntax05.js",
"chakra/es6/supersyntax06.js",
"chakra/es6/unicode_6_identifier_Blue511452.js",
"chakra/es6/unicode_6_identifier_Blue524737.js",
"chakra/es6module/GetModuleNamespace.js",
"chakra/es6module/ModuleCircularBar.js",
"chakra/es6module/ModuleCircularFoo.js",
"chakra/es6module/ModuleComplexExports.js",
"chakra/es6module/ModuleComplexReexports.js",
"chakra/es6module/ModuleDefaultExport1.js",
"chakra/es6module/ModuleDefaultExport2.js",
"chakra/es6module/ModuleDefaultExport3.js",
"chakra/es6module/ModuleDefaultExport4.js",
"chakra/es6module/ModuleDefaultReexport.js",
"chakra/es6module/ModuleReexportDefault.js",
"chakra/es6module/ModuleSimpleExport.js",
"chakra/es6module/ModuleSimpleReexport.js",
"chakra/es6module/ValidExportDefaultStatement1.js",
"chakra/es6module/ValidExportDefaultStatement2.js",
"chakra/es6module/ValidExportStatements.js",
"chakra/es6module/ValidExportStatements2.js",
"chakra/es6module/ValidImportStatements.js",
"chakra/es6module/ValidReExportStatements.js",
"chakra/es6module/bug_OS12095746.js",
"chakra/es6module/bug_OS12095746_mod0.js",
"chakra/es6module/bug_OS12095746_mod1.js",
"chakra/es6module/bug_OS12095746_mod2.js",
"chakra/es6module/bug_OS12095746_moddep.js",
"chakra/es6module/bug_OS12113549_module1.js",
"chakra/es6module/bug_OS14562349.js",
"chakra/es6module/bug_issue_3076.js",
"chakra/es6module/bug_issue_3257/mod/mod0.js",
"chakra/es6module/bug_issue_3257/mod1.js",
"chakra/es6module/bug_issue_3257/mod2/mod2.js",
"chakra/es6module/bug_issue_3257/script/script0.js",
"chakra/es6module/bug_issue_5777.js",
"chakra/es6module/dynamic_import_promises_5796.js",
"chakra/es6module/exportBinding.js",
"chakra/es6module/exportmodule.js",
"chakra/es6module/module-3250-bug-dep.js",
"chakra/es6module/module-3250-bug-dep2.js",
"chakra/es6module/module-3250-ext-a.js",
"chakra/es6module/module-3250-ext-b.js",
"chakra/es6module/moduleExport1.js",
"chakra/es6module/moduleImportTheError.js",
"chakra/es6module/moduleThrowAnError.js",
"chakra/es6module/module_1_2645.js",
"chakra/es6module/module_2_2645.js",
"chakra/es6module/module_4482_dep1.js",
"chakra/es6module/module_4482_dep2.js",
"chakra/es6module/module_4482_dep3.js",
"chakra/es6module/module_4570_dep1.js",
"chakra/es6module/module_4570_dep2.js",
"chakra/es6module/moduletest2_mod0.js",
"chakra/es6module/moduletest2_mod1a.js",
"chakra/es6module/moduletest2_mod1b.js",
"chakra/es6module/moduletest2_mod2a.js",
"chakra/es6module/otherModule.js",
"chakra/es6module/passmodule.js",
"chakra/es6module/testDynamicImportfromModule.js",
"chakra/es7/json_superset.js",
"chakra/inlining/bug_gh6303.js",
"chakra/inlining/profilingbug.js",
"chakra/stackfunc/602481.js",
"chakra/strict/bug212755.js",
"chakra/strict/delete.js",
"chakra/strict/formal_samename1.js",
"chakra/strict/formal_samename2.js",
"chakra/strict/multiunit.js",
"chakra/strict/nonSimpleParameterList.js",
"chakra/strict/strictargs-deferred.js",
"chakra/strict/strictargs2-deferred.js",
"chakra/strict/strictargs3-deferred.js",
"chakra/strict/stricteval-deferred.js",
"chakra/strict/stricteval2-deferred.js",
"chakra/strict/strictkwd-deferred.js",
/* Tests with mutation errors from chakra */
"chakra/es6module/bug_issue_3257.js",
"chakra/es6module/moduleUrlInError.js",
"chakra/es6module/moduletest1.js",
"chakra/es6module/moduletest2.js",
/* Very slow tests from chakra */
"chakra/benchmarks/ARES-6/Air/payload-imaging-gaussian-blur-gaussianBlur.js", // 21.782s
"chakra/benchmarks/ARES-6/Air/payload-gbemu-executeIteration.js", // 18.461s
/* Tests with parse errors from jstests */
"WebKit/JSTests/es6/non-strict_function_semantics_function_statements_in_if-statement_clauses.js",
"WebKit/JSTests/stress/arrowfunction-lexical-bind-this-8.js",
"WebKit/JSTests/stress/big-int-as-property-name.js",
"WebKit/JSTests/stress/for-let-comma.js",
"WebKit/JSTests/stress/import-basic.js",
"WebKit/JSTests/stress/import-from-eval.js",
"WebKit/JSTests/stress/import-reject-with-exception.js",
"WebKit/JSTests/stress/import-tests/cocoa.js",
"WebKit/JSTests/stress/import-tests/multiple.js",
"WebKit/JSTests/stress/import-tests/multiple2.js",
"WebKit/JSTests/stress/import-tests/should.js",
"WebKit/JSTests/stress/import-with-empty-string.js",
"WebKit/JSTests/stress/module-namespace-access-change.js",
"WebKit/JSTests/stress/module-namespace-access-non-constant.js",
"WebKit/JSTests/stress/module-namespace-access-poly.js",
"WebKit/JSTests/stress/module-namespace-access-transitive-exports.js",
"WebKit/JSTests/stress/module-namespace-access.js",
"WebKit/JSTests/stress/printableModuleKey-should-never-throw.js",
"WebKit/JSTests/stress/re-execute-error-module.js",
"WebKit/JSTests/stress/regress-170732.js",
"WebKit/JSTests/stress/regress-191856.js",
"WebKit/JSTests/stress/resources/error-module.js",
"WebKit/JSTests/stress/resources/module-namespace-access-transitive-exports-2.js",
"WebKit/JSTests/stress/resources/module-namespace-access-transitive-exports.js",
"WebKit/JSTests/stress/resources/module-namespace-access.js",
"WebKit/JSTests/stress/sloppy-mode-function-hoisting.js",
"WebKit/JSTests/stress/yield-label.js",
/* Tests with parse errors from crashtests */
"CrashTests/115674352/util.js",
"CrashTests/132918471/fast/js/resources/js-test-post.js",
"CrashTests/135733397/resources/cookies-test-post.js",
"CrashTests/158344541/support/refTestWait.js",
"CrashTests/178811021/media-file.js",
"CrashTests/178811021/video-test.js",
"CrashTests/31681819/fast/js/resources/js-test-post.js",
"CrashTests/4506116685037568/00422.js",
"CrashTests/4523272292270080/02509.js",
"CrashTests/4531783459405824/01124.js",
"CrashTests/4563969814560768/1.0.2/conformance/resources/webgl-test-utils.js",
"CrashTests/4563969814560768/1.0.2/conformance/resources/webgl-test.js",
"CrashTests/4563969814560768/1.0.2/resources/js-test-pre.js",
"CrashTests/4592095397150720/619.js",
"CrashTests/4620742728613888/02272.js",
"CrashTests/4675875294674944/04443.js",
"CrashTests/4676310267068416/00041.js",
"CrashTests/4676310267068416/meta-00041.js",
"CrashTests/4689880216240128/meta-00116.js",
"CrashTests/4710304564903936/resources/js-test-post.js",
"CrashTests/4715062213476352/meta-00915.js",
"CrashTests/4730791635451904/00498.js",
"CrashTests/4731918950203392/04316.js",
"CrashTests/4747813124571136/00737.js",
"CrashTests/4777280799506432/01745.js",
"CrashTests/4784915024707584/meta-00090.js",
"CrashTests/4786126975139840/00686.js",
"CrashTests/4804606392795136/00345.js",
"CrashTests/4823335117783040/meta-00192.js",
"CrashTests/4827148775849984/02704.js",
"CrashTests/4835573090222080/00096.js",
"CrashTests/4835573090222080/meta-00096.js",
"CrashTests/4837730048278528/03052.js",
"CrashTests/4843490131312640/03475.js",
"CrashTests/4850895428517888/2670.js",
"CrashTests/4854644212105216/392.js",
"CrashTests/4855156194934784/meta-00080.js",
"CrashTests/4899093893742592/02412.js",
"CrashTests/4914294111076352/resources/worker-common.js",
"CrashTests/4920133693472768/09913.js",
"CrashTests/4924640359088128/resources/methods.js",
"CrashTests/4966722004058112/01202.js",
"CrashTests/4996582417891328/00314.js",
"CrashTests/5010966233481216/05443.js",
"CrashTests/5016449390477312/02595.js",
"CrashTests/5019028805124096/01923.js",
"CrashTests/5024919414112256/02190.js",
"CrashTests/5026147325968384/01281.js",
"CrashTests/5034236802498560/00038.js",
"CrashTests/5034236802498560/meta-00038.js",
"CrashTests/5036266378756096/resources/js-test.js",
"CrashTests/5040821977219072/07176.js",
"CrashTests/5047964758441984/02170.js",
"CrashTests/5064701201350656/mjsunit_modified.js",
"CrashTests/5071018176282624/05782.js",
"CrashTests/5073353348087808/03720.js",
"CrashTests/5083537469079552/03453.js",
"CrashTests/5091969183776768/js/angular.js",
"CrashTests/5104674803023872/meta-00066.js",
"CrashTests/5110246766673920/117.js",
"CrashTests/5126730184654848/00846.js",
"CrashTests/5140656268640256/resources/interpolation-test.js",
"CrashTests/5151090662178816/01492.js",
"CrashTests/5153368765628416/00787.js",
"CrashTests/5157575680327680/06055.js",
"CrashTests/5159014924288000/01496.js",
"CrashTests/5164793027624960/01357.js",
"CrashTests/5165045173846016/Common/MV.js",
"CrashTests/5168023154720768/meta-00125.js",
"CrashTests/5171658670473216/02099.js",
"CrashTests/5190716938387456/05795.js",
"CrashTests/5192473061359616/meta-00780.js",
"CrashTests/5197954434596864/01324.js",
"CrashTests/5200019587334144/meta-00398.js",
"CrashTests/5222394685292544/resources/stress-js-execution.js",
"CrashTests/5226258591121408/04850.js",
"CrashTests/5226692407984128/meta-00030.js",
"CrashTests/5238861996490752/01351.js",
"CrashTests/5242104612651008/mjsunit_modified.js",
"CrashTests/5254331529166848/meta-00409.js",
"CrashTests/5254663852261376/meta-00497.js",
"CrashTests/5280655383724032/meta-00355.js",
"CrashTests/5283736101322752/00921.js",
"CrashTests/5289653387919360/635.js",
"CrashTests/5301431549820928/meta-00738.js",
"CrashTests/5335637787934720/mersenne.js",
"CrashTests/5337864091729920/00078.js",
"CrashTests/5346139261108224/meta-00086.js",
"CrashTests/5354535555825664/01561.js",
"CrashTests/5402562393276416/meta-00565.js",
"CrashTests/5418169017303040/156.js",
"CrashTests/5435516837429248/02591.js",
"CrashTests/5443796254064640/08661.js",
"CrashTests/5474124668600320/meta-00992.js",
"CrashTests/5486126228570112/02840.js",
"CrashTests/5487631620112384/animations/resources/animation-test-helpers.js",
"CrashTests/5521703332741120/00376.js",
"CrashTests/5530153792045056/meta-00910.js",
"CrashTests/5540548491608064/01146.js",
"CrashTests/5541203771916288/currentscript.js",
"CrashTests/5559694775025664/imported/w3c/html-templates/testcommon.js",
"CrashTests/5559694775025664/resources/testharness.js",
"CrashTests/5559694775025664/resources/testharnessreport.js",
"CrashTests/5568247077011456/04042.js",
"CrashTests/5593713261412352/319.js",
"CrashTests/5606041047007232/02795.js",
"CrashTests/5606702255964160/meta-00168.js",
"CrashTests/5615411944226816/02684.js",
"CrashTests/5630063870214144/02130.js",
"CrashTests/5630225822121984/03637.js",
"CrashTests/5635645835182080/worker-serviceworker-7636bedbbb1f120d.js",
"CrashTests/5639628713492480/04139.js",
"CrashTests/5642849944993792/resources/js-test.js",
"CrashTests/5644307466878976/__MACOSX/._audio.js",
"CrashTests/5644307466878976/__MACOSX/._processor.js",
"CrashTests/5649862583648256/meta-00236.js",
"CrashTests/5650039238033408/00812.js",
"CrashTests/5651703040835584/resources/testharnessreport.js",
"CrashTests/5652465613406208/4584.js",
"CrashTests/5661345388167168/resources/stress-js-execution.js",
"CrashTests/5668694740172800/meta-00294.js",
"CrashTests/5672678890405888/resources/js-test.js",
"CrashTests/5685487336161280/03642.js",
"CrashTests/5686447370665984/sdk/tests/conformance/ogles/ogles-utils.js",
"CrashTests/5686447370665984/sdk/tests/conformance/resources/glsl-conformance-test.js",
"CrashTests/5686447370665984/sdk/tests/conformance/resources/webgl-test-utils.js",
"CrashTests/5686447370665984/sdk/tests/resources/js-test-pre.js",
"CrashTests/5688866685321216/09854.js",
"CrashTests/5689884189392896/02723.js",
"CrashTests/5694701996867584/conformance/resources/webgl-test.js",
"CrashTests/5703976838234112/test.js",
"CrashTests/5707472246472704/1443.js",
"CrashTests/5721502735532032/03042.js",
"CrashTests/5734750167105536/01271.js",
"CrashTests/5735023732064256/meta-00070.js",
"CrashTests/5736353084342272/resources/testharness.js",
"CrashTests/5737388710821888/resources/js-test.js",
"CrashTests/5744365229441024/resources/testharness.js",
"CrashTests/5745342726537216/meta-00053.js",
"CrashTests/5755508264534016/00224.js",
"CrashTests/5763511307337728/04651.js",
"CrashTests/5774432061095936/00972.js",
"CrashTests/5798263663099904/01459.js",
"CrashTests/5802116248764416/06966.js",
"CrashTests/5806021251432448/background.js",
"CrashTests/58219635/fast/js/resources/js-test-post.js",
"CrashTests/5826758986170368/resources/js-test-post.js",
"CrashTests/5841445051170816/resources/js-test-pre.js",
"CrashTests/5842510916091904/resources/webgl_test_files/resources/js-test-post.js",
"CrashTests/58693299/selfhtml.js",
"CrashTests/5910324886634496/02597.js",
"CrashTests/5925149103357952/webaudio/resources/audit.js",
"CrashTests/5931087833333760/03890.js",
"CrashTests/5933875666616320/01048.js",
"CrashTests/5949184339083264/poc.js",
"CrashTests/5950573451804672/494.js",
"CrashTests/5950617700007936/01848.js",
"CrashTests/5970316012290048/414.js",
"CrashTests/5996165326962688/meta-00146.js",
"CrashTests/6010230465626112/resources/webgl_test_files/js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js",
"CrashTests/6018592823836672/support/refTestWait.js",
"CrashTests/6026840030314496/00848.js",
"CrashTests/6037361396809728/02741.js",
"CrashTests/6049932086083584/03169.js",
"CrashTests/6051257375784960/03082.js",
"CrashTests/6071110049988608/00548.js",
"CrashTests/6073192676327424/resources/js-test-pre.js",
"CrashTests/6085702952681472/00521.js",
"CrashTests/6113149884563456/02823.js",
"CrashTests/6150179231105024/conformance/resources/webgl-test.js",
"CrashTests/6158905865666560/meta-00624.js",
"CrashTests/6179220893204480/02159.js",
"CrashTests/6183415490019328/02656.js",
"CrashTests/6198951751188480/1248.js",
"CrashTests/6204924829630464/meta-00272.js",
"CrashTests/6216405020835840/03985.js",
"CrashTests/6218202061209600/mersenne.js",
"CrashTests/6220111297118208/meta-00050.js",
"CrashTests/6223202209234944/02648.js",
"CrashTests/6239384157552640/meta-00271.js",
"CrashTests/6250055858126848/04619.js",
"CrashTests/6255231244697600/meta-00216.js",
"CrashTests/6255916311379968/1372.js",
"CrashTests/6259138054324224/meta-00172.js",
"CrashTests/6278159702425600/01463.js",
"CrashTests/6280577705705472/1146.js",
"CrashTests/6285336190124032/01621.js",
"CrashTests/6295241556492288/01763.js",
"CrashTests/6304143111356416/00782.js",
"CrashTests/6328755580567552/resources/js-test.js",
"CrashTests/6328755580567552/svg/dynamic-updates/resources/SVGTestCase.js",
"CrashTests/6330764245073920/poc1.js",
"CrashTests/6332832186761216/00681.js",
"CrashTests/6339944789049344/04142.js",
"CrashTests/6345007341764608/00699.js",
"CrashTests/6351789088833536/meta-00122.js",
"CrashTests/6352599495475200/meta-00093.js",
"CrashTests/6358320674242560/resources/js-test.js",
"CrashTests/6359996105359360/934166-poc.js",
"CrashTests/6362821967740928/00524.js",
"CrashTests/6374053756272640/824.js",
"CrashTests/6387037962240000/02996.js",
"CrashTests/6394941698998272/meta-00167.js",
"CrashTests/6403694305476608/meta-00079.js",
"CrashTests/6405187880353792/meta-00826.js",
"CrashTests/6406267560263680/02111.js",
"CrashTests/6406622734974976/meta-00188.js",
"CrashTests/6427802493779968/meta-00335.js",
"CrashTests/6440904627060736/meta-00149.js",
"CrashTests/6443097497010176/1.0.2/resources/webgl_test_files/conformance/resources/webgl-test-utils.js",
"CrashTests/6443097497010176/1.0.2/resources/webgl_test_files/conformance/resources/webgl-test.js",
"CrashTests/6443097497010176/1.0.2/resources/webgl_test_files/resources/js-test-pre.js",
"CrashTests/6443097497010176/1.0.2/resources/webkit-webgl-test-harness.js",
"CrashTests/6449605693931520/meta-00261.js",
"CrashTests/6452658006392832/meta-00824.js",
"CrashTests/6463535346614272/meta-00886.js",
"CrashTests/6509855193169920/03031.js",
"CrashTests/6530413356122112/meta-00391.js",
"CrashTests/6541223017054208/01484.js",
"CrashTests/6550225930944512/mnt/scratch0/clusterfuzz/slave-bot/inputs/fuzzers/inferno_twister_custom_bundle/inferno_twister_custom_bundle_data/moz_tests/dom/workers/test/threadErrors_worker1.js",
"CrashTests/6552552797503488/bug_41414141.js",
"CrashTests/6576437049950208/conformance/resources/glsl-generator.js",
"CrashTests/6576437049950208/resources/js-test-pre.js",
"CrashTests/6586504922267648/00672.js",
"CrashTests/6597230699216896/meta-00299.js",
"CrashTests/6613865297084416/builds/chromium-browser-syzyasan_win32-release/revisions/asan-win32-release-276100/resources/inspector/main/Main.js",
"CrashTests/6622275291840512/resources/js-test.js",
"CrashTests/6644133880397824/00752.js",
"CrashTests/6646069054013440/poc.js",
"CrashTests/6658388688371712/00042.js",
"CrashTests/6659440421109760/00027.js",
"CrashTests/6695292278931456/04706.js",
"CrashTests/6727300586405888/builds/chromium-browser-syzyasan_win32-release/revisions/asan-win32-release-259551/resources/inspector/Main.js",
"CrashTests/6731147175526400/meta-00107.js",
"CrashTests/6744125769252864/494.js",
/* Tests with mutation errors from crashtests */
"CrashTests/4542853924782080/01450.js",
"CrashTests/4575654914293760/01532.js",
"CrashTests/4652594229411840/00000.js",
"CrashTests/4656490341466112/00126.js",
"CrashTests/4672370177736704/00528.js",
"CrashTests/4798856567717888/04694.js",
"CrashTests/4804923870150656/03027.js",
"CrashTests/4895570342707200/02467.js",
"CrashTests/4983976359100416/02090.js",
"CrashTests/5087167542853632/02505.js",
"CrashTests/5136618234314752/00136.js",
"CrashTests/5518580170096640/00960.js",
"CrashTests/5604116503199744/00316.js",
"CrashTests/5631123291111424/00708.js",
"CrashTests/5701970444288000/00241.js",
"CrashTests/5834909260709888/01407.js",
"CrashTests/5927058168610816/01389.js",
"CrashTests/6005687605002240/00969.js",
"CrashTests/6396053053243392/00161.js",
"CrashTests/6491889133158400/01408.js",
"CrashTests/6666268416671744/09877.js",
/* Very slow tests from crashtests */
"CrashTests/5680390288441344/scripts/extension.js", // 48.473s
"CrashTests/5680390288441344/scripts/feedback.js", // 24.001s
"CrashTests/5666182802309120/binaryen-1564.js", // 18.342s
"CrashTests/5306741051621376/binaryen-2962.js", // 16.455s
"CrashTests/6071297320747008/324.js", // 14.031s
"CrashTests/6250982932086784/binaryen-538.js", // 11.258s
"CrashTests/5187171718529024/844.js", // 10.189s
"CrashTests/4741082707132416/binaryen-1700.js", // 10.129s
];
const softSkipped = [
/* Slow tests from v8 */
"v8/test/mjsunit/object-literal.js", // 4.219s
"v8/test/mjsunit/wasm/wasm-module-builder.js", // 4.07s
/* Slow tests from spidermonkey */
"spidermonkey/non262/statements/regress-74474-003.js", // 7.228s
"spidermonkey/non262/statements/regress-74474-002.js", // 7.209s
"spidermonkey/non262/extensions/dataview.js", // 3.845s
/* Slow tests from chakra */
"chakra/TaggedIntegers/loops.js", // 7.354s
"chakra/benchmarks/ARES-6/Air/payload-typescript-scanIdentifier.js", // 7.011s
"chakra/benchmarks/Octane/crypto.js", // 4.004s
"chakra/benchmarks/Octane_Closure/crypto.js", // 3.178s
"chakra/benchmarks/ARES-6/Air/payload-airjs-ACLj8C.js", // 2.918s
/* Slow tests from jstests */
"WebKit/JSTests/stress/v8-crypto-strict.js", // 3.023s
"WebKit/JSTests/stress/v8-regexp-strict.js", // 2.555s
/* Slow tests from crashtests */
"CrashTests/5082337238712320/binaryen-3268.js", // 9.621s
"CrashTests/4602127226241024/js/jquery.js", // 9.337s
"CrashTests/6472801805664256/common/js/frameworks/jquery-1.8.2.min.js", // 8.859s
"CrashTests/5657116044951552/scripts/libs/jquery.js", // 8.649s
"CrashTests/4614296351277056/js/jquery-1.8.0.min.js", // 8.446s
"CrashTests/5550653104455680/js/jquery-1.8.0.min.js", // 8.426s
"CrashTests/5091969183776768/js/jquery.js", // 8.396s
"CrashTests/4612142496743424/binaryen-1882.js", // 8.101s
"CrashTests/5049543056424960/inc/jquery-2.1.0.min.js", // 7.912s
"CrashTests/6183950024441856/common/widget-api/widgets/common/jquery-1.7.1.min.js", // 7.454s
"CrashTests/6183950024441856/common/components/menu/js/jquery-1.7.1.min.js", // 7.409s
"CrashTests/5365583999664128/extensionData/plugins/4_jquery_1_7_1.js", // 7.298s
"CrashTests/4615141375344640/lib/jquery.js", // 7.144s
"CrashTests/6183950024441856/common/js/jquery-1.7.1.min.js", // 7.133s
"CrashTests/5657174977806336/binaryen-1398.js", // 6.913s
"CrashTests/6327982568898560/binaryen-862.js", // 6.736s
"CrashTests/4633495124312064/634.js", // 5.399s
"CrashTests/5689977077891072/01770.js", // 5.345s
"CrashTests/6636948839202816/121.js", // 5.31s
"CrashTests/5365583999664128/extensionData/plugins/17_jQuery.js", // 5.234s
"CrashTests/5533984447266816/626.js", // 5.002s
"CrashTests/4528969625894912/encaiiljifbdbjlphpgpiimidegddhic/lib/3rdparty/jquery.js", // 4.998s
"CrashTests/5274731158568960/test2.js", // 4.907s
"CrashTests/4528969625894912/lib/3rdparty/jquery.js", // 4.847s
"CrashTests/6103088053354496/965.js", // 4.574s
"CrashTests/5293298093391872/65.js", // 3.944s
"CrashTests/6215250211504128/05886.js", // 3.928s
"CrashTests/6107728614522880/wasm-hashset/many-test.js", // 3.235s
"CrashTests/5157721919979520/00935.js", // 3.224s
"CrashTests/5804707603021824/workers/wasm-hashset/worker.js", // 3.116s
"CrashTests/6107728614522880/wasm-hashset/worker.js", // 3.115s
"CrashTests/4986854798262272/js/webgl-test-utils.js", // 3.098s
"CrashTests/4764215218012160/workers/wasm-hashset/worker.js", // 3.092s
"CrashTests/4764215218012160/workers/wasm-hashset/test.js", // 3.064s
"CrashTests/5970862301904896/wasm-hashset/many-test.js", // 3.037s
"CrashTests/6264668110323712/js/webgl-test-utils.js", // 3.031s
"CrashTests/5144726426222592/957.js", // 3.028s
"CrashTests/4521096081309696/workers/wasm-hashset/many-worker-2.js", // 3.007s
"CrashTests/4727886732066816/03031.js", // 2.945s
"CrashTests/6171607952523264/workers/wasm-hashset/many-test-2.js", // 2.924s
"CrashTests/5804707603021824/workers/wasm-hashset/many-test.js", // 2.92s
"CrashTests/5903614327128064/js/webgl-test-utils.js", // 2.892s
"CrashTests/5474186315956224/js/webgl-test-utils.js", // 2.881s
"CrashTests/5720170289692672/js/webgl-test-utils.js", // 2.88s
"CrashTests/5709689405571072/js/webgl-test-utils.js", // 2.87s
"CrashTests/4808534067838976/113.js", // 2.852s
"CrashTests/5150788929454080/js/webgl-test-utils.js", // 2.842s
"CrashTests/4521096081309696/workers/wasm-hashset/many-test-2.js", // 2.839s
"CrashTests/4750804070957056/js/webgl-test-utils.js", // 2.837s
"CrashTests/5877660912451584/js/webgl-test-utils.js", // 2.831s
"CrashTests/6117827240263680/js/webgl-test-utils.js", // 2.821s
"CrashTests/5649522772541440/js/webgl-test-utils.js", // 2.821s
"CrashTests/6207235662020608/js/webgl-test-utils.js", // 2.81s
"CrashTests/5081168717545472/js/webgl-test-utils.js", // 2.793s
"CrashTests/6113858805301248/js/webgl-test-utils.js", // 2.781s
"CrashTests/4895116383485952/js/webgl-test-utils.js", // 2.767s
"CrashTests/5205072808771584/js/webgl-test-utils.js", // 2.766s
"CrashTests/5550653104455680/js/esprima.js", // 2.758s
"CrashTests/5540518327746560/js/webgl-test-utils.js", // 2.751s
"CrashTests/6307834848608256/js/webgl-test-utils.js", // 2.723s
"CrashTests/4561088605323264/js/webgl-test-utils.js", // 2.722s
"CrashTests/5152046202093568/binaryen-397.js", // 2.721s
"CrashTests/4614296351277056/js/esprima.js", // 2.72s
"CrashTests/5289255386742784/js/webgl-test-utils.js", // 2.718s
"CrashTests/5636770818686976/00408.js", // 2.718s
"CrashTests/6021155845308416/js/webgl-test-utils.js", // 2.708s
"CrashTests/5316130750332928/js/webgl-test-utils.js", // 2.694s
"CrashTests/5630410519478272/916.js", // 2.685s
"CrashTests/4763495091142656/js/webgl-test-utils.js", // 2.676s
"CrashTests/6643859697434624/00989.js", // 2.672s
"CrashTests/6578304131006464/js/webgl-test-utils.js", // 2.63s
"CrashTests/5921882795933696/js/webgl-test-utils.js", // 2.613s
"CrashTests/5720530023612416/binaryen-1954.js", // 2.592s
"CrashTests/5753604559470592/03311.js", // 2.589s
"CrashTests/4780408753094656/js/webgl-test-utils.js", // 2.584s
"CrashTests/6103004909666304/js/webgl-test-utils.js", // 2.582s
"CrashTests/5940011987107840/js/webgl-test-utils.js", // 2.569s
"CrashTests/6612369747476480/04469.js", // 2.566s
"CrashTests/5766886287081472/js/webgl-test-utils.js", // 2.561s
"CrashTests/5130481752735744/817.js", // 2.557s
"CrashTests/5667434598760448/js/webgl-test-utils.js", // 2.557s
"CrashTests/5304417640513536/js/webgl-test-utils.js", // 2.557s
"CrashTests/5069958615400448/js/webgl-test-utils.js", // 2.539s
"CrashTests/5803513008095232/js/webgl-test-utils.js", // 2.524s
"CrashTests/5684927436423168/js/webgl-test-utils.js", // 2.521s
"CrashTests/6343749881036800/01604.js", // 2.516s
"CrashTests/6159546553466880/js/webgl-test-utils.js", // 2.506s
"CrashTests/5436877461782528/binaryen-4415.js", // 2.492s
"CrashTests/5246233363611648/js/webgl-test-utils.js", // 2.478s
"CrashTests/5154715558084608/572.js", // 2.472s
"CrashTests/5216366704721920/js/webgl-test-utils.js", // 2.47s
"CrashTests/5020463045804032/js/webgl-test-utils.js", // 2.44s
"CrashTests/6231966593318912/js/webgl-test-utils.js", // 2.438s
"CrashTests/4712093587865600/js/webgl-test-utils.js", // 2.421s
"CrashTests/4722289303355392/js/webgl-test-utils.js", // 2.415s
"CrashTests/6446057308028928/js/webgl-test-utils.js", // 2.414s
"CrashTests/6585627176992768/binaryen-655.js", // 2.411s
"CrashTests/6371786506371072/js/webgl-test-utils.js", // 2.408s
"CrashTests/5875816496627712/js/webgl-test-utils.js", // 2.404s
"CrashTests/4571384448811008/fast/canvas/webgl/resources/webgl-test-utils-full.js", // 2.404s
"CrashTests/4902839495032832/2.0.0/resources/webgl_test_files/js/webgl-test-utils.js", // 2.391s
"CrashTests/6396634260570112/builds/chromium-browser-asan_linux-release_4392242b7f59878a2775b4607420a2b37e17ff13/revisions/asan-linux-release-616366/gen/third_party/blink/public/mojom/payments/payment_request.mojom.js", // 2.379s
"CrashTests/5973030224527360/builds/chrome-test-builds_media_mac-release_e6940505d6c387d688e04a7feeb7e2019c3efe81/revisions/asan-mac-release-405858/resources/inspector/heap_snapshot_worker.js", // 2.376s
"CrashTests/4928460350029824/js/webgl-test-utils.js", // 2.371s
"CrashTests/5447031043915776/js/webgl-test-utils.js", // 2.35s
"CrashTests/5097133477462016/binaryen-1557.js", // 2.339s
"CrashTests/5748791416979456/js/webgl-test-utils.js", // 2.335s
"CrashTests/4979734430351360/builds/chromium-browser-asan_linux-release_4392242b7f59878a2775b4607420a2b37e17ff13/revisions/asan-linux-release-587925/gen/third_party/blink/public/mojom/payments/payment_request.mojom.js", // 2.329s
"CrashTests/5882955910873088/test.js", // 2.329s
"CrashTests/6030846597005312/binaryen-97.js", // 2.31s
"CrashTests/5934321914609664/js/webgl-test-utils.js", // 2.306s
"CrashTests/4872723313197056/builds/chromium-browser-asan_linux-release_4392242b7f59878a2775b4607420a2b37e17ff13/revisions/asan-linux-release-589752/gen/third_party/blink/public/mojom/payments/payment_request.mojom.js", // 2.291s
"CrashTests/4864843149213696/builds/chromium-browser-asan_linux-release_4392242b7f59878a2775b4607420a2b37e17ff13/revisions/asan-linux-release-588015/gen/third_party/blink/public/mojom/payments/payment_request.mojom.js", // 2.281s
"CrashTests/4526031242788864/rf_onloadcontent.js", // 2.261s
"CrashTests/5673981645684736/js/webgl-test-utils.js", // 2.247s
"CrashTests/5112085437743104/js/webgl-test-utils.js", // 2.223s
"CrashTests/4544669955129344/binaryen-1549.js", // 2.211s
"CrashTests/4661285908905984/builds/chromium-browser-asan_linux-release_4392242b7f59878a2775b4607420a2b37e17ff13/revisions/asan-linux-release-578254/gen/third_party/blink/public/platform/modules/payments/payment_request.mojom.js", // 2.204s
"CrashTests/5710180189995008/js/webgl-test-utils.js", // 2.188s
"CrashTests/6522661136760832/js/webgl-test-utils.js", // 2.176s
"CrashTests/6158076232990720/resources/testharness.js", // 2.174s
"CrashTests/5657181087727616/binaryen-125.js", // 2.159s
"CrashTests/4714207862587392/03389.js", // 2.145s
"CrashTests/5716123902410752/resources/testharness.js", // 2.135s
"CrashTests/6203771342159872/builds/chromium-browser-asan_linux-release_4392242b7f59878a2775b4607420a2b37e17ff13/revisions/asan-linux-release-707359/gen/media/mojo/mojom/media_types.mojom.js", // 2.133s
"CrashTests/6393868459180032/jquery.flot.js", // 2.114s
"CrashTests/5186189903396864/resources/testharness.js", // 2.111s
"CrashTests/5490620452044800/00601.js", // 2.089s
"CrashTests/4656197324767232/gen/third_party/blink/public/platform/modules/payments/payment_request.mojom.js", // 2.081s
"CrashTests/5873758480105472/conformance/resources/webgl-test-utils.js", // 2.079s
"CrashTests/5308016126853120/conformance/resources/webgl-test-utils.js", // 2.075s
"CrashTests/6693648314400768/1.0.3/resources/webgl_test_files/conformance/resources/webgl-test-utils.js", // 2.07s
"CrashTests/4607827521568768/resources/testharness.js", // 2.066s
"CrashTests/6444261469847552/jquery.flot.js", // 2.043s
"CrashTests/5949856401326080/conformance/resources/webgl-test-utils.js", // 2.028s
"CrashTests/5320478993678336/conformance/resources/webgl-test-utils.js", // 2.024s
"CrashTests/4871780976099328/LayoutTests/resources/testharness.js", // 2.024s
"CrashTests/5195343992586240/binaryen-2577.js", // 2.022s
"CrashTests/5170518889332736/resources/webgl-test-utils.js", // 2.019s
"CrashTests/4942847902220288/conformance/resources/webgl-test-utils.js", // 2.005s
"CrashTests/6459909679087616/conformance/resources/webgl-test-utils.js", // 2.001s
];
const sloppy = [
/* Tests requiring sloppy mode from v8 */
"v8/test/mjsunit/accessors-on-global-object.js",
"v8/test/mjsunit/argument-assigned.js",
"v8/test/mjsunit/argument-named-arguments.js",
"v8/test/mjsunit/arguments-apply.js",
"v8/test/mjsunit/arguments-lazy.js",
"v8/test/mjsunit/arguments-read-and-assignment.js",
"v8/test/mjsunit/arguments.js",
"v8/test/mjsunit/array-indexing-receiver.js",
"v8/test/mjsunit/arrow-with.js",
"v8/test/mjsunit/asm-directive.js",
"v8/test/mjsunit/compiler/delete.js",
"v8/test/mjsunit/compiler/global-delete.js",
"v8/test/mjsunit/compiler/global-var-delete.js",
"v8/test/mjsunit/compiler/opt-next-call-turbo.js",
"v8/test/mjsunit/compiler/optimized-for-in.js",
"v8/test/mjsunit/compiler/optimized-with.js",
"v8/test/mjsunit/compiler/regress-1037771.js",
"v8/test/mjsunit/compiler/regress-665680.js",
"v8/test/mjsunit/compiler/regress-669517.js",
"v8/test/mjsunit/compiler/rotate.js",
"v8/test/mjsunit/compiler/try-catch-deopt.js",
"v8/test/mjsunit/compiler/try-context.js",
"v8/test/mjsunit/compiler/uint32.js",
"v8/test/mjsunit/compiler/variables.js",
"v8/test/mjsunit/context-calls-maintained.js",
"v8/test/mjsunit/delete-global-properties.js",
"v8/test/mjsunit/delete-in-with.js",
"v8/test/mjsunit/delete-vars-from-eval.js",
"v8/test/mjsunit/delete.js",
"v8/test/mjsunit/deopt-with-fp-regs.js",
"v8/test/mjsunit/elements-kind.js",
"v8/test/mjsunit/es6/array-concat-sloppy-arguments-with-dupes.js",
"v8/test/mjsunit/es6/arrow-functions-lexical-arguments.js",
"v8/test/mjsunit/es6/arrow-functions-this.js",
"v8/test/mjsunit/es6/block-eval-var-over-let.js",
"v8/test/mjsunit/es6/block-let-contextual-sloppy.js",
"v8/test/mjsunit/es6/block-sloppy-function.js",
"v8/test/mjsunit/es6/classes.js",
"v8/test/mjsunit/es6/default-parameters.js",
"v8/test/mjsunit/es6/destructuring-assignment.js",
"v8/test/mjsunit/es6/generator-destructuring.js",
"v8/test/mjsunit/es6/generators-iteration.js",
"v8/test/mjsunit/es6/generators-parsing.js",
"v8/test/mjsunit/es6/global-proto-proxy.js",
"v8/test/mjsunit/es6/new-target.js",
"v8/test/mjsunit/es6/object-literals-property-shorthand.js",
"v8/test/mjsunit/es6/proxies-function.js",
"v8/test/mjsunit/es6/proxies-with-unscopables.js",
"v8/test/mjsunit/es6/proxies-with.js",
"v8/test/mjsunit/es6/regress/regress-crbug-461520.js",
"v8/test/mjsunit/es6/sloppy-restrictive-block-function.js",
"v8/test/mjsunit/es6/super.js",
"v8/test/mjsunit/es6/templates.js",
"v8/test/mjsunit/es6/unscopables.js",
"v8/test/mjsunit/es7/array-includes-receiver.js",
"v8/test/mjsunit/es7/exponentiation-operator.js",
"v8/test/mjsunit/es8/async-await-basic.js",
"v8/test/mjsunit/es8/async-destructuring.js",
"v8/test/mjsunit/eval.js",
"v8/test/mjsunit/for-in.js",
"v8/test/mjsunit/function-arguments-duplicate.js",
"v8/test/mjsunit/getter-in-prototype.js",
"v8/test/mjsunit/global-arrow-delete-this.js",
"v8/test/mjsunit/global-infinity.js",
"v8/test/mjsunit/global-load-from-eval-in-with.js",
"v8/test/mjsunit/global-load-from-nested-eval.js",
"v8/test/mjsunit/global-nan.js",
"v8/test/mjsunit/global-undefined.js",
"v8/test/mjsunit/global-vars-with.js",
"v8/test/mjsunit/harmony/bigint/property-names.js",
"v8/test/mjsunit/harmony/global-configurable.js",
"v8/test/mjsunit/harmony/import-from-compilation-errored.js",
"v8/test/mjsunit/harmony/import-from-evaluation-errored.js",
"v8/test/mjsunit/harmony/import-from-fetch-errored.js",
"v8/test/mjsunit/harmony/import-from-instantiation-errored.js",
"v8/test/mjsunit/harmony/numeric-separator.js",
"v8/test/mjsunit/harmony/private-fields-special-object.js",
"v8/test/mjsunit/ignition/dead-code-source-position.js",
"v8/test/mjsunit/ignition/regress-616064.js",
"v8/test/mjsunit/no-octal-constants-above-256.js",
"v8/test/mjsunit/override-read-only-property.js",
"v8/test/mjsunit/receiver-in-with-calls.js",
"v8/test/mjsunit/regress/regress-1030466.js",
"v8/test/mjsunit/regress/regress-1079.js",
"v8/test/mjsunit/regress/regress-1125.js",
"v8/test/mjsunit/regress/regress-1132.js",
"v8/test/mjsunit/regress/regress-124.js",
"v8/test/mjsunit/regress/regress-1528.js",
"v8/test/mjsunit/regress/regress-2071.js",
"v8/test/mjsunit/regress/regress-2594.js",
"v8/test/mjsunit/regress/regress-263.js",
"v8/test/mjsunit/regress/regress-2690.js",
"v8/test/mjsunit/regress/regress-3138.js",
"v8/test/mjsunit/regress/regress-318420.js",
"v8/test/mjsunit/regress/regress-3185905.js",
"v8/test/mjsunit/regress/regress-353058.js",
"v8/test/mjsunit/regress/regress-392.js",
"v8/test/mjsunit/regress/regress-410030.js",
"v8/test/mjsunit/regress/regress-410912.js",
"v8/test/mjsunit/regress/regress-4169.js",
"v8/test/mjsunit/regress/regress-4214.js",
"v8/test/mjsunit/regress/regress-436893.js",
"v8/test/mjsunit/regress/regress-4577.js",
"v8/test/mjsunit/regress/regress-492.js",
"v8/test/mjsunit/regress/regress-5205.js",
"v8/test/mjsunit/regress/regress-5405.js",
"v8/test/mjsunit/regress/regress-5692.js",
"v8/test/mjsunit/regress/regress-583260.js",
"v8/test/mjsunit/regress/regress-587004.js",
"v8/test/mjsunit/regress/regress-592353.js",
"v8/test/mjsunit/regress/regress-608630.js",
"v8/test/mjsunit/regress/regress-649067.js",
"v8/test/mjsunit/regress/regress-6677.js",
"v8/test/mjsunit/regress/regress-670147.js",
"v8/test/mjsunit/regress/regress-6733.js",
"v8/test/mjsunit/regress/regress-678525.js",
"v8/test/mjsunit/regress/regress-70066.js",
"v8/test/mjsunit/regress/regress-74.js",
"v8/test/mjsunit/regress/regress-740694.js",
"v8/test/mjsunit/regress/regress-744292.js",
"v8/test/mjsunit/regress/regress-784080.js",
"v8/test/mjsunit/regress/regress-797581.js",
"v8/test/mjsunit/regress/regress-800651.js",
"v8/test/mjsunit/regress/regress-801772.js",
"v8/test/mjsunit/regress/regress-95485.js",
"v8/test/mjsunit/regress/regress-96523.js",
"v8/test/mjsunit/regress/regress-969.js",
"v8/test/mjsunit/regress/regress-abort-context-allocate-params.js",
"v8/test/mjsunit/regress/regress-abort-preparsing-params.js",
"v8/test/mjsunit/regress/regress-crbug-1041210.js",
"v8/test/mjsunit/regress/regress-crbug-1041616.js",
"v8/test/mjsunit/regress/regress-crbug-135008.js",
"v8/test/mjsunit/regress/regress-crbug-412208.js",
"v8/test/mjsunit/regress/regress-crbug-450642.js",
"v8/test/mjsunit/regress/regress-crbug-455644.js",
"v8/test/mjsunit/regress/regress-crbug-505907.js",
"v8/test/mjsunit/regress/regress-crbug-506956.js",
"v8/test/mjsunit/regress/regress-crbug-552304.js",
"v8/test/mjsunit/regress/regress-crbug-628573.js",
"v8/test/mjsunit/regress/regress-crbug-631027.js",
"v8/test/mjsunit/regress/regress-crbug-648740.js",
"v8/test/mjsunit/regress/regress-crbug-663750.js",
"v8/test/mjsunit/regress/regress-crbug-691687.js",
"v8/test/mjsunit/regress/regress-crbug-851393.js",
"v8/test/mjsunit/regress/regress-crbug-934166.js",
"v8/test/mjsunit/regress/regress-sloppy-block-function-hoisting-dynamic.js",
"v8/test/mjsunit/regress/regress-v8-9394-2.js",
"v8/test/mjsunit/regress/regress-v8-9394.js",
"v8/test/mjsunit/regress/wasm/loop-stack-check.js",
"v8/test/mjsunit/regress/wasm/regress-648079.js",
"v8/test/mjsunit/regress/wasm/regress-654377.js",
"v8/test/mjsunit/regress/wasm/regress-753496.js",
"v8/test/mjsunit/scope-calls-eval.js",
"v8/test/mjsunit/serialize-embedded-error.js",
"v8/test/mjsunit/strict-mode-implicit-receiver.js",
"v8/test/mjsunit/strict-mode.js",
"v8/test/mjsunit/switch.js",
"v8/test/mjsunit/throw-and-catch-function.js",
"v8/test/mjsunit/unused-context-in-with.js",
"v8/test/mjsunit/value-wrapper.js",
"v8/test/mjsunit/wasm/import-mutable-global.js",
"v8/test/mjsunit/with-leave.js",
"v8/test/mjsunit/with-parameter-access.js",
"v8/test/mjsunit/with-prototype.js",
"v8/test/mjsunit/with-readonly.js",
"v8/test/mjsunit/with-value.js",
/* Tests requiring sloppy mode from spidermonkey */
"spidermonkey/non262/Array/unscopables.js",
"spidermonkey/non262/Array/values.js",
"spidermonkey/non262/BigInt/property-name-guessed-name.js",
"spidermonkey/non262/BigInt/property-name.js",
"spidermonkey/non262/Date/time-zones-posix.js",
"spidermonkey/non262/Date/time-zones.js",
"spidermonkey/non262/Exceptions/catchguard-002-n.js",
"spidermonkey/non262/Exceptions/catchguard-003-n.js",
"spidermonkey/non262/Exceptions/regress-273931.js",
"spidermonkey/non262/Function/10.2.1.1.6.js",
"spidermonkey/non262/Function/arguments-parameter-shadowing.js",
"spidermonkey/non262/Function/arrow-has-duplicated.js",
"spidermonkey/non262/Function/regress-131964.js",
"spidermonkey/non262/Function/regress-94506.js",
"spidermonkey/non262/Function/regress-97921.js",
"spidermonkey/non262/Function/rest-has-duplicated.js",
"spidermonkey/non262/Function/rest-parameter-names.js",
"spidermonkey/non262/GC/regress-383269-02.js",
"spidermonkey/non262/RegExp/regress-6359.js",
"spidermonkey/non262/RegExp/regress-85721.js",
"spidermonkey/non262/Scope/regress-184107.js",
"spidermonkey/non262/Scope/regress-185485.js",
"spidermonkey/non262/Scope/regress-192226.js",
"spidermonkey/non262/Scope/regress-208496-001.js",
"spidermonkey/non262/Scope/regress-208496-002.js",
"spidermonkey/non262/Scope/scope-004.js",
"spidermonkey/non262/Script/delete-001.js",
"spidermonkey/non262/Script/new-001.js",
"spidermonkey/non262/String/regress-392378.js",
"spidermonkey/non262/TypedObject/method_from.js",
"spidermonkey/non262/TypedObject/method_map.js",
"spidermonkey/non262/Unicode/regress-352044-02-n.js",
"spidermonkey/non262/arrow-functions/arrow-not-as-end-of-statement.js",
"spidermonkey/non262/arrow-functions/arrow-returning-arrow-with-block-body-followed-by-regexp.js",
"spidermonkey/non262/async-functions/async-contains-unicode-escape.js",
"spidermonkey/non262/async-functions/duplicate-__proto__.js",
"spidermonkey/non262/class/outerBinding.js",
"spidermonkey/non262/destructuring/bug1396261.js",
"spidermonkey/non262/destructuring/duplicate-__proto__.js",
"spidermonkey/non262/destructuring/yield-in-object-destr-function.js",
"spidermonkey/non262/destructuring/yield-in-object-destr-script.js",
"spidermonkey/non262/destructuring/yield-with-escape-in-object-destr-function.js",
"spidermonkey/non262/destructuring/yield-with-escape-in-object-destr-script.js",
"spidermonkey/non262/eval/redeclared-arguments-in-param-expression-eval.js",
"spidermonkey/non262/execution-contexts/regress-448595-01.js",
"spidermonkey/non262/expressions/delete-constant-folded-and-or.js",
"spidermonkey/non262/extensions/clone-leaf-object.js",
"spidermonkey/non262/extensions/clone-simple.js",
"spidermonkey/non262/extensions/cross-global-eval-is-indirect.js",
"spidermonkey/non262/extensions/eval-native-callback-is-indirect.js",
"spidermonkey/non262/extensions/function-definition-with.js",
"spidermonkey/non262/extensions/inc-dec-functioncall.js",
"spidermonkey/non262/extensions/recursion.js",
"spidermonkey/non262/extensions/regress-104077.js",
"spidermonkey/non262/extensions/regress-226078.js",
"spidermonkey/non262/extensions/regress-352604.js",
"spidermonkey/non262/extensions/regress-365527.js",
"spidermonkey/non262/extensions/regress-406572.js",
"spidermonkey/non262/extensions/regress-416834.js",
"spidermonkey/non262/extensions/regress-476414-01.js",
"spidermonkey/non262/extensions/regress-476414-02.js",
"spidermonkey/non262/extensions/uneval/bug496985.js",
"spidermonkey/non262/extensions/uneval/regress-385393-03.js",
"spidermonkey/non262/extensions/uneval/regress-452498-101.js",
"spidermonkey/non262/extensions/uneval/regress-452498-117.js",
"spidermonkey/non262/extensions/uneval/regress-624199.js",
"spidermonkey/non262/fields/await-identifier-module-1.js",
"spidermonkey/non262/fields/await-identifier-module-2.js",
"spidermonkey/non262/fields/await-identifier-script.js",
"spidermonkey/non262/generators/iteration.js",
"spidermonkey/non262/generators/syntax.js",
"spidermonkey/non262/generators/yield-non-regexp.js",
"spidermonkey/non262/global/direct-eval-but-not.js",
"spidermonkey/non262/global/eval-02.js",
"spidermonkey/non262/global/eval-inside-with-is-direct.js",
"spidermonkey/non262/global/eval-native-callback-is-indirect.js",
"spidermonkey/non262/jit/regress-451673.js",
"spidermonkey/non262/lexical-conventions/lexical-001.js",
"spidermonkey/non262/lexical-conventions/regress-177314.js",
"spidermonkey/non262/lexical-environment/block-scoped-functions-annex-b-arguments.js",
"spidermonkey/non262/lexical-environment/block-scoped-functions-annex-b-eval.js",
"spidermonkey/non262/lexical-environment/block-scoped-functions-annex-b-if.js",
"spidermonkey/non262/lexical-environment/block-scoped-functions-annex-b-parameter.js",
"spidermonkey/non262/lexical-environment/block-scoped-functions-annex-b-with.js",
"spidermonkey/non262/lexical-environment/block-scoped-functions-deprecated-redecl.js",
"spidermonkey/non262/lexical-environment/implicit-this-in-with.js",
"spidermonkey/non262/lexical-environment/redeclaring-global-properties.js",
"spidermonkey/non262/lexical-environment/unscopables-basics.js",
"spidermonkey/non262/lexical-environment/unscopables-closures.js",
"spidermonkey/non262/lexical-environment/unscopables-const.js",
"spidermonkey/non262/lexical-environment/unscopables-delete.js",
"spidermonkey/non262/lexical-environment/unscopables-getters.js",
"spidermonkey/non262/lexical-environment/unscopables-global.js",
"spidermonkey/non262/lexical-environment/unscopables-ignored.js",
"spidermonkey/non262/lexical-environment/unscopables-miss.js",
"spidermonkey/non262/lexical-environment/unscopables-mutation-frozen.js",
"spidermonkey/non262/lexical-environment/unscopables-mutation.js",
"spidermonkey/non262/lexical-environment/unscopables-proto.js",
"spidermonkey/non262/lexical-environment/unscopables-proxy.js",
"spidermonkey/non262/lexical-environment/unscopables-strict.js",
"spidermonkey/non262/lexical-environment/unscopables-tdz.js",
"spidermonkey/non262/lexical-environment/with-global-ignores-global-let-variables.js",
"spidermonkey/non262/module/bug1488117-import-namespace.js",
"spidermonkey/non262/module/bug1488117.js",
"spidermonkey/non262/reflect-parse/PatternBuilders.js",
"spidermonkey/non262/reflect-parse/classes.js",
"spidermonkey/non262/regress/regress-104077.js",
"spidermonkey/non262/regress/regress-131510-001.js",
"spidermonkey/non262/regress/regress-146596.js",
"spidermonkey/non262/regress/regress-170193.js",
"spidermonkey/non262/regress/regress-230216-1.js",
"spidermonkey/non262/regress/regress-230216-3.js",
"spidermonkey/non262/regress/regress-243389-n.js",
"spidermonkey/non262/regress/regress-252892.js",
"spidermonkey/non262/regress/regress-290656.js",
"spidermonkey/non262/regress/regress-319391.js",
"spidermonkey/non262/regress/regress-336100.js",
"spidermonkey/non262/regress/regress-343713.js",
"spidermonkey/non262/regress/regress-344959.js",
"spidermonkey/non262/regress/regress-349482-02.js",
"spidermonkey/non262/regress/regress-350253.js",
"spidermonkey/non262/regress/regress-351515.js",
"spidermonkey/non262/regress/regress-352604.js",
"spidermonkey/non262/regress/regress-428366.js",
"spidermonkey/non262/regress/regress-441477-01.js",
"spidermonkey/non262/regress/regress-452498-072.js",
"spidermonkey/non262/regress/regress-452498-102.js",
"spidermonkey/non262/regress/regress-452498-117.js",
"spidermonkey/non262/regress/regress-452498-135.js",
"spidermonkey/non262/regress/regress-452498-168-2.js",
"spidermonkey/non262/regress/regress-452498-181.js",
"spidermonkey/non262/regress/regress-452498-192.js",
"spidermonkey/non262/regress/regress-452742-01.js",
"spidermonkey/non262/regress/regress-452742-02.js",
"spidermonkey/non262/regress/regress-462292.js",
"spidermonkey/non262/regress/regress-467495-03.js",
"spidermonkey/non262/regress/regress-467495-04.js",
"spidermonkey/non262/regress/regress-467495-05.js",
"spidermonkey/non262/regress/regress-467495-06.js",
"spidermonkey/non262/regress/regress-477234.js",
"spidermonkey/non262/regress/regress-483749.js",
"spidermonkey/non262/regress/regress-509354.js",
"spidermonkey/non262/regress/regress-551763-0.js",
"spidermonkey/non262/regress/regress-551763-1.js",
"spidermonkey/non262/regress/regress-551763-2.js",
"spidermonkey/non262/regress/regress-554955-1.js",
"spidermonkey/non262/regress/regress-554955-2.js",
"spidermonkey/non262/regress/regress-554955-3.js",
"spidermonkey/non262/regress/regress-569306.js",
"spidermonkey/non262/regress/regress-591897.js",
"spidermonkey/non262/regress/regress-593256.js",
"spidermonkey/non262/regress/regress-597945-1.js",
"spidermonkey/non262/regress/regress-602621.js",
"spidermonkey/non262/regress/regress-609617.js",
"spidermonkey/non262/regress/regress-633741.js",
"spidermonkey/non262/regress/regress-672892.js",
"spidermonkey/non262/regress/regress-68498-001.js",
"spidermonkey/non262/regress/regress-68498-002.js",
"spidermonkey/non262/regress/regress-68498-003.js",
"spidermonkey/non262/regress/regress-68498-004.js",
"spidermonkey/non262/regress/regress-98901.js",
"spidermonkey/non262/statements/for-in-with-assignment-semantics.js",
"spidermonkey/non262/statements/for-in-with-assignments.js",
"spidermonkey/non262/statements/for-of-iterator-close.js",
"spidermonkey/non262/strict/directive-prologue-01.js",
"spidermonkey/non262/syntax/escaped-strict-reserved-words-and-yield.js",
"spidermonkey/non262/template-strings/noSubst.js",
"spidermonkey/test/expected/export/multi-header.js",
"spidermonkey/test/expected/export/reftest-error-syntaxerror.js",
"spidermonkey/test/expected/export/regular.js",
"spidermonkey/test/expected/import/files/local/smTempBranch/language/export/escaped-foobarbaz.js",
"spidermonkey/test/fixtures/export/.ignore.js",
"spidermonkey/test/fixtures/export/multi-header.js",
"spidermonkey/test/fixtures/export/reftest-error-syntaxerror.js",
"spidermonkey/test/fixtures/export/regular.js",
/* Tests requiring sloppy mode from chakra */
"chakra/AsmJs/evalbug.js",
"chakra/AsmJs/switchBinaryTraverse.js",
"chakra/Basics/SpecialSymbolCapture.js",
"chakra/Basics/With-defer-block-scope.js",
"chakra/Basics/With.js",
"chakra/Basics/With2.js",
"chakra/Basics/keyword.js",
"chakra/Basics/scopedaccessors.js",
"chakra/Basics/with3.js",
"chakra/Basics/withBug940841.js",
"chakra/Basics/withBug940841_2.js",
"chakra/Basics/witheval.js",
"chakra/Bugs/OS_4341640.js",
"chakra/Bugs/SuperAccessInGlobalLambda.js",
"chakra/Bugs/blue_1096569.js",
"chakra/Bugs/bug10191241.js",
"chakra/Bugs/bug56026.js",
"chakra/Bugs/bug56026_minimal.js",
"chakra/Bugs/bug56026_minimalWithProperties.js",
"chakra/Bugs/bug56026_nested.js",
"chakra/Bugs/bug56026_trycatch.js",
"chakra/Bugs/bug_OS18260560.js",
"chakra/Bugs/misc_bugs.js",
"chakra/Bugs/withSplitScope.js",
"chakra/Bugs/withnonativeApplyOptimizationBug3433559.js",
"chakra/Closures/bug_OS_10735999.js",
"chakra/Closures/bug_OS_13412380.js",
"chakra/Closures/bug_OS_2525694.js",
"chakra/Closures/cachedscope_1.js",
"chakra/Closures/initcachedscope.js",
"chakra/ControlFlow/DoWhile.js",
"chakra/DebuggerCommon/ES6_letconst_shadow_eval_with.js",
"chakra/DebuggerCommon/blockScopeGlobalSlotArrayTest.bug222631.js",
"chakra/DebuggerCommon/blockScopeSibling.bug263635.js",
"chakra/DebuggerCommon/blockScopeWithTest.js",
"chakra/DebuggerCommon/bug_204064.js",
"chakra/DebuggerCommon/default.js",
"chakra/DebuggerCommon/frames_inspection_arrayES5.js",
"chakra/DebuggerCommon/funcSource.js",
"chakra/DebuggerCommon/globalFuncVars.js",
"chakra/DebuggerCommon/level_1.js",
"chakra/DebuggerCommon/protoTest2.js",
"chakra/DebuggerCommon/shadow_with.js",
"chakra/DebuggerCommon/step_in_only_debugJIT_attach.js",
"chakra/DebuggerCommon/with_shadow.js",
"chakra/EH/optional-catch-binding.js",
"chakra/EH/try2.js",
"chakra/EH/try5-ES3.js",
"chakra/EH/tryfinallyinlineswbug.js",
"chakra/Function/LabelFuncAsWithStmt.js",
"chakra/Function/arguments1.js",
"chakra/Function/arguments2.js",
"chakra/Function/arguments4.js",
"chakra/Function/argumentsMisc.js",
"chakra/Function/bug542360.js",
"chakra/Function/caller_replaced_proto.js",
"chakra/Function/callsideeffects.js",
"chakra/Function/crosssite_bind_main.js",
"chakra/Function/defernested.js",
"chakra/Function/deferredBadContinue.js",
"chakra/Function/deferredParsing.js",
"chakra/Function/deferredWith.js",
"chakra/Function/deferredWith2.js",
"chakra/Function/funcExpr.js",
"chakra/Function/sameNamePara.js",
"chakra/Function/someMoreArguments.js",
"chakra/Function/stackargs.js",
"chakra/Generated/add.js",
"chakra/Generated/add0.js",
"chakra/Generated/add1.js",
"chakra/Generated/add2.js",
"chakra/Generated/add3.js",
"chakra/Generated/and.js",
"chakra/Generated/and0.js",
"chakra/Generated/and1.js",
"chakra/Generated/and2.js",
"chakra/Generated/and3.js",
"chakra/Generated/div.js",
"chakra/Generated/div0.js",
"chakra/Generated/div1.js",
"chakra/Generated/div2.js",
"chakra/Generated/div3.js",
"chakra/Generated/eq.js",
"chakra/Generated/eq0.js",
"chakra/Generated/eq1.js",
"chakra/Generated/eq2.js",
"chakra/Generated/eq3.js",
"chakra/Generated/ge.js",
"chakra/Generated/ge0.js",
"chakra/Generated/ge1.js",
"chakra/Generated/ge2.js",
"chakra/Generated/ge3.js",
"chakra/Generated/gt.js",
"chakra/Generated/gt0.js",
"chakra/Generated/gt1.js",
"chakra/Generated/gt2.js",
"chakra/Generated/gt3.js",
"chakra/Generated/land.js",
"chakra/Generated/land0.js",
"chakra/Generated/land1.js",
"chakra/Generated/land2.js",
"chakra/Generated/land3.js",
"chakra/Generated/le.js",
"chakra/Generated/le0.js",
"chakra/Generated/le1.js",
"chakra/Generated/le2.js",
"chakra/Generated/le3.js",
"chakra/Generated/lor.js",
"chakra/Generated/lor0.js",
"chakra/Generated/lor1.js",
"chakra/Generated/lor2.js",
"chakra/Generated/lor3.js",
"chakra/Generated/lsh.js",
"chakra/Generated/lsh0.js",
"chakra/Generated/lsh1.js",
"chakra/Generated/lsh2.js",
"chakra/Generated/lsh3.js",
"chakra/Generated/lt.js",
"chakra/Generated/lt0.js",
"chakra/Generated/lt1.js",
"chakra/Generated/lt2.js",
"chakra/Generated/lt3.js",
"chakra/Generated/mod.js",
"chakra/Generated/mod0.js",
"chakra/Generated/mod1.js",
"chakra/Generated/mod2.js",
"chakra/Generated/mod3.js",
"chakra/Generated/mul.js",
"chakra/Generated/mul0.js",
"chakra/Generated/mul1.js",
"chakra/Generated/mul2.js",
"chakra/Generated/mul3.js",
"chakra/Generated/ne.js",
"chakra/Generated/ne0.js",
"chakra/Generated/ne1.js",
"chakra/Generated/ne2.js",
"chakra/Generated/ne3.js",
"chakra/Generated/or.js",
"chakra/Generated/or0.js",
"chakra/Generated/or1.js",
"chakra/Generated/or2.js",
"chakra/Generated/or3.js",
"chakra/Generated/rsh.js",
"chakra/Generated/rsh0.js",
"chakra/Generated/rsh1.js",
"chakra/Generated/rsh2.js",
"chakra/Generated/rsh3.js",
"chakra/Generated/rshu.js",
"chakra/Generated/rshu0.js",
"chakra/Generated/rshu1.js",
"chakra/Generated/rshu2.js",
"chakra/Generated/rshu3.js",
"chakra/Generated/seq.js",
"chakra/Generated/seq0.js",
"chakra/Generated/seq1.js",
"chakra/Generated/seq2.js",
"chakra/Generated/seq3.js",
"chakra/Generated/sne.js",
"chakra/Generated/sne0.js",
"chakra/Generated/sne1.js",
"chakra/Generated/sne2.js",
"chakra/Generated/sne3.js",
"chakra/Generated/sub.js",
"chakra/Generated/sub0.js",
"chakra/Generated/sub1.js",
"chakra/Generated/sub2.js",
"chakra/Generated/sub3.js",
"chakra/Generated/xor.js",
"chakra/Generated/xor0.js",
"chakra/Generated/xor1.js",
"chakra/Generated/xor2.js",
"chakra/Generated/xor3.js",
"chakra/GlobalFunctions/ParseInt1.js",
"chakra/GlobalFunctions/eval1.js",
"chakra/GlobalFunctions/parseInt.js",
"chakra/GlobalFunctions/toString.js",
"chakra/InlineCaches/test6.js",
"chakra/LetConst/arguments.js",
"chakra/LetConst/constreassign1.js",
"chakra/LetConst/defer1.js",
"chakra/LetConst/eval1.js",
"chakra/LetConst/letlet.js",
"chakra/LetConst/scopegen1.js",
"chakra/LetConst/tdz1.js",
"chakra/LetConst/tdz2.js",
"chakra/LetConst/with.js",
"chakra/Operators/delete2.js",
"chakra/Operators/delete3.js",
"chakra/Optimizer/Miscellaneous_MaxInterpret.js",
"chakra/Optimizer/bugsimplepathbrfoldgetter.js",
"chakra/Optimizer/test115.js",
"chakra/Optimizer/test135.js",
"chakra/Optimizer/test146.js",
"chakra/PerfHint/try_with_eval_perfhint.js",
"chakra/Regex/regex1.js",
"chakra/Scanner/InvalidCharacter.js",
"chakra/Strings/concat4.js",
"chakra/Strings/long_concatstr.js",
"chakra/UnifiedRegex/bugFixRegression.js",
"chakra/WasmSpec/testsuite/js-api/constructor/instantiate-bad-imports.any.js",
"chakra/WasmSpec/testsuite/js-api/instance/constructor-bad-imports.any.js",
"chakra/benchmarks/ARES-6/Babylon/babylon-blob.js",
"chakra/es6/DeferParseLambda.js",
"chakra/es6/DeferParseMethods.js",
"chakra/es6/ES6Iterators-forof.js",
"chakra/es6/ES6NewTarget.js",
"chakra/es6/blockscope-deferred.js",
"chakra/es6/blockscope-functionbinding.js",
"chakra/es6/boundConstruction.js",
"chakra/es6/bug_OS17895855.js",
"chakra/es6/bug_OS_4498031.js",
"chakra/es6/bug_issue_3247_dep.js",
"chakra/es6/bug_issue_5994.js",
"chakra/es6/default-splitscope-undodeferparse.js",
"chakra/es6/default-splitscope.js",
"chakra/es6/default.js",
"chakra/es6/destructuring_params.js",
"chakra/es6/destructuring_params_arguments_override.js",
"chakra/es6/forInEdgeCases.js",
"chakra/es6/generators-functionality.js",
"chakra/es6/generators-syntax.js",
"chakra/es6/globalCatchNewTargetSyntaxError.js",
"chakra/es6/globalNewTargetSyntaxError.js",
"chakra/es6/globalParamCatchNewTargetSyntaxError.js",
"chakra/es6/lambda-expr.js",
"chakra/es6/lambda1.js",
"chakra/es6/letconst_global_shadow_deleted.js",
"chakra/es6/objlit.js",
"chakra/es6/rest.js",
"chakra/es6/spreadIterator.js",
"chakra/es6/supersyntax02.js",
"chakra/es6/supersyntax05.js",
"chakra/es6/supersyntax06.js",
"chakra/es6/unicode_6_identifier_Blue511452.js",
"chakra/es6/unicode_6_identifier_Blue524737.js",
"chakra/es6/unscopablesWithScopeTest.js",
"chakra/es6module/GetModuleNamespace.js",
"chakra/es6module/ModuleCircularBar.js",
"chakra/es6module/ModuleCircularFoo.js",
"chakra/es6module/ModuleComplexExports.js",
"chakra/es6module/ModuleComplexReexports.js",
"chakra/es6module/ModuleDefaultExport1.js",
"chakra/es6module/ModuleDefaultExport2.js",
"chakra/es6module/ModuleDefaultExport3.js",
"chakra/es6module/ModuleDefaultExport4.js",
"chakra/es6module/ModuleDefaultReexport.js",
"chakra/es6module/ModuleReexportDefault.js",
"chakra/es6module/ModuleSimpleExport.js",
"chakra/es6module/ModuleSimpleReexport.js",
"chakra/es6module/ValidExportDefaultStatement1.js",
"chakra/es6module/ValidExportDefaultStatement2.js",
"chakra/es6module/ValidExportStatements.js",
"chakra/es6module/ValidExportStatements2.js",
"chakra/es6module/ValidImportStatements.js",
"chakra/es6module/ValidReExportStatements.js",
"chakra/es6module/bug_OS12095746.js",
"chakra/es6module/bug_OS12095746_mod0.js",
"chakra/es6module/bug_OS12095746_mod1.js",
"chakra/es6module/bug_OS12095746_mod2.js",
"chakra/es6module/bug_OS12095746_moddep.js",
"chakra/es6module/bug_OS12113549_module1.js",
"chakra/es6module/bug_OS14562349.js",
"chakra/es6module/bug_issue_3076.js",
"chakra/es6module/bug_issue_3257/mod/mod0.js",
"chakra/es6module/bug_issue_3257/mod1.js",
"chakra/es6module/bug_issue_3257/mod2/mod2.js",
"chakra/es6module/bug_issue_3257/script/script0.js",
"chakra/es6module/bug_issue_5777.js",
"chakra/es6module/dynamic_import_promises_5796.js",
"chakra/es6module/exportBinding.js",
"chakra/es6module/exportmodule.js",
"chakra/es6module/module-3250-bug-dep.js",
"chakra/es6module/module-3250-bug-dep2.js",
"chakra/es6module/module-3250-ext-a.js",
"chakra/es6module/module-3250-ext-b.js",
"chakra/es6module/moduleExport1.js",
"chakra/es6module/moduleImportTheError.js",
"chakra/es6module/moduleThrowAnError.js",
"chakra/es6module/module_1_2645.js",
"chakra/es6module/module_2_2645.js",
"chakra/es6module/module_4482_dep1.js",
"chakra/es6module/module_4482_dep2.js",
"chakra/es6module/module_4482_dep3.js",
"chakra/es6module/module_4570_dep1.js",
"chakra/es6module/module_4570_dep2.js",
"chakra/es6module/moduletest2_mod0.js",
"chakra/es6module/moduletest2_mod1a.js",
"chakra/es6module/moduletest2_mod1b.js",
"chakra/es6module/moduletest2_mod2a.js",
"chakra/es6module/otherModule.js",
"chakra/es6module/passmodule.js",
"chakra/es6module/testDynamicImportfromModule.js",
"chakra/es7/asyncawait-functionality.js",
"chakra/es7/json_superset.js",
"chakra/fieldopts/equiv-mismatch2.js",
"chakra/fieldopts/markTemp.js",
"chakra/inlining/bug_gh6303.js",
"chakra/inlining/profilingbug.js",
"chakra/loop/loop.js",
"chakra/stackfunc/602481.js",
"chakra/stackfunc/arguments_assignment.js",
"chakra/stackfunc/with_crossscope.js",
"chakra/stackfunc/with_existing.js",
"chakra/stackfunc/with_namedfunc.js",
"chakra/stackfunc/withref_delayobjscope.js",
"chakra/strict/basics_function_in_SM.js",
"chakra/strict/bug212755.js",
"chakra/strict/comma_bug219390.js",
"chakra/strict/delete.js",
"chakra/strict/formal_samename1.js",
"chakra/strict/formal_samename2.js",
"chakra/strict/multiunit.js",
"chakra/strict/nonSimpleParameterList.js",
"chakra/strict/strictargs-deferred.js",
"chakra/strict/strictargs2-deferred.js",
"chakra/strict/strictargs3-deferred.js",
"chakra/strict/stricteval-deferred.js",
"chakra/strict/stricteval2-deferred.js",
"chakra/strict/strictkwd-deferred.js",
"chakra/wasm.simd/int64x2Tests.js",
/* Tests requiring sloppy mode from jstests */
"WebKit/JSTests/es6/Proxy_internal_get_calls_HasBinding.js",
"WebKit/JSTests/es6/non-strict_function_semantics_function_statements_in_if-statement_clauses.js",
"WebKit/JSTests/es6/non-strict_function_semantics_labeled_function_statements.js",
"WebKit/JSTests/es6/well-known_symbols_Symbol.unscopables.js",
"WebKit/JSTests/stress/adhoc-setter-frame-should-not-be-killed.js",
"WebKit/JSTests/stress/allocation-sinking-hints-are-valid-ssa-2.js",
"WebKit/JSTests/stress/allocation-sinking-hints-are-valid-ssa.js",
"WebKit/JSTests/stress/array-copywithin.js",
"WebKit/JSTests/stress/arrow-function-and-use-strict-directive.js",
"WebKit/JSTests/stress/arrow-functions-as-default-parameter-values.js",
"WebKit/JSTests/stress/arrowfunction-lexical-bind-arguments-non-strict-1.js",
"WebKit/JSTests/stress/arrowfunction-lexical-bind-arguments-non-strict-2.js",
"WebKit/JSTests/stress/arrowfunction-lexical-bind-this-8.js",
"WebKit/JSTests/stress/big-int-as-property-name.js",
"WebKit/JSTests/stress/const-and-with-statement.js",
"WebKit/JSTests/stress/const-not-strict-mode.js",
"WebKit/JSTests/stress/constant-closure-var-with-dynamic-invalidation.js",
"WebKit/JSTests/stress/do-eval-virtual-call-correctly.js",
"WebKit/JSTests/stress/es6-default-parameters.js",
"WebKit/JSTests/stress/eval-cached.js",
"WebKit/JSTests/stress/eval-func-decl-block-with-var-and-remove.js",
"WebKit/JSTests/stress/eval-func-decl-in-eval-within-with-scope.js",
"WebKit/JSTests/stress/eval-that-is-not-eval.js",
"WebKit/JSTests/stress/for-in-tests.js",
"WebKit/JSTests/stress/for-let-comma.js",
"WebKit/JSTests/stress/generator-syntax.js",
"WebKit/JSTests/stress/get-argument-by-val-safe-in-inlined-varargs-call-out-of-bounds.js",
"WebKit/JSTests/stress/get-by-offset-should-use-correct-child.js",
"WebKit/JSTests/stress/get-from-scope-dynamic-onto-proxy.js",
"WebKit/JSTests/stress/get-my-argument-by-val-safe-out-of-bounds.js",
"WebKit/JSTests/stress/get-my-argument-by-val-safe-wrap-around.js",
"WebKit/JSTests/stress/getter-setter-should-be-cell.js",
"WebKit/JSTests/stress/global-environment-does-not-trap-unscopables.js",
"WebKit/JSTests/stress/global-lexical-variable-with-statement.js",
"WebKit/JSTests/stress/global-object-proto-getter.js",
"WebKit/JSTests/stress/hashbang.js",
"WebKit/JSTests/stress/import-basic.js",
"WebKit/JSTests/stress/import-from-eval.js",
"WebKit/JSTests/stress/import-reject-with-exception.js",
"WebKit/JSTests/stress/import-tests/cocoa.js",
"WebKit/JSTests/stress/import-tests/multiple.js",
"WebKit/JSTests/stress/import-tests/multiple2.js",
"WebKit/JSTests/stress/import-tests/should.js",
"WebKit/JSTests/stress/import-with-empty-string.js",
"WebKit/JSTests/stress/lazy-global-object-property-materialization-should-not-putDirectWithoutTransition.js",
"WebKit/JSTests/stress/lexical-let-and-with-statement.js",
"WebKit/JSTests/stress/lexical-let-not-strict-mode.js",
"WebKit/JSTests/stress/licm-should-handle-if-a-hoist-causes-a-provable-osr-exit.js",
"WebKit/JSTests/stress/module-namespace-access-change.js",
"WebKit/JSTests/stress/module-namespace-access-non-constant.js",
"WebKit/JSTests/stress/module-namespace-access-poly.js",
"WebKit/JSTests/stress/module-namespace-access-transitive-exports.js",
"WebKit/JSTests/stress/module-namespace-access.js",
"WebKit/JSTests/stress/object-allocation-sinking-interpretation-can-interpret-edges-that-can-be-proven-unreachable-in-ai.js",
"WebKit/JSTests/stress/object-allocation-sinking-phase-needs-to-write-to-each-scope-offset.js",
"WebKit/JSTests/stress/printableModuleKey-should-never-throw.js",
"WebKit/JSTests/stress/proxy-call-apply-handler-to-this.js",
"WebKit/JSTests/stress/proxy-getter-stack-overflow.js",
"WebKit/JSTests/stress/proxy-stack-overflow-exceptions.js",
"WebKit/JSTests/stress/proxy-with-statement.js",
"WebKit/JSTests/stress/put-dynamic-var-strict-and-sloppy.js",
"WebKit/JSTests/stress/re-execute-error-module.js",
"WebKit/JSTests/stress/regress-159954.js",
"WebKit/JSTests/stress/regress-170732.js",
"WebKit/JSTests/stress/regress-178890.js",
"WebKit/JSTests/stress/regress-191856.js",
"WebKit/JSTests/stress/regress-192626.js",
"WebKit/JSTests/stress/resources/error-module.js",
"WebKit/JSTests/stress/resources/module-namespace-access-transitive-exports-2.js",
"WebKit/JSTests/stress/resources/module-namespace-access-transitive-exports.js",
"WebKit/JSTests/stress/resources/module-namespace-access.js",
"WebKit/JSTests/stress/sloppy-mode-function-hoisting.js",
"WebKit/JSTests/stress/sloppy-mode-hoist-arguments-function-non-simple-parameter-list.js",
"WebKit/JSTests/stress/string-prototype-scopes.js",
"WebKit/JSTests/stress/tagged-templates-this.js",
"WebKit/JSTests/stress/to-this-before-arrow-function-closes-over-this-that-starts-as-lexical-environment.js",
"WebKit/JSTests/stress/unscopables.js",
"WebKit/JSTests/stress/use-arguments-as-object-pointer.js",
"WebKit/JSTests/stress/values-unscopables.js",
"WebKit/JSTests/stress/variable-named-eval-under-tdz.js",
"WebKit/JSTests/stress/with.js",
"WebKit/JSTests/stress/with_and_arith.js",
"WebKit/JSTests/stress/yield-label.js",
/* Tests requiring sloppy mode from crashtests */
"CrashTests/115674352/util.js",
"CrashTests/132918471/fast/js/resources/js-test-post.js",
"CrashTests/135733397/resources/cookies-test-post.js",
"CrashTests/158344541/support/refTestWait.js",
"CrashTests/178811021/media-file.js",
"CrashTests/178811021/video-test.js",
"CrashTests/31681819/fast/js/resources/js-test-post.js",
"CrashTests/4506116685037568/00422.js",
"CrashTests/4506610717425664/00502.js",
"CrashTests/4523272292270080/02509.js",
"CrashTests/4527439453618176/00122.js",
"CrashTests/4528969625894912/encaiiljifbdbjlphpgpiimidegddhic/lib/tweet_manager.js",
"CrashTests/4528969625894912/lib/tweet_manager.js",
"CrashTests/4531783459405824/01124.js",
"CrashTests/4542853924782080/01450.js",
"CrashTests/4553411667165184/00361.js",
"CrashTests/4558140288794624/00118.js",
"CrashTests/4559554636677120/00921.js",
"CrashTests/4563969814560768/1.0.2/conformance/resources/webgl-test-utils.js",
"CrashTests/4563969814560768/1.0.2/conformance/resources/webgl-test.js",
"CrashTests/4563969814560768/1.0.2/resources/js-test-pre.js",
"CrashTests/4592095397150720/619.js",
"CrashTests/4599018605772800/00095.js",
"CrashTests/4609052021096448/02286.js",
"CrashTests/4620742728613888/02272.js",
"CrashTests/4625478540066816/02759.js",
"CrashTests/4632675287826432/01188.js",
"CrashTests/4636862568726528/02064.js",
"CrashTests/4637950708285440/02664.js",
"CrashTests/4646057439133696/01096.js",
"CrashTests/4665806235369472/02400.js",
"CrashTests/4666942225383424/00033.js",
"CrashTests/4675875294674944/04443.js",
"CrashTests/4676310267068416/00041.js",
"CrashTests/4676310267068416/meta-00041.js",
"CrashTests/4678125190643712/01568.js",
"CrashTests/4689880216240128/meta-00116.js",
"CrashTests/4692754406047744/00819.js",
"CrashTests/4704815858057216/02665.js",
"CrashTests/4709921473167360/00418.js",
"CrashTests/4710304564903936/resources/js-test-post.js",
"CrashTests/4714207862587392/03389.js",
"CrashTests/4714965806153728/00222.js",
"CrashTests/4715062213476352/meta-00915.js",
"CrashTests/4730791635451904/00498.js",
"CrashTests/4731918950203392/04316.js",
"CrashTests/4736176662773760/01784.js",
"CrashTests/4747467118084096/02508.js",
"CrashTests/4747813124571136/00737.js",
"CrashTests/4762878654545920/00656.js",
"CrashTests/4763433329491968/01684.js",
"CrashTests/4769018565623808/00203.js",
"CrashTests/4769117811507200/01576.js",
"CrashTests/4776648177352704/02684.js",
"CrashTests/4777280799506432/01745.js",
"CrashTests/4778588336291840/03439.js",
"CrashTests/4784915024707584/meta-00090.js",
"CrashTests/4786126975139840/00686.js",
"CrashTests/4804556499451904/07362.js",
"CrashTests/4804606392795136/00345.js",
"CrashTests/4808505226690560/00570.js",
"CrashTests/4816373903785984/01394.js",
"CrashTests/4817362373836800/01654.js",
"CrashTests/4823335117783040/meta-00192.js",
"CrashTests/4827148775849984/02704.js",
"CrashTests/4828749863583744/00863.js",
"CrashTests/4830304484196352/01110.js",
"CrashTests/4835573090222080/00096.js",
"CrashTests/4835573090222080/meta-00096.js",
"CrashTests/4837730048278528/03052.js",
"CrashTests/4843490131312640/03475.js",
"CrashTests/4850895428517888/2670.js",
"CrashTests/4854644212105216/392.js",
"CrashTests/4855156194934784/meta-00080.js",
"CrashTests/4863599620390912/01845.js",
"CrashTests/4865459476234240/02997.js",
"CrashTests/4867582249664512/01063.js",
"CrashTests/4876270013382656/test.js",
"CrashTests/4877247254626304/00194.js",
"CrashTests/4888824389304320/00897.js",
"CrashTests/4895370524491776/00981.js",
"CrashTests/4897972860223488/00795.js",
"CrashTests/4899093893742592/02412.js",
"CrashTests/4904085663776768/01119.js",
"CrashTests/4907797561212928/01094.js",
"CrashTests/4907899447410688/lib/prototype.js",
"CrashTests/4908800751173632/02190.js",
"CrashTests/4914294111076352/resources/worker-common.js",
"CrashTests/4917356818071552/00992.js",
"CrashTests/4920133693472768/09913.js",
"CrashTests/4924640359088128/resources/methods.js",
"CrashTests/4930344755658752/00813.js",
"CrashTests/4932372025311232/01177.js",
"CrashTests/4940906897866752/01190.js",
"CrashTests/4966722004058112/01202.js",
"CrashTests/4972148754743296/01007.js",
"CrashTests/4976392256618496/01500.js",
"CrashTests/4982480049274880/00401.js",
"CrashTests/4991878320095232/01486.js",
"CrashTests/4996582417891328/00314.js",
"CrashTests/5000906812162048/02217.js",
"CrashTests/5006028967247872/01936.js",
"CrashTests/5010596302946304/03143.js",
"CrashTests/5010966233481216/05443.js",
"CrashTests/5015563071913984/00891.js",
"CrashTests/5016449390477312/02595.js",
"CrashTests/5017709745274880/00480.js",
"CrashTests/5019028805124096/01923.js",
"CrashTests/5020202404937728/04355.js",
"CrashTests/5024919414112256/02190.js",
"CrashTests/5026147325968384/01281.js",
"CrashTests/5026251190829056/01496.js",
"CrashTests/5034236802498560/00038.js",
"CrashTests/5034236802498560/meta-00038.js",
"CrashTests/5036266378756096/resources/js-test.js",
"CrashTests/5040821977219072/07176.js",
"CrashTests/5047964758441984/02170.js",
"CrashTests/5048503350853632/00378.js",
"CrashTests/5055795031965696/00903.js",
"CrashTests/5064701201350656/mjsunit_modified.js",
"CrashTests/5068740508516352/00968.js",
"CrashTests/5068815053619200/02921.js",
"CrashTests/5070483825885184/01709.js",
"CrashTests/5071018176282624/05782.js",
"CrashTests/5072932293050368/01965.js",
"CrashTests/5073353348087808/03720.js",
"CrashTests/5076362928848896/00103.js",
"CrashTests/5080979047317504/04300.js",
"CrashTests/5083229709664256/00286.js",
"CrashTests/5083537469079552/03453.js",
"CrashTests/5086848684654592/00140.js",
"CrashTests/5089350304661504/04000.js",
"CrashTests/5090843606515712/4564.js",
"CrashTests/5091969183776768/js/angular.js",
"CrashTests/5092426574987264/02412.js",
"CrashTests/5092539386822656/00729.js",
"CrashTests/5096882252677120/05262.js",
"CrashTests/5097225136504832/00340.js",
"CrashTests/5104674803023872/meta-00066.js",
"CrashTests/5107484490989568/00655.js",
"CrashTests/5110246766673920/117.js",
"CrashTests/5113028242702336/03897.js",
"CrashTests/5114377424601088/00224.js",
"CrashTests/5126302418337792/00216.js",
"CrashTests/5126730184654848/00846.js",
"CrashTests/5127274311843840/769.js",
"CrashTests/5128141337133056/898.js",
"CrashTests/5129004072042496/02689.js",
"CrashTests/5130481752735744/817.js",
"CrashTests/5140656268640256/resources/interpolation-test.js",
"CrashTests/5150697335816192/04726.js",
"CrashTests/5151090662178816/01492.js",
"CrashTests/5152408142086144/01220.js",
"CrashTests/5153368765628416/00787.js",
"CrashTests/5157575680327680/06055.js",
"CrashTests/5159014924288000/01496.js",
"CrashTests/5164793027624960/01357.js",
"CrashTests/5165045173846016/Common/MV.js",
"CrashTests/5165672034205696/05364.js",
"CrashTests/5168023154720768/meta-00125.js",
"CrashTests/5171157051899904/00383.js",
"CrashTests/5171658670473216/02099.js",
"CrashTests/5174188858146816/00365.js",
"CrashTests/5190716938387456/05795.js",
"CrashTests/5192473061359616/meta-00780.js",
"CrashTests/5197954434596864/01324.js",
"CrashTests/5200019587334144/meta-00398.js",
"CrashTests/5214085959909376/00916.js",
"CrashTests/5219122255757312/00999.js",
"CrashTests/5222394685292544/resources/stress-js-execution.js",
"CrashTests/5225766790889472/03395.js",
"CrashTests/5226258591121408/04850.js",
"CrashTests/5226692407984128/meta-00030.js",
"CrashTests/5226950361612288/01783.js",
"CrashTests/5231597301334016/00307.js",
"CrashTests/5238861996490752/01351.js",
"CrashTests/5242104612651008/mjsunit_modified.js",
"CrashTests/5254331529166848/meta-00409.js",
"CrashTests/5254663852261376/meta-00497.js",
"CrashTests/5257477901778944/06912.js",
"CrashTests/5265513080946688/00263.js",
"CrashTests/5271669179678720/01206.js",
"CrashTests/5280655383724032/meta-00355.js",
"CrashTests/5283736101322752/00921.js",
"CrashTests/5289653387919360/635.js",
"CrashTests/5292566928162816/05416.js",
"CrashTests/5301431549820928/meta-00738.js",
"CrashTests/5313740812320768/00284.js",
"CrashTests/5326135539793920/01618.js",
"CrashTests/5327466171465728/benchmarks/propertyTreeSplitting.js",
"CrashTests/5335637787934720/mersenne.js",
"CrashTests/5337864091729920/00078.js",
"CrashTests/5346139261108224/meta-00086.js",
"CrashTests/5351139388424192/00966.js",
"CrashTests/5351969500168192/02350.js",
"CrashTests/5352173552795648/00798.js",
"CrashTests/5352347554545664/00293.js",
"CrashTests/5354535555825664/01561.js",
"CrashTests/5361893420302336/03633.js",
"CrashTests/5363987624493056/00401.js",
"CrashTests/5367250713575424/00858.js",
"CrashTests/5384147026837504/00846.js",
"CrashTests/5385945858179072/01283.js",
"CrashTests/5385947877998592/00345.js",
"CrashTests/5390684309946368/00499.js",
"CrashTests/5397761290403840/00742.js",
"CrashTests/5397969593958400/02399.js",
"CrashTests/5400975855321088/04550.js",
"CrashTests/5402562393276416/meta-00565.js",
"CrashTests/5417888764657664/01529.js",
"CrashTests/5418169017303040/156.js",
"CrashTests/5420098825748480/01174.js",
"CrashTests/5435516837429248/02591.js",
"CrashTests/5439052443025408/01562.js",
"CrashTests/5443705157976064/04908.js",
"CrashTests/5443796254064640/08661.js",
"CrashTests/5474124668600320/meta-00992.js",
"CrashTests/5480706662727680/02537.js",
"CrashTests/5486126228570112/02840.js",
"CrashTests/5487631620112384/animations/resources/animation-test-helpers.js",
"CrashTests/5494987147444224/01679.js",
"CrashTests/5513876092223488/00005.js",
"CrashTests/5521703332741120/00376.js",
"CrashTests/5528671464456192/01324.js",
"CrashTests/5530121586081792/03646.js",
"CrashTests/5530153792045056/meta-00910.js",
"CrashTests/5536392074493952/01051.js",
"CrashTests/5540548491608064/01146.js",
"CrashTests/5541203771916288/currentscript.js",
"CrashTests/5544125599580160/00526.js",
"CrashTests/5559694775025664/imported/w3c/html-templates/testcommon.js",
"CrashTests/5559694775025664/resources/testharness.js",
"CrashTests/5559694775025664/resources/testharnessreport.js",
"CrashTests/5568247077011456/04042.js",
"CrashTests/5577681470488576/00437.js",
"CrashTests/5593713261412352/319.js",
"CrashTests/5603057343660032/01771.js",
"CrashTests/5605754113884160/01777.js",
"CrashTests/5606041047007232/02795.js",
"CrashTests/5606702255964160/meta-00168.js",
"CrashTests/5612290518810624/dist/jquery.js",
"CrashTests/5615411944226816/02684.js",
"CrashTests/5620205313589248/01035.js",
"CrashTests/5625391309127680/02293.js",
"CrashTests/5630063870214144/02130.js",
"CrashTests/5630225822121984/03637.js",
"CrashTests/5630410519478272/916.js",
"CrashTests/5635092719599616/00041.js",
"CrashTests/5635645835182080/worker-serviceworker-7636bedbbb1f120d.js",
"CrashTests/5639584467910656/00441.js",
"CrashTests/5639628713492480/04139.js",
"CrashTests/5642849944993792/resources/js-test.js",
"CrashTests/5644307466878976/__MACOSX/._audio.js",
"CrashTests/5644307466878976/__MACOSX/._processor.js",
"CrashTests/5645896422522880/00670.js",
"CrashTests/5648004624678912/01755.js",
"CrashTests/5649862583648256/meta-00236.js",
"CrashTests/5650039238033408/00812.js",
"CrashTests/5651439780495360/250.js",
"CrashTests/5651703040835584/resources/testharnessreport.js",
"CrashTests/5652465613406208/4584.js",
"CrashTests/5657116044951552/scripts/options.js",
"CrashTests/5657183745998848/01385.js",
"CrashTests/5657306247462912/00434.js",
"CrashTests/5661345388167168/resources/stress-js-execution.js",
"CrashTests/5662199714480128/00467.js",
"CrashTests/5662596912513024/265.js",
"CrashTests/5664971082694656/02223.js",
"CrashTests/5665078627663872/262.js",
"CrashTests/5668694740172800/meta-00294.js",
"CrashTests/5672678890405888/resources/js-test.js",
"CrashTests/5672678890405888/webaudio/resources/distance-model-testing.js",
"CrashTests/5675659103830016/04982.js",
"CrashTests/5676981169487872/01110.js",
"CrashTests/5677821452091392/02168.js",
"CrashTests/5679632916676608/04152.js",
"CrashTests/5684463616917504/01498.js",
"CrashTests/5685487336161280/03642.js",
"CrashTests/5686447370665984/sdk/tests/conformance/ogles/ogles-utils.js",
"CrashTests/5686447370665984/sdk/tests/conformance/resources/glsl-conformance-test.js",
"CrashTests/5686447370665984/sdk/tests/conformance/resources/webgl-test-utils.js",
"CrashTests/5686447370665984/sdk/tests/resources/js-test-pre.js",
"CrashTests/5688866685321216/09854.js",
"CrashTests/5689884189392896/02723.js",
"CrashTests/5690371071803392/01662.js",
"CrashTests/5690744270487552/oob_write.js",
"CrashTests/5694376231632896/1033966.js",
"CrashTests/5694701996867584/conformance/resources/webgl-test.js",
"CrashTests/5696049601314816/7.js",
"CrashTests/5697903049441280/03188.js",
"CrashTests/5703976838234112/test.js",
"CrashTests/5707472246472704/1443.js",
"CrashTests/5713776938582016/00793.js",
"CrashTests/5721502735532032/03042.js",
"CrashTests/5733293570392064/00764.js",
"CrashTests/5734750167105536/01271.js",
"CrashTests/5735023732064256/meta-00070.js",
"CrashTests/5736353084342272/resources/testharness.js",
"CrashTests/5737388710821888/resources/js-test.js",
"CrashTests/5744365229441024/resources/testharness.js",
"CrashTests/5745342726537216/meta-00053.js",
"CrashTests/5750922200875008/747.js",
"CrashTests/5753604559470592/03311.js",
"CrashTests/5754855756136448/00202.js",
"CrashTests/5755508264534016/00224.js",
"CrashTests/5763511307337728/04651.js",
"CrashTests/5763879718617088/lib/prototype.js",
"CrashTests/5764427184865280/00843.js",
"CrashTests/5765576144060416/815.js",
"CrashTests/5767941953945600/02556.js",
"CrashTests/5774432061095936/00972.js",
"CrashTests/5780358435962880/02297.js",
"CrashTests/5781432505466880/02329.js",
"CrashTests/5784274577129472/146.js",
"CrashTests/5784274665996288/02175.js",
"CrashTests/5794086030147584/04345.js",
"CrashTests/5798263663099904/01459.js",
"CrashTests/5802116248764416/06966.js",
"CrashTests/5806021251432448/background.js",
"CrashTests/58219635/fast/js/resources/js-test-post.js",
"CrashTests/5826758986170368/resources/js-test-post.js",
"CrashTests/5830309687853056/00112.js",
"CrashTests/5830406377832448/01330.js",
"CrashTests/5832728473239552/02422.js",
"CrashTests/5841445051170816/resources/js-test-pre.js",
"CrashTests/5842510916091904/resources/webgl_test_files/resources/js-test-post.js",
"CrashTests/58693299/selfhtml.js",
"CrashTests/5878747354365952/02158.js",
"CrashTests/5910324886634496/02597.js",
"CrashTests/5913894233833472/05410.js",
"CrashTests/5919491238920192/00154.js",
"CrashTests/5925149103357952/webaudio/resources/audit.js",
"CrashTests/5931087833333760/03890.js",
"CrashTests/5931608799707136/04633.js",
"CrashTests/5933875666616320/01048.js",
"CrashTests/5936525417644032/00317.js",
"CrashTests/5941859303555072/01996.js",
"CrashTests/5949184339083264/poc.js",
"CrashTests/5950573451804672/494.js",
"CrashTests/5950617700007936/01848.js",
"CrashTests/5957695718031360/01051.js",
"CrashTests/5969639398440960/00249.js",
"CrashTests/5970316012290048/414.js",
"CrashTests/5978056946876416/00920.js",
"CrashTests/5989158878183424/02865.js",
"CrashTests/5990019710320640/00076.js",
"CrashTests/5996165326962688/meta-00146.js",
"CrashTests/6002230377840640/01046.js",
"CrashTests/6007370099195904/HTML5/Bugbash/Demo.js",
"CrashTests/6010230465626112/resources/webgl_test_files/js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js",
"CrashTests/6018592823836672/support/refTestWait.js",
"CrashTests/6022256973840384/04395.js",
"CrashTests/6022630427590656/03625.js",
"CrashTests/6023488715620352/04168.js",
"CrashTests/6026840030314496/00848.js",
"CrashTests/6034116338909184/513.js",
"CrashTests/6037361396809728/02741.js",
"CrashTests/6043736092966912/00712.js",
"CrashTests/6049932086083584/03169.js",
"CrashTests/6051257375784960/03082.js",
"CrashTests/6054819434070016/02737.js",
"CrashTests/6059329424457728/01928.js",
"CrashTests/6068082133696512/01044.js",
"CrashTests/6071110049988608/00548.js",
"CrashTests/6073192676327424/resources/js-test-pre.js",
"CrashTests/6081148422979584/00926.js",
"CrashTests/6081568072531968/02867.js",
"CrashTests/6085702952681472/00521.js",
"CrashTests/6096783899361280/01310.js",
"CrashTests/6099421385981952/04526.js",
"CrashTests/6103999282413568/fast/dom/script-tests/event-handlers.js",
"CrashTests/6107917668319232/00571.js",
"CrashTests/6113149884563456/02823.js",
"CrashTests/6124318079582208/00744.js",
"CrashTests/6134706385977344/00149.js",
"CrashTests/6136495474737152/00377.js",
"CrashTests/6150179231105024/conformance/resources/webgl-test.js",
"CrashTests/6156744933769216/02993.js",
"CrashTests/6158905865666560/meta-00624.js",
"CrashTests/6162601424453632/00565.js",
"CrashTests/6166378025320448/dist/jquery.js",
"CrashTests/6169525843394560/00344.js",
"CrashTests/6171947516297216/00845.js",
"CrashTests/6179220893204480/02159.js",
"CrashTests/6179752663842816/01196.js",
"CrashTests/6183005912825856/00515.js",
"CrashTests/6183415490019328/02656.js",
"CrashTests/6198951751188480/1248.js",
"CrashTests/6199083597824000/00227.js",
"CrashTests/6202558821957632/02015.js",
"CrashTests/6204924829630464/meta-00272.js",
"CrashTests/6211017381249024/01253.js",
"CrashTests/6213317429559296/02944.js",
"CrashTests/6216405020835840/03985.js",
"CrashTests/6218202061209600/mersenne.js",
"CrashTests/6220111297118208/meta-00050.js",
"CrashTests/6223202209234944/02648.js",
"CrashTests/6234705257168896/01780.js",
"CrashTests/6239384157552640/meta-00271.js",
"CrashTests/6248723961348096/01050.js",
"CrashTests/6249957991645184/00503.js",
"CrashTests/6250003584909312/1114.js",
"CrashTests/6250055858126848/04619.js",
"CrashTests/6255231244697600/meta-00216.js",
"CrashTests/6255916311379968/1372.js",
"CrashTests/6259138054324224/meta-00172.js",
"CrashTests/6269363175555072/00815.js",
"CrashTests/6273728140017664/03583.js",
"CrashTests/6277052166832128/00830.js",
"CrashTests/6278159702425600/01463.js",
"CrashTests/6280577705705472/1146.js",
"CrashTests/6285336190124032/01621.js",
"CrashTests/6292792642371584/00047.js",
"CrashTests/6294597573541888/00725.js",
"CrashTests/6294835115065344/00805.js",
"CrashTests/6295241556492288/01763.js",
"CrashTests/6300171514675200/00115.js",
"CrashTests/6304143111356416/00782.js",
"CrashTests/6319065615040512/04012.js",
"CrashTests/6328755580567552/resources/js-test.js",
"CrashTests/6328755580567552/svg/dynamic-updates/resources/SVGTestCase.js",
"CrashTests/6330764245073920/poc1.js",
"CrashTests/6332832186761216/00681.js",
"CrashTests/6332904701427712/00888.js",
"CrashTests/6332930432958464/02637.js",
"CrashTests/6339944789049344/04142.js",
"CrashTests/6345007341764608/00699.js",
"CrashTests/6346448656400384/dist/jquery.js",
"CrashTests/6351789088833536/meta-00122.js",
"CrashTests/6352599495475200/meta-00093.js",
"CrashTests/6353579392630784/04156.js",
"CrashTests/6358320674242560/resources/js-test.js",
"CrashTests/6359996105359360/934166-poc.js",
"CrashTests/6362821967740928/00524.js",
"CrashTests/6364115106004992/03982.js",
"CrashTests/6374053756272640/824.js",
"CrashTests/6384055239835648/00899.js",
"CrashTests/6387037962240000/02996.js",
"CrashTests/6391863691706368/01129.js",
"CrashTests/6394941698998272/meta-00167.js",
"CrashTests/6403694305476608/meta-00079.js",
"CrashTests/6405187880353792/meta-00826.js",
"CrashTests/6406267560263680/02111.js",
"CrashTests/6406622734974976/meta-00188.js",
"CrashTests/6408374819487744/02912.js",
"CrashTests/6413480679964672/01826.js",
"CrashTests/6417030613041152/02923.js",
"CrashTests/6417972328660992/09282.js",
"CrashTests/6419282024726528/00370.js",
"CrashTests/6423571127599104/04989.js",
"CrashTests/6427802493779968/meta-00335.js",
"CrashTests/6440904627060736/meta-00149.js",
"CrashTests/6441460252803072/04234.js",
"CrashTests/6443097497010176/1.0.2/resources/webgl_test_files/conformance/resources/webgl-test-utils.js",
"CrashTests/6443097497010176/1.0.2/resources/webgl_test_files/conformance/resources/webgl-test.js",
"CrashTests/6443097497010176/1.0.2/resources/webgl_test_files/resources/js-test-pre.js",
"CrashTests/6443097497010176/1.0.2/resources/webkit-webgl-test-harness.js",
"CrashTests/6449605693931520/meta-00261.js",
"CrashTests/6452658006392832/meta-00824.js",
"CrashTests/6454378660626432/00345.js",
"CrashTests/6463535346614272/meta-00886.js",
"CrashTests/6486287733489664/01857.js",
"CrashTests/6491889133158400/01408.js",
"CrashTests/6499287285366784/01193.js",
"CrashTests/6506410742120448/04615.js",
"CrashTests/6507668386873344/02815.js",
"CrashTests/6509855193169920/03031.js",
"CrashTests/6530413356122112/meta-00391.js",
"CrashTests/6534217117990912/01172.js",
"CrashTests/6541223017054208/01484.js",
"CrashTests/6550225930944512/mnt/scratch0/clusterfuzz/slave-bot/inputs/fuzzers/inferno_twister_custom_bundle/inferno_twister_custom_bundle_data/moz_tests/dom/workers/test/threadErrors_worker1.js",
"CrashTests/6552552797503488/bug_41414141.js",
"CrashTests/6566622022860800/05257.js",
"CrashTests/6566953431597056/02044.js",
"CrashTests/6574969751601152/01903.js",
"CrashTests/6576437049950208/conformance/resources/glsl-generator.js",
"CrashTests/6576437049950208/resources/js-test-pre.js",
"CrashTests/6576519795965952/04466.js",
"CrashTests/6586504922267648/00672.js",
"CrashTests/6588129316438016/04328.js",
"CrashTests/6590585390235648/00180.js",
"CrashTests/6597230699216896/meta-00299.js",
"CrashTests/6598446651015168/02933.js",
"CrashTests/6603081141977088/00482.js",
"CrashTests/6603770342408192/00211.js",
"CrashTests/6613865297084416/builds/chromium-browser-syzyasan_win32-release/revisions/asan-win32-release-276100/resources/inspector/main/Main.js",
"CrashTests/6616252740009984/01288.js",
"CrashTests/6622275291840512/resources/js-test.js",
"CrashTests/6637202159960064/01577.js",
"CrashTests/6637774979465216/01973.js",
"CrashTests/6644133880397824/00752.js",
"CrashTests/6645639153188864/00207.js",
"CrashTests/6646069054013440/poc.js",
"CrashTests/6652514189508608/poc.js",
"CrashTests/6658388688371712/00042.js",
"CrashTests/6659440421109760/00027.js",
"CrashTests/6669656538742784/00851.js",
"CrashTests/6669776086630400/01043.js",
"CrashTests/6681695539429376/01791.js",
"CrashTests/6694038640001024/01601.js",
"CrashTests/6695292278931456/04706.js",
"CrashTests/6701111818059776/00487.js",
"CrashTests/6710149884674048/00808.js",
"CrashTests/6710629039079424/01300.js",
"CrashTests/6720085192343552/00257.js",
"CrashTests/6727300586405888/builds/chromium-browser-syzyasan_win32-release/revisions/asan-win32-release-259551/resources/inspector/Main.js",
"CrashTests/6731147175526400/meta-00107.js",
"CrashTests/6744125769252864/494.js",
];
module.exports = {
generatedSkipped: new Set(skipped),
generatedSoftSkipped: new Set(softSkipped),
generatedSloppy: new Set(sloppy),
};
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Mutator for array expressions.
*/
'use strict';
const babelTypes = require('@babel/types');
const common = require('./common.js');
const mutator = require('./mutator.js');
const random = require('../random.js');
// Blueprint for choosing the maximum number of mutations. Bias towards
// performing only one mutation.
const MUTATION_CHOICES = [1, 1, 1, 1, 1, 2, 2, 2, 3];
const MAX_ARRAY_LENGTH = 50;
class ArrayMutator extends mutator.Mutator {
constructor(settings) {
super();
this.settings = settings;
}
get visitor() {
const thisMutator = this;
return {
ArrayExpression(path) {
const elements = path.node.elements;
if (!random.choose(thisMutator.settings.MUTATE_ARRAYS) ||
elements.length > MAX_ARRAY_LENGTH) {
return;
}
// Annotate array expression with the action taken, indicating
// if we also replaced elements.
function annotate(message, replace) {
if (replace) message += ' (replaced)';
thisMutator.annotate(path.node, message);
}
// Add or replace elements at a random index.
function randomSplice(replace, ...args) {
// Choose an index that's small enough to replace all desired items.
const index = random.randInt(0, elements.length - replace);
elements.splice(index, replace, ...args);
}
function duplicateElement(replace) {
const element = random.single(elements);
if (!element || common.isLargeNode(element)) {
return;
}
annotate('Duplicate an element', replace);
randomSplice(replace, babelTypes.cloneDeep(element));
}
function insertRandomValue(replace) {
annotate('Insert a random value', replace);
randomSplice(replace, common.randomValue(path));
}
function insertHole(replace) {
annotate('Insert a hole', replace);
randomSplice(replace, null);
}
function removeElements(count) {
annotate('Remove elements');
randomSplice(random.randInt(1, count));
}
function shuffle() {
annotate('Shuffle array');
random.shuffle(elements);
}
// Mutation options. Repeated mutations have a higher probability.
const mutations = [
() => duplicateElement(1),
() => duplicateElement(1),
() => duplicateElement(1),
() => duplicateElement(0),
() => duplicateElement(0),
() => insertRandomValue(1),
() => insertRandomValue(1),
() => insertRandomValue(0),
() => insertHole(1),
() => insertHole(0),
() => removeElements(1),
() => removeElements(elements.length),
shuffle,
];
// Perform several mutations.
const count = random.single(MUTATION_CHOICES);
for (let i = 0; i < count; i++) {
random.single(mutations)();
}
// Don't recurse on nested arrays.
path.skip();
},
}
}
}
module.exports = {
ArrayMutator: ArrayMutator,
};
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Common mutator utilities.
*/
const babelTemplate = require('@babel/template').default;
const babelTypes = require('@babel/types');
const babylon = require('@babel/parser');
const sourceHelpers = require('../source_helpers.js');
const random = require('../random.js');
const INTERESTING_NUMBER_VALUES = [
-1, -0.0, 0, 1,
// Float values.
-0.000000000000001, 0.000000000000001,
// Special values.
NaN, +Infinity, -Infinity,
// Boundaries of int, signed, unsigned, SMI (near +/- 2^(30, 31, 32).
0x03fffffff, 0x040000000, 0x040000001,
-0x03fffffff, -0x040000000, -0x040000001,
0x07fffffff, 0x080000000, 0x080000001,
-0x07fffffff, -0x080000000, -0x080000001,
0x0ffffffff, 0x100000000, 0x100000001,
-0x0ffffffff, -0x100000000, -0x100000001,
// Boundaries of maximum safe integer (near +/- 2^53).
9007199254740990, 9007199254740991, 9007199254740992,
-9007199254740990, -9007199254740991, -9007199254740992,
// Boundaries of double.
5e-324, 1.7976931348623157e+308,
-5e-324,-1.7976931348623157e+308,
]
const INTERESTING_NON_NUMBER_VALUES = [
// Simple arrays.
'[]',
'Array(0x8000).fill("a")',
// Simple object.
'{}',
'{a: "foo", b: 10, c: {}}',
// Simple strings.
'"foo"',
'""',
// Simple regex.
'/0/',
'"/0/"',
// Simple symbol.
'Symbol("foo")',
// Long string.
'Array(0x8000).join("a")',
// Math.PI
'Math.PI',
// Others.
'false',
'true',
'undefined',
'null',
'this',
'this[0]',
'this[1]',
// Empty function.
'(function() {return 0;})',
// Objects with functions.
'({toString:function(){return "0";}})',
'({valueOf:function(){return 0;}})',
'({valueOf:function(){return "0";}})',
// Objects for primitive types created using new.
'(new Boolean(false))',
'(new Boolean(true))',
'(new String(""))',
'(new Number(0))',
'(new Number(-0))',
]
const LARGE_NODE_SIZE = 100;
const MAX_ARGUMENT_COUNT = 10;
function _identifier(identifier) {
return babelTypes.identifier(identifier);
}
function _numericLiteral(number) {
return babelTypes.numericLiteral(number);
}
function _unwrapExpressionStatement(value) {
if (babelTypes.isExpressionStatement(value)) {
return value.expression;
}
return value;
}
function isVariableIdentifier(name) {
return /__v_[0-9]+/.test(name);
}
function isFunctionIdentifier(name) {
return /__f_[0-9]+/.test(name);
}
function isInForLoopCondition(path) {
// Return whether if we're in the init/test/update parts of a for loop (but
// not the body). Mutating variables in the init/test/update will likely
// modify loop variables and cause infinite loops.
const forStatementChild = path.find(
p => p.parent && babelTypes.isForStatement(p.parent));
return (forStatementChild && forStatementChild.parentKey !== 'body');
}
function isInWhileLoop(path) {
// Return whether if we're in a while loop.
const whileStatement = path.find(p => babelTypes.isWhileStatement(p));
return Boolean(whileStatement);
}
function _availableIdentifiers(path, filter) {
// TODO(ochang): Consider globals that aren't declared with let/var etc.
const available = new Array();
const allBindings = path.scope.getAllBindings();
for (const key of Object.keys(allBindings)) {
if (!filter(key)) {
continue;
}
if (filter === isVariableIdentifier &&
path.willIMaybeExecuteBefore(allBindings[key].path)) {
continue;
}
available.push(_identifier(key));
}
return available;
}
function availableVariables(path) {
return _availableIdentifiers(path, isVariableIdentifier);
}
function availableFunctions(path) {
return _availableIdentifiers(path, isFunctionIdentifier);
}
function randomVariable(path) {
return random.single(availableVariables(path));
}
function randomFunction(path) {
return random.single(availableFunctions(path));
}
function randomSeed() {
return random.randInt(0, 2**20);
}
function randomObject(seed) {
if (seed === undefined) {
seed = randomSeed();
}
const template = babelTemplate('__getRandomObject(SEED)');
return template({
SEED: _numericLiteral(seed),
}).expression;
}
function randomProperty(identifier, seed) {
if (seed === undefined) {
seed = randomSeed();
}
const template = babelTemplate('__getRandomProperty(IDENTIFIER, SEED)');
return template({
IDENTIFIER: identifier,
SEED: _numericLiteral(seed),
}).expression;
}
function randomArguments(path) {
const numArgs = random.randInt(0, MAX_ARGUMENT_COUNT);
const args = [];
for (let i = 0; i < numArgs; i++) {
args.push(randomValue(path));
}
return args.map(_unwrapExpressionStatement);
}
function randomValue(path) {
const probability = random.random();
if (probability < 0.01) {
const randomFunc = randomFunction(path);
if (randomFunc) {
return randomFunc;
}
}
if (probability < 0.25) {
const randomVar = randomVariable(path);
if (randomVar) {
return randomVar;
}
}
if (probability < 0.5) {
return randomInterestingNumber();
}
if (probability < 0.75) {
return randomInterestingNonNumber();
}
return randomObject();
}
function callRandomFunction(path, identifier, seed) {
if (seed === undefined) {
seed = randomSeed();
}
let args = [
identifier,
_numericLiteral(seed)
];
args = args.map(_unwrapExpressionStatement);
args = args.concat(randomArguments(path));
return babelTypes.callExpression(
babelTypes.identifier('__callRandomFunction'),
args);
}
function nearbyRandomNumber(value) {
const probability = random.random();
if (probability < 0.9) {
return _numericLiteral(value + random.randInt(-0x10, 0x10));
} else if (probability < 0.95) {
return _numericLiteral(value + random.randInt(-0x100, 0x100));
} else if (probability < 0.99) {
return _numericLiteral(value + random.randInt(-0x1000, 0x1000));
}
return _numericLiteral(value + random.randInt(-0x10000, 0x10000));
}
function randomInterestingNumber() {
const value = random.single(INTERESTING_NUMBER_VALUES);
if (random.choose(0.05)) {
return nearbyRandomNumber(value);
}
return _numericLiteral(value);
}
function randomInterestingNonNumber() {
return babylon.parseExpression(random.single(INTERESTING_NON_NUMBER_VALUES));
}
function concatFlags(inputs) {
const flags = new Set();
for (const input of inputs) {
for (const flag of input.flags || []) {
flags.add(flag);
}
}
return Array.from(flags.values());
}
function concatPrograms(inputs) {
// Concatentate programs.
const resultProgram = babelTypes.program([]);
const result = babelTypes.file(resultProgram, [], null);
for (const input of inputs) {
const ast = input.ast.program;
resultProgram.body = resultProgram.body.concat(ast.body);
resultProgram.directives = resultProgram.directives.concat(ast.directives);
}
// TODO(machenbach): Concat dependencies here as soon as they are cached.
const combined = new sourceHelpers.ParsedSource(
result, '', '', concatFlags(inputs));
// If any input file is sloppy, the combined result is sloppy.
combined.sloppy = inputs.some(input => input.isSloppy());
return combined;
}
function setSourceLoc(source, index, total) {
const noop = babelTypes.noop();
noop.__loc = index / total;
noop.__self = noop;
source.ast.program.body.unshift(noop);
}
function getSourceLoc(node) {
// Source location is invalid in cloned nodes.
if (node !== node.__self) {
return undefined;
}
return node.__loc;
}
function setOriginalPath(source, originalPath) {
const noop = babelTypes.noop();
noop.__path = originalPath;
noop.__self = noop;
source.ast.program.body.unshift(noop);
}
function getOriginalPath(node) {
// Original path is invalid in cloned nodes.
if (node !== node.__self) {
return undefined;
}
return node.__path;
}
// Estimate the size of a node in raw source characters.
function isLargeNode(node) {
// Ignore array holes inserted by us (null) or previously cloned nodes
// (they have no start/end).
if (!node || node.start === undefined || node.end === undefined ) {
return false;
}
return node.end - node.start > LARGE_NODE_SIZE;
}
module.exports = {
callRandomFunction: callRandomFunction,
concatFlags: concatFlags,
concatPrograms: concatPrograms,
availableVariables: availableVariables,
availableFunctions: availableFunctions,
randomFunction: randomFunction,
randomVariable: randomVariable,
isInForLoopCondition: isInForLoopCondition,
isInWhileLoop: isInWhileLoop,
isLargeNode: isLargeNode,
isVariableIdentifier: isVariableIdentifier,
isFunctionIdentifier: isFunctionIdentifier,
nearbyRandomNumber: nearbyRandomNumber,
randomArguments: randomArguments,
randomInterestingNonNumber: randomInterestingNonNumber,
randomInterestingNumber: randomInterestingNumber,
randomObject: randomObject,
randomProperty: randomProperty,
randomSeed: randomSeed,
randomValue: randomValue,
getOriginalPath: getOriginalPath,
setOriginalPath: setOriginalPath,
getSourceLoc: getSourceLoc,
setSourceLoc: setSourceLoc,
}
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Expression mutator.
*/
'use strict';
const babelTemplate = require('@babel/template').default;
const common = require('./common.js');
const random = require('../random.js');
const mutator = require('./mutator.js');
const sourceHelpers = require('../source_helpers.js');
class CrossOverMutator extends mutator.Mutator {
constructor(settings, db) {
super();
this.settings = settings;
this.db = db;
}
get visitor() {
const thisMutator = this;
return [{
ExpressionStatement(path) {
if (!random.choose(thisMutator.settings.MUTATE_CROSSOVER_INSERT)) {
return;
}
const canHaveSuper = Boolean(path.findParent(x => x.isClassMethod()));
const randomExpression = thisMutator.db.getRandomStatement(
{canHaveSuper: canHaveSuper});
// Insert the statement.
var templateOptions = Object.assign({}, sourceHelpers.BABYLON_OPTIONS);
templateOptions['placeholderPattern'] = /^VAR_[0-9]+$/;
let toInsert = babelTemplate(
randomExpression.source,
templateOptions);
const dependencies = {};
if (randomExpression.dependencies) {
const variables = common.availableVariables(path);
if (!variables.length) {
return;
}
for (const dependency of randomExpression.dependencies) {
dependencies[dependency] = random.single(variables);
}
}
try {
toInsert = toInsert(dependencies);
} catch (e) {
if (thisMutator.settings.testing) {
// Fail early in tests.
throw e;
}
console.log('ERROR: Failed to parse:', randomExpression.source);
console.log(e);
return;
}
thisMutator.annotate(
toInsert,
'Crossover from ' + randomExpression.originalPath);
if (random.choose(0.5)) {
thisMutator.insertBeforeSkip(path, toInsert);
} else {
thisMutator.insertAfterSkip(path, toInsert);
}
path.skip();
},
}, {
}];
}
}
module.exports = {
CrossOverMutator: CrossOverMutator,
};
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Mutator for differential fuzzing.
*/
'use strict';
const babelTemplate = require('@babel/template').default;
const babelTypes = require('@babel/types');
const common = require('./common.js');
const mutator = require('./mutator.js');
const random = require('../random.js');
// Templates for various statements.
const incCaught = babelTemplate('__caught++;');
const printValue = babelTemplate('print(VALUE);');
const printCaught = babelTemplate('print("Caught: " + __caught);');
const printHash = babelTemplate('print("Hash: " + __hash);');
const prettyPrint = babelTemplate('__prettyPrint(ID);');
const prettyPrintExtra = babelTemplate('__prettyPrintExtra(ID);');
// This section prefix is expected by v8_foozzie.py. Existing prefixes
// (e.g. from CrashTests) are cleaned up with CLEANED_PREFIX.
const SECTION_PREFIX = 'v8-foozzie source: ';
const CLEANED_PREFIX = 'v***************e: ';
/**
* Babel statement for calling deep printing from the fuzz library.
*/
function prettyPrintStatement(variable) {
return prettyPrint({ ID: babelTypes.cloneDeep(variable) });
}
/**
* As above, but using the "extra" variant, which will reduce printing
* after too many calls to prevent I/O flooding.
*/
function prettyPrintExtraStatement(variable) {
return prettyPrintExtra({ ID: babelTypes.cloneDeep(variable) });
}
/**
* Mutator for suppressing known and/or unfixable issues.
*/
class DifferentialFuzzSuppressions extends mutator.Mutator {
get visitor() {
let thisMutator = this;
return {
// Clean up strings containing the magic section prefix. Those can come
// e.g. from CrashTests and would confuse the deduplication in
// v8_foozzie.py.
StringLiteral(path) {
if (path.node.value.startsWith(SECTION_PREFIX)) {
const postfix = path.node.value.substring(SECTION_PREFIX.length);
path.node.value = CLEANED_PREFIX + postfix;
thisMutator.annotate(path.node, 'Replaced magic string');
}
},
// Known precision differences: https://crbug.com/1063568
BinaryExpression(path) {
if (path.node.operator == '**') {
path.node.operator = '+';
thisMutator.annotate(path.node, 'Replaced **');
}
},
// Unsupported language feature: https://crbug.com/1020573
MemberExpression(path) {
if (path.node.property.name == "arguments") {
let replacement = common.randomVariable(path);
if (!replacement) {
replacement = babelTypes.thisExpression();
}
thisMutator.annotate(replacement, 'Replaced .arguments');
thisMutator.replaceWithSkip(path, replacement);
}
},
};
}
}
/**
* Mutator for tracking original input files and for extra printing.
*/
class DifferentialFuzzMutator extends mutator.Mutator {
constructor(settings) {
super();
this.settings = settings;
}
/**
* Looks for the dummy node that marks the beginning of an input file
* from the corpus.
*/
isSectionStart(path) {
return !!common.getOriginalPath(path.node);
}
/**
* Create print statements for printing the magic section prefix that's
* expected by v8_foozzie.py to differentiate different source files.
*/
getSectionHeader(path) {
const orig = common.getOriginalPath(path.node);
return printValue({
VALUE: babelTypes.stringLiteral(SECTION_PREFIX + orig),
});
}
/**
* Create statements for extra printing at the end of a section. We print
* the number of caught exceptions, a generic hash of all observed values
* and the contents of all variables in scope.
*/
getSectionFooter(path) {
const variables = common.availableVariables(path);
const statements = variables.map(prettyPrintStatement);
statements.unshift(printCaught());
statements.unshift(printHash());
const statement = babelTypes.tryStatement(
babelTypes.blockStatement(statements),
babelTypes.catchClause(
babelTypes.identifier('e'),
babelTypes.blockStatement([])));
this.annotate(statement, 'Print variables and exceptions from section');
return statement;
}
/**
* Helper for printing the contents of several variables.
*/
printVariables(path, nodes) {
const statements = [];
for (const node of nodes) {
if (!babelTypes.isIdentifier(node) ||
!common.isVariableIdentifier(node.name))
continue;
statements.push(prettyPrintExtraStatement(node));
}
if (statements.length) {
this.annotate(statements[0], 'Extra variable printing');
this.insertAfterSkip(path, statements);
}
}
get visitor() {
const thisMutator = this;
const settings = this.settings;
return {
// Replace existing normal print statements with deep printing.
CallExpression(path) {
if (babelTypes.isIdentifier(path.node.callee) &&
path.node.callee.name == 'print') {
path.node.callee = babelTypes.identifier('__prettyPrintExtra');
thisMutator.annotate(path.node, 'Pretty printing');
}
},
// Either print or track caught exceptions, guarded by a probability.
CatchClause(path) {
const probability = random.random();
if (probability < settings.DIFF_FUZZ_EXTRA_PRINT &&
path.node.param &&
babelTypes.isIdentifier(path.node.param)) {
const statement = prettyPrintExtraStatement(path.node.param);
path.node.body.body.unshift(statement);
} else if (probability < settings.DIFF_FUZZ_TRACK_CAUGHT) {
path.node.body.body.unshift(incCaught());
}
},
// Insert section headers and footers between the contents of two
// original source files. We detect the dummy no-op nodes that were
// previously tagged with the original path of the file.
Noop(path) {
if (!thisMutator.isSectionStart(path)) {
return;
}
const header = thisMutator.getSectionHeader(path);
const footer = thisMutator.getSectionFooter(path);
thisMutator.insertBeforeSkip(path, footer);
thisMutator.insertBeforeSkip(path, header);
},
// Additionally we print one footer in the end.
Program: {
exit(path) {
const footer = thisMutator.getSectionFooter(path);
path.node.body.push(footer);
},
},
// Print contents of variables after assignments, guarded by a
// probability.
ExpressionStatement(path) {
if (!babelTypes.isAssignmentExpression(path.node.expression) ||
!random.choose(settings.DIFF_FUZZ_EXTRA_PRINT)) {
return;
}
const left = path.node.expression.left;
if (babelTypes.isMemberExpression(left)) {
thisMutator.printVariables(path, [left.object]);
} else {
thisMutator.printVariables(path, [left]);
}
},
// Print contents of variables after declaration, guarded by a
// probability.
VariableDeclaration(path) {
if (babelTypes.isLoop(path.parent) ||
!random.choose(settings.DIFF_FUZZ_EXTRA_PRINT)) {
return;
}
const identifiers = path.node.declarations.map(decl => decl.id);
thisMutator.printVariables(path, identifiers);
},
};
}
}
module.exports = {
DifferentialFuzzMutator: DifferentialFuzzMutator,
DifferentialFuzzSuppressions: DifferentialFuzzSuppressions,
};
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Expression mutator.
*/
'use strict';
const babelTypes = require('@babel/types');
const random = require('../random.js');
const mutator = require('./mutator.js');
class ExpressionMutator extends mutator.Mutator {
constructor(settings) {
super();
this.settings = settings;
}
get visitor() {
const thisMutator = this;
return {
ExpressionStatement(path) {
if (!random.choose(thisMutator.settings.MUTATE_EXPRESSIONS)) {
return;
}
const probability = random.random();
if (probability < 0.7) {
const repeated = babelTypes.cloneDeep(path.node);
thisMutator.annotate(repeated, 'Repeated');
thisMutator.insertBeforeSkip(path, repeated);
} else if (path.key > 0) {
// Get a random previous sibling.
const prev = path.getSibling(random.randInt(0, path.key - 1));
if (!prev || !prev.node) {
return;
}
// Either select a previous or the current node to clone.
const [selected, destination] = random.shuffle([prev, path]);
if (selected.isDeclaration()) {
return;
}
const cloned = babelTypes.cloneDeep(selected.node);
thisMutator.annotate(cloned, 'Cloned sibling');
if (random.choose(0.5)) {
thisMutator.insertBeforeSkip(destination, cloned);
} else {
thisMutator.insertAfterSkip(destination, cloned);
}
}
},
};
}
}
module.exports = {
ExpressionMutator: ExpressionMutator,
};
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Function calls mutator.
*/
'use strict';
const babelTemplate = require('@babel/template').default;
const babelTypes = require('@babel/types');
const common = require('./common.js');
const random = require('../random.js');
const mutator = require('./mutator.js');
function _liftExpressionsToStatements(path, nodes) {
// If the node we're replacing is an expression in an expression statement,
// lift the replacement nodes into statements too.
if (!babelTypes.isExpressionStatement(path.parent)) {
return nodes;
}
return nodes.map(n => babelTypes.expressionStatement(n));
}
class FunctionCallMutator extends mutator.Mutator {
constructor(settings) {
super();
this.settings = settings;
}
get visitor() {
const thisMutator = this;
return {
CallExpression(path) {
if (!babelTypes.isIdentifier(path.node.callee)) {
return;
}
if (!common.isFunctionIdentifier(path.node.callee.name)) {
return;
}
if (!random.choose(thisMutator.settings.MUTATE_FUNCTION_CALLS)) {
return;
}
const probability = random.random();
if (probability < 0.5) {
const randFunc = common.randomFunction(path);
if (randFunc) {
thisMutator.annotate(
path.node,
`Replaced ${path.node.callee.name} with ${randFunc.name}`);
path.node.callee = randFunc;
}
} else if (probability < 0.7 && thisMutator.settings.engine == 'V8') {
const prepareTemplate = babelTemplate(
'__V8BuiltinPrepareFunctionForOptimization(ID)');
const optimizeTemplate = babelTemplate(
'__V8BuiltinOptimizeFunctionOnNextCall(ID)');
const nodes = [
prepareTemplate({
ID: babelTypes.cloneDeep(path.node.callee),
}).expression,
babelTypes.cloneDeep(path.node),
babelTypes.cloneDeep(path.node),
optimizeTemplate({
ID: babelTypes.cloneDeep(path.node.callee),
}).expression,
];
thisMutator.annotate(
path.node,
`Optimizing ${path.node.callee.name}`);
if (!babelTypes.isExpressionStatement(path.parent)) {
nodes.push(path.node);
thisMutator.replaceWithSkip(
path, babelTypes.sequenceExpression(nodes));
} else {
thisMutator.insertBeforeSkip(
path, _liftExpressionsToStatements(path, nodes));
}
} else if (probability < 0.85 &&
thisMutator.settings.engine == 'V8') {
const template = babelTemplate(
'__V8BuiltinDeoptimizeFunction(ID)');
const insert = _liftExpressionsToStatements(path, [
template({
ID: babelTypes.cloneDeep(path.node.callee),
}).expression,
]);
thisMutator.annotate(
path.node,
`Deoptimizing ${path.node.callee.name}`);
thisMutator.insertAfterSkip(path, insert);
} else {
const template = babelTemplate(
'runNearStackLimit(() => { return CALL });');
thisMutator.annotate(
path.node,
`Run to stack limit ${path.node.callee.name}`);
thisMutator.replaceWithSkip(
path,
template({
CALL: path.node,
}).expression);
}
path.skip();
},
}
}
}
module.exports = {
FunctionCallMutator: FunctionCallMutator,
};
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Mutator
*/
'use strict';
const babelTraverse = require('@babel/traverse').default;
const babelTypes = require('@babel/types');
class Mutator {
get visitor() {
return null;
}
_traverse(ast, visitor) {
let oldEnter = null;
if (Object.prototype.hasOwnProperty.call(visitor, 'enter')) {
oldEnter = visitor['enter'];
}
// Transparently skip nodes that are marked.
visitor['enter'] = (path) => {
if (this.shouldSkip(path.node)) {
path.skip();
return;
}
if (oldEnter) {
oldEnter(path);
}
}
babelTraverse(ast, visitor);
}
mutate(source) {
if (Array.isArray(this.visitor)) {
for (const visitor of this.visitor) {
this._traverse(source.ast, visitor);
}
} else {
this._traverse(source.ast, this.visitor);
}
}
get _skipPropertyName() {
return '__skip' + this.constructor.name;
}
shouldSkip(node) {
return Boolean(node[this._skipPropertyName]);
}
skipMutations(node) {
// Mark a node to skip further mutations of the same kind.
if (Array.isArray(node)) {
for (const item of node) {
item[this._skipPropertyName] = true;
}
} else {
node[this._skipPropertyName] = true;
}
return node;
}
insertBeforeSkip(path, node) {
this.skipMutations(node);
path.insertBefore(node);
}
insertAfterSkip(path, node) {
this.skipMutations(node);
path.insertAfter(node);
}
replaceWithSkip(path, node) {
this.skipMutations(node);
path.replaceWith(node);
}
replaceWithMultipleSkip(path, node) {
this.skipMutations(node);
path.replaceWithMultiple(node);
}
annotate(node, message) {
babelTypes.addComment(
node, 'leading', ` ${this.constructor.name}: ${message} `);
}
}
module.exports = {
Mutator: Mutator,
}
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Normalizer.
* This renames variables so that we don't have collisions when combining
* different files. It also simplifies other logic when e.g. determining the
* type of an identifier.
*/
'use strict';
const babelTypes = require('@babel/types');
const mutator = require('./mutator.js');
class NormalizerContext {
constructor() {
this.funcIndex = 0;
this.varIndex = 0;
this.classIndex = 0;
}
}
class IdentifierNormalizer extends mutator.Mutator {
constructor() {
super();
this.context = new NormalizerContext();
}
get visitor() {
const context = this.context;
const renamed = new WeakSet();
const globalMappings = new Map();
return [{
Scope(path) {
for (const [name, binding] of Object.entries(path.scope.bindings)) {
if (renamed.has(binding.identifier)) {
continue;
}
renamed.add(binding.identifier);
if (babelTypes.isClassDeclaration(binding.path.node) ||
babelTypes.isClassExpression(binding.path.node)) {
path.scope.rename(name, '__c_' + context.classIndex++);
} else if (babelTypes.isFunctionDeclaration(binding.path.node) ||
babelTypes.isFunctionExpression(binding.path.node)) {
path.scope.rename(name, '__f_' + context.funcIndex++);
} else {
path.scope.rename(name, '__v_' + context.varIndex++);
}
}
},
AssignmentExpression(path) {
// Find assignments for which we have no binding in the scope. We assume
// that these are globals which are local to our script (which weren't
// declared with var/let/const etc).
const ids = path.getBindingIdentifiers();
for (const name in ids) {
if (!path.scope.getBinding(name)) {
globalMappings.set(name, '__v_' + context.varIndex++);
}
}
}
}, {
// Second pass to rename globals that weren't declared with
// var/let/const etc.
Identifier(path) {
if (!globalMappings.has(path.node.name)) {
return;
}
if (path.scope.getBinding(path.node.name)) {
// Don't rename if there is a binding that hides the global.
return;
}
path.node.name = globalMappings.get(path.node.name);
}
}];
}
}
module.exports = {
IdentifierNormalizer: IdentifierNormalizer,
};
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Numbers mutator.
*/
'use strict';
const babelTypes = require('@babel/types');
const common = require('./common.js');
const random = require('../random.js');
const mutator = require('./mutator.js');
const MIN_SAFE_INTEGER = -9007199254740991;
const MAX_SAFE_INTEGER = 9007199254740991;
function isObjectKey(path) {
return (path.parent &&
babelTypes.isObjectMember(path.parent) &&
path.parent.key === path.node);
}
function createRandomNumber(value) {
// TODO(ochang): Maybe replace with variable.
const probability = random.random();
if (probability < 0.01) {
return babelTypes.numericLiteral(
random.randInt(MIN_SAFE_INTEGER, MAX_SAFE_INTEGER));
} else if (probability < 0.06) {
return common.randomInterestingNumber();
} else {
return common.nearbyRandomNumber(value);
}
}
class NumberMutator extends mutator.Mutator {
constructor(settings) {
super();
this.settings = settings;
}
ignore(path) {
return !random.choose(this.settings.MUTATE_NUMBERS) ||
common.isInForLoopCondition(path) ||
common.isInWhileLoop(path);
}
randomReplace(path, value, forcePositive=false) {
const randomNumber = createRandomNumber(value);
if (forcePositive) {
randomNumber.value = Math.abs(randomNumber.value);
}
this.annotate(
path.node,
`Replaced ${value} with ${randomNumber.value}`);
this.replaceWithSkip(path, randomNumber);
}
get visitor() {
const thisMutator = this;
return {
NumericLiteral(path) {
if (thisMutator.ignore(path)) {
return;
}
// We handle negative unary expressions separately to replace the whole
// expression below. E.g. -5 is UnaryExpression(-, NumericLiteral(5)).
if (path.parent && babelTypes.isUnaryExpression(path.parent) &&
path.parent.operator === '-') {
return;
}
// Enfore positive numbers if the literal is the key of an object
// property or method. Negative keys cause syntax errors.
const forcePositive = isObjectKey(path);
thisMutator.randomReplace(path, path.node.value, forcePositive);
},
UnaryExpression(path) {
if (thisMutator.ignore(path)) {
return;
}
// Handle the case we ignore above.
if (path.node.operator === '-' &&
babelTypes.isNumericLiteral(path.node.argument)) {
thisMutator.randomReplace(path, -path.node.argument.value);
}
}
};
}
}
module.exports = {
NumberMutator: NumberMutator,
};
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Mutator for object expressions.
*/
'use strict';
const babelTypes = require('@babel/types');
const common = require('./common.js');
const mutator = require('./mutator.js');
const random = require('../random.js');
const MAX_PROPERTIES = 50;
/**
* Turn the key of an object property into a string literal.
*/
function keyToString(key) {
if (babelTypes.isNumericLiteral(key)) {
return babelTypes.stringLiteral(key.value.toString());
}
if (babelTypes.isIdentifier(key)) {
return babelTypes.stringLiteral(key.name);
}
// Already a string literal.
return key;
}
class ObjectMutator extends mutator.Mutator {
constructor(settings) {
super();
this.settings = settings;
}
get visitor() {
const thisMutator = this;
return {
ObjectExpression(path) {
const properties = path.node.properties;
if (!random.choose(thisMutator.settings.MUTATE_OBJECTS) ||
properties.length > MAX_PROPERTIES) {
return;
}
// Use the indices of object properties for mutations. We ignore
// getters and setters.
const propertyIndicies = [];
for (const [index, property] of properties.entries()) {
if (babelTypes.isObjectProperty(property)) {
propertyIndicies.push(index);
}
}
// The mutations below require at least one property.
if (!propertyIndicies.length) {
return;
}
// Annotate object expression with the action taken.
function annotate(message) {
thisMutator.annotate(path.node, message);
}
function getOneRandomProperty() {
return properties[random.single(propertyIndicies)];
}
function getTwoRandomProperties() {
const [a, b] = random.sample(propertyIndicies, 2);
return [properties[a], properties[b]];
}
function swapPropertyValues() {
if (propertyIndicies.length > 1) {
annotate('Swap properties');
const [a, b] = getTwoRandomProperties();
[a.value, b.value] = [b.value, a.value];
}
}
function duplicatePropertyValue() {
if (propertyIndicies.length > 1) {
const [a, b] = random.shuffle(getTwoRandomProperties());
if (common.isLargeNode(b.value)) {
return;
}
annotate('Duplicate a property value');
a.value = babelTypes.cloneDeep(b.value);
}
}
function insertRandomValue() {
annotate('Insert a random value');
const property = getOneRandomProperty();
property.value = common.randomValue(path);
}
function stringifyKey() {
annotate('Stringify a property key');
const property = getOneRandomProperty();
property.key = keyToString(property.key);
}
function removeProperty() {
annotate('Remove a property');
properties.splice(random.single(propertyIndicies), 1);
}
// Mutation options. Repeated mutations have a higher probability.
const mutations = [
swapPropertyValues,
swapPropertyValues,
duplicatePropertyValue,
duplicatePropertyValue,
insertRandomValue,
insertRandomValue,
removeProperty,
stringifyKey,
];
// Perform mutation.
random.single(mutations)();
},
}
}
}
module.exports = {
ObjectMutator: ObjectMutator,
};
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Try catch wrapper.
*/
const babelTypes = require('@babel/types');
const common = require('./common.js');
const mutator = require('./mutator.js');
const random = require('../random.js');
// Default target probability for skipping try-catch completely.
const DEFAULT_SKIP_PROB = 0.2;
// Default target probability to wrap only on toplevel, i.e. to not nest
// try-catch.
const DEFAULT_TOPLEVEL_PROB = 0.3;
// Probability to deviate from defaults and use extreme cases.
const IGNORE_DEFAULT_PROB = 0.05;
// Member expressions to be wrapped. List of (object, property) identifier
// tuples.
const WRAPPED_MEMBER_EXPRESSIONS = [
['WebAssembly', 'Module'],
['WebAssembly', 'Instantiate'],
];
function wrapTryCatch(node) {
return babelTypes.tryStatement(
babelTypes.blockStatement([node]),
babelTypes.catchClause(
babelTypes.identifier('e'),
babelTypes.blockStatement([])));
}
function wrapTryCatchInFunction(node) {
const ret = wrapTryCatch(babelTypes.returnStatement(node));
const anonymousFun = babelTypes.functionExpression(
null, [], babelTypes.blockStatement([ret]));
return babelTypes.callExpression(anonymousFun, []);
}
// Wrap particular member expressions after `new` that are known to appear
// in initializer lists of `let` and `const`.
function replaceNewExpression(path) {
const callee = path.node.callee;
if (!babelTypes.isMemberExpression(callee) ||
!babelTypes.isIdentifier(callee.object) ||
!babelTypes.isIdentifier(callee.property)) {
return;
}
if (WRAPPED_MEMBER_EXPRESSIONS.some(
([object, property]) => callee.object.name === object &&
callee.property.name === property)) {
path.replaceWith(wrapTryCatchInFunction(path.node));
path.skip();
}
}
function replaceAndSkip(path) {
if (!babelTypes.isLabeledStatement(path.parent) ||
!babelTypes.isLoop(path.node)) {
// Don't wrap loops with labels as it makes continue
// statements syntactically invalid. We wrap the label
// instead below.
path.replaceWith(wrapTryCatch(path.node));
}
// Prevent infinite looping.
path.skip();
}
class AddTryCatchMutator extends mutator.Mutator {
callWithProb(path, fun) {
const probability = random.random();
if (probability < this.skipProb * this.loc) {
// Entirely skip try-catch wrapper.
path.skip();
} else if (probability < (this.skipProb + this.toplevelProb) * this.loc) {
// Only wrap on top-level.
fun(path);
}
}
get visitor() {
const thisMutator = this;
const accessStatement = {
enter(path) {
thisMutator.callWithProb(path, replaceAndSkip);
},
exit(path) {
// Apply nested wrapping (is only executed if not skipped above).
replaceAndSkip(path);
}
};
return {
Program: {
enter(path) {
// Track original source location fraction in [0, 1).
thisMutator.loc = 0;
// Target probability for skipping try-catch.
thisMutator.skipProb = DEFAULT_SKIP_PROB;
// Target probability for not nesting try-catch.
thisMutator.toplevelProb = DEFAULT_TOPLEVEL_PROB;
// Maybe deviate from target probability for the entire test.
if (random.choose(IGNORE_DEFAULT_PROB)) {
thisMutator.skipProb = random.uniform(0, 1);
thisMutator.toplevelProb = random.uniform(0, 1);
thisMutator.annotate(
path.node,
'Target skip probability ' + thisMutator.skipProb +
' and toplevel probability ' + thisMutator.toplevelProb);
}
}
},
Noop: {
enter(path) {
if (common.getSourceLoc(path.node)) {
thisMutator.loc = common.getSourceLoc(path.node);
}
},
},
ExpressionStatement: accessStatement,
IfStatement: accessStatement,
LabeledStatement: {
enter(path) {
// Apply an extra try-catch around the label of a loop, since we
// ignore the loop itself if it has a label.
if (babelTypes.isLoop(path.node.body)) {
thisMutator.callWithProb(path, replaceAndSkip);
}
},
exit(path) {
// Apply nested wrapping (is only executed if not skipped above).
if (babelTypes.isLoop(path.node.body)) {
replaceAndSkip(path);
}
},
},
// This covers {While|DoWhile|ForIn|ForOf|For}Statement.
Loop: accessStatement,
NewExpression: {
enter(path) {
thisMutator.callWithProb(path, replaceNewExpression);
},
exit(path) {
// Apply nested wrapping (is only executed if not skipped above).
replaceNewExpression(path);
}
},
SwitchStatement: accessStatement,
VariableDeclaration: {
enter(path) {
if (path.node.kind !== 'var' || babelTypes.isLoop(path.parent))
return;
thisMutator.callWithProb(path, replaceAndSkip);
},
exit(path) {
if (path.node.kind !== 'var' || babelTypes.isLoop(path.parent))
return;
// Apply nested wrapping (is only executed if not skipped above).
replaceAndSkip(path);
}
},
WithStatement: accessStatement,
};
}
}
module.exports = {
AddTryCatchMutator: AddTryCatchMutator,
}
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Variables mutator.
*/
'use strict';
const babelTypes = require('@babel/types');
const common = require('./common.js');
const random = require('../random.js');
const mutator = require('./mutator.js');
function _isInFunctionParam(path) {
const child = path.find(p => p.parent && babelTypes.isFunction(p.parent));
return child && child.parentKey === 'params';
}
class VariableMutator extends mutator.Mutator {
constructor(settings) {
super();
this.settings = settings;
}
get visitor() {
const thisMutator = this;
return {
Identifier(path) {
if (!random.choose(thisMutator.settings.MUTATE_VARIABLES)) {
return;
}
if (!common.isVariableIdentifier(path.node.name)) {
return;
}
// Don't mutate variables that are being declared.
if (babelTypes.isVariableDeclarator(path.parent)) {
return;
}
// Don't mutate function params.
if (_isInFunctionParam(path)) {
return;
}
if (common.isInForLoopCondition(path) ||
common.isInWhileLoop(path)) {
return;
}
const randVar = common.randomVariable(path);
if (!randVar) {
return;
}
const newName = randVar.name;
thisMutator.annotate(
path.node,
`Replaced ${path.node.name} with ${newName}`);
path.node.name = newName;
}
};
}
}
module.exports = {
VariableMutator: VariableMutator,
};
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Variables mutator.
*/
'use strict';
const babelTemplate = require('@babel/template').default;
const babelTypes = require('@babel/types');
const common = require('./common.js');
const random = require('../random.js');
const mutator = require('./mutator.js');
const MAX_MUTATION_RECURSION_DEPTH = 5;
class VariableOrObjectMutator extends mutator.Mutator {
constructor(settings) {
super();
this.settings = settings;
}
_randomVariableOrObject(path) {
const randomVar = common.randomVariable(path);
if (random.choose(0.05) || !randomVar) {
return common.randomObject();
}
return randomVar;
}
_randomVariableOrObjectMutations(path, recurseDepth=0) {
if (recurseDepth >= MAX_MUTATION_RECURSION_DEPTH) {
return new Array();
}
const probability = random.random();
if (probability < 0.3) {
const first = this._randomVariableOrObjectMutations(path, recurseDepth + 1);
const second = this._randomVariableOrObjectMutations(
path, recurseDepth + 1);
return first.concat(second);
}
const randVarOrObject = this._randomVariableOrObject(path);
const randProperty = common.randomProperty(randVarOrObject);
let newRandVarOrObject = randVarOrObject;
if (random.choose(0.2)) {
newRandVarOrObject = this._randomVariableOrObject(path);
}
const mutations = new Array();
if (probability < 0.4) {
const template = babelTemplate(
'delete IDENTIFIER[PROPERTY], __callGC()')
mutations.push(template({
IDENTIFIER: randVarOrObject,
PROPERTY: randProperty
}));
} else if (probability < 0.5) {
const template = babelTemplate(
'IDENTIFIER[PROPERTY], __callGC()')
mutations.push(template({
IDENTIFIER: randVarOrObject,
PROPERTY: randProperty
}));
} else if (probability < 0.6) {
const template = babelTemplate(
'IDENTIFIER[PROPERTY] = RANDOM, __callGC()')
mutations.push(template({
IDENTIFIER: randVarOrObject,
PROPERTY: randProperty,
RANDOM: common.randomValue(path),
}));
} else if (probability < 0.7) {
mutations.push(
babelTypes.expressionStatement(
common.callRandomFunction(path, randVarOrObject)));
} else if (probability < 0.8) {
const template = babelTemplate(
'VAR = IDENTIFIER, __callGC()')
var randomVar = common.randomVariable(path);
if (!randomVar) {
return mutations;
}
mutations.push(template({
VAR: randomVar,
IDENTIFIER: randVarOrObject,
}));
} else if (probability < 0.9) {
const template = babelTemplate(
'if (IDENTIFIER != null && typeof(IDENTIFIER) == "object") ' +
'Object.defineProperty(IDENTIFIER, PROPERTY, {value: VALUE})')
mutations.push(template({
IDENTIFIER: newRandVarOrObject,
PROPERTY: randProperty,
VALUE: common.randomValue(path),
}));
} else {
const template = babelTemplate(
'if (IDENTIFIER != null && typeof(IDENTIFIER) == "object") ' +
'Object.defineProperty(IDENTIFIER, PROPERTY, {' +
'get: function() { GETTER_MUTATION ; return VALUE; },' +
'set: function(value) { SETTER_MUTATION; }' +
'})');
mutations.push(template({
IDENTIFIER: newRandVarOrObject,
PROPERTY: randProperty,
GETTER_MUTATION: this._randomVariableOrObjectMutations(
path, recurseDepth + 1),
SETTER_MUTATION: this._randomVariableOrObjectMutations(
path, recurseDepth + 1),
VALUE: common.randomValue(path),
}));
}
return mutations;
}
get visitor() {
const settings = this.settings;
const thisMutator = this;
return {
ExpressionStatement(path) {
if (!random.choose(settings.ADD_VAR_OR_OBJ_MUTATIONS)) {
return;
}
const mutations = thisMutator._randomVariableOrObjectMutations(path);
thisMutator.annotate(mutations[0], 'Random mutation');
if (random.choose(0.5)) {
thisMutator.insertBeforeSkip(path, mutations);
} else {
thisMutator.insertAfterSkip(path, mutations);
}
path.skip();
}
};
}
}
module.exports = {
VariableOrObjectMutator: VariableOrObjectMutator,
};
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "ochang_js_fuzzer",
"version": "1.0.0",
"description": "",
"main": "run.js",
"scripts": {
"test": "APP_NAME=d8 mocha"
},
"bin": "run.js",
"author": "ochang@google.com",
"license": "ISC",
"dependencies": {
"@babel/generator": "^7.1.3",
"@babel/template": "^7.1.2",
"@babel/traverse": "^7.1.4",
"@babel/types": "^7.1.3",
"@babel/parser": "^7.1.3",
"commander": "^2.11.0",
"globals": "^10.1.0",
"tempfile": "^3.0.0",
"tempy": "^0.5.0"
},
"devDependencies": {
"eslint": "^6.8.0",
"mocha": "^3.5.3",
"pkg": "^4.3.4",
"prettier": "2.0.5",
"sinon": "^4.0.0"
},
"pkg": {
"assets": "resources/**/*"
}
}
#!/bin/bash
# Copyright 2020 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
OS="linux"
OS_LABEL="Linux"
SUFFIX=""
if [[ -n "$1" && $1 == "win" ]]; then
OS="win"
OS_LABEL="Windows"
SUFFIX=".exe"
elif [[ -n "$1" && $1 == "macos" ]]; then
OS="macos"
OS_LABEL="MacOS"
fi
echo "Building and packaging for $OS_LABEL..."
(set -x; $DIR/node_modules/.bin/pkg -t node10-$OS-x64 $DIR)
rm -rf $DIR/output > /dev/null 2>&1 || true
rm $DIR/output.zip > /dev/null 2>&1 || true
mkdir $DIR/output
cd $DIR/output
ln -s ../db db
ln -s ../ochang_js_fuzzer$SUFFIX run$SUFFIX
ln -s ../foozzie_launcher.py foozzie_launcher.py
echo "Creating $DIR/output.zip"
(set -x; zip -r $DIR/output.zip * > /dev/null)
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Random helpers.
*/
'use strict';
const assert = require('assert');
function randInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function choose(probability) {
return Math.random() < probability;
}
function random() {
return Math.random();
}
function uniform(min, max) {
return Math.random() * (max - min) + min;
}
function sample(iterable, count) {
const result = new Array(count);
let index = 0;
for (const item of iterable) {
if (index < count) {
result[index] = item;
} else {
const randIndex = randInt(0, index);
if (randIndex < count) {
result[randIndex] = item;
}
}
index++;
}
if (index < count) {
// Not enough items.
result.length = index;
}
return result;
}
function swap(array, p1, p2) {
[array[p1], array[p2]] = [array[p2], array[p1]];
}
/**
* Returns "count" elements, randomly selected from "highProbArray" and
* "lowProbArray". Elements from highProbArray have a "factor" times
* higher chance to be chosen. As a side effect, this swaps the chosen
* elements to the end of the respective input arrays. The complexity is
* O(count).
*/
function twoBucketSample(lowProbArray, highProbArray, factor, count) {
// Track number of available elements for choosing.
let low = lowProbArray.length;
let high = highProbArray.length;
assert(low + high >= count);
const result = [];
for (let i = 0; i < count; i++) {
// Map a random number to the summarized indices of both arrays. Give
// highProbArray elements a "factor" times higher probability.
const p = random();
const index = Math.floor(p * (high * factor + low));
if (index < low) {
// If the index is in the low part, draw the element and discard it.
result.push(lowProbArray[index]);
swap(lowProbArray, index, --low);
} else {
// Same as above but for a highProbArray element. The index is first
// mapped back to the array's range.
const highIndex = Math.floor((index - low) / factor);
result.push(highProbArray[highIndex]);
swap(highProbArray, highIndex, --high);
}
}
return result;
}
function single(array) {
return array[randInt(0, array.length - 1)];
}
function shuffle(array) {
for (let i = 0; i < array.length - 1; i++) {
const j = randInt(i, array.length - 1);
swap(array, i, j);
}
return array;
}
module.exports = {
choose: choose,
randInt: randInt,
random: random,
sample: sample,
shuffle: shuffle,
single: single,
twoBucketSample: twoBucketSample,
uniform: uniform,
}
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Adjust chakra behavior for differential fuzzing.
this.WScript = new Proxy({}, {
get(target, name) {
switch (name) {
case 'Echo':
return __prettyPrintExtra;
default:
return {};
}
}
});
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function debug(msg) {
__prettyPrintExtra(msg);
}
function shouldBe(_a) {
__prettyPrintExtra((typeof _a == "function" ? _a() : eval(_a)));
}
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Helpers for printing in correctness fuzzing.
// Global helper functions for printing.
var __prettyPrint;
var __prettyPrintExtra;
// Track caught exceptions.
var __caught = 0;
// Track a hash of all printed values - printing is cut off after a
// certain size.
var __hash = 0;
(function() {
const charCodeAt = String.prototype.charCodeAt;
const join = Array.prototype.join;
const map = Array.prototype.map;
const substring = String.prototype.substring;
const toString = Object.prototype.toString;
// Same as in mjsunit.js.
const classOf = function(object) {
// Argument must not be null or undefined.
const string = toString.call(object);
// String has format [object <ClassName>].
return substring.call(string, 8, string.length - 1);
};
// For standard cases use original prettyPrinted from mjsunit.
const origPrettyPrinted = prettyPrinted;
// Override prettyPrinted with a version that also recusively prints objects
// and arrays with a depth of 4. We don't track circles, but we'd cut off
// after a depth of 4 if there are any.
prettyPrinted = function prettyPrinted(value, depth=4) {
if (depth <= 0) {
return "...";
}
switch (typeof value) {
case "object":
if (value === null) return "null";
switch (classOf(value)) {
case "Array":
return prettyPrintedArray(value, depth);
case "Object":
return prettyPrintedObject(value, depth);
}
}
// Fall through to original version for all other types.
return origPrettyPrinted(value);
}
// Helper for pretty array with depth.
function prettyPrintedArray(array, depth) {
const result = map.call(array, (value, index, array) => {
if (value === undefined && !(index in array)) return "";
return prettyPrinted(value, depth - 1);
});
return `[${join.call(result, ", ")}]`;
}
// Helper for pretty objects with depth.
function prettyPrintedObject(object, depth) {
const keys = Object.keys(object);
const prettyValues = map.call(keys, (key) => {
return `${key}: ${prettyPrinted(object[key], depth - 1)}`;
});
const content = join.call(prettyValues, ", ");
return `${object.constructor.name || "Object"}{${content}}`;
}
// Helper for calculating a hash code of a string.
function hashCode(str) {
let hash = 0;
if (str.length == 0) {
return hash;
}
for (let i = 0; i < str.length; i++) {
const char = charCodeAt.call(str, i);
hash = ((hash << 5) - hash) + char;
hash = hash & hash;
}
return hash;
}
// Upper limit for calling extra printing. When reached, hashes of
// strings are tracked and printed instead.
let maxExtraPrinting = 100;
// Helper for pretty printing.
__prettyPrint = function(value, extra=false) {
let str = prettyPrinted(value);
// Change __hash with the contents of the full string to
// keep track of differences also when we don't print.
const hash = hashCode(str);
__hash = hashCode(hash + __hash.toString());
if (extra && maxExtraPrinting-- <= 0) {
return;
}
// Cut off long strings to prevent overloading I/O. We still track
// the hash of the full string.
if (str.length > 64) {
const head = substring.call(str, 0, 54);
const tail = substring.call(str, str.length - 10, str.length - 1);
str = `${head}[...]${tail}`;
}
print(str);
};
__prettyPrintExtra = function (value) {
__prettyPrint(value, true);
}
})();
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Substitute for mjsunit. We reuse prettyPrinted from mjsunit, but only if
// it is loaded. If not, we use this substitute instead.
let prettyPrinted = value => value;
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Don't breach stack limit in differential fuzzing as it leads to
// early bailout.
runNearStackLimit = function(f) {
try {
f();
} catch (e) {}
};
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Adjust mjsunit behavior for differential fuzzing.
// We're not interested in stack traces.
MjsUnitAssertionError = () => {};
// Do more printing in assertions for more correctness coverage.
failWithMessage = message => { __prettyPrint(message); };
assertSame = (expected, found, name_opt) => { __prettyPrint(found); };
assertNotSame = (expected, found, name_opt) => { __prettyPrint(found); };
assertEquals = (expected, found, name_opt) => { __prettyPrint(found); };
assertNotEquals = (expected, found, name_opt) => { __prettyPrint(found); };
assertNull = (value, name_opt) => { __prettyPrint(value); };
assertNotNull = (value, name_opt) => { __prettyPrint(value); };
// Suppress optimization status as it leads to false positives.
assertUnoptimized = () => {};
assertOptimized = () => {};
isNeverOptimize = () => {};
isAlwaysOptimize = () => {};
isInterpreted = () => {};
isOptimized = () => {};
isTurboFanned = () => {};
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Slightly modified variants from http://code.fitness/post/2016/01/javascript-enumerate-methods.html.
function __isPropertyOfType(obj, name, type) {
let desc;
try {
desc = Object.getOwnPropertyDescriptor(obj, name);
} catch(e) {
return false;
}
if (!desc)
return false;
return typeof type === 'undefined' || typeof desc.value === type;
}
function __getProperties(obj, type) {
if (typeof obj === "undefined" || obj === null)
return [];
let properties = [];
for (let name of Object.getOwnPropertyNames(obj)) {
if (__isPropertyOfType(obj, name, type))
properties.push(name);
}
let proto = Object.getPrototypeOf(obj);
while (proto && proto != Object.prototype) {
Object.getOwnPropertyNames(proto)
.forEach (name => {
if (name !== 'constructor') {
if (__isPropertyOfType(proto, name, type))
properties.push(name);
}
});
proto = Object.getPrototypeOf(proto);
}
return properties;
}
function* __getObjects(root = this, level = 0) {
if (level > 4)
return;
let obj_names = __getProperties(root, 'object');
for (let obj_name of obj_names) {
let obj = root[obj_name];
if (obj === root)
continue;
yield obj;
yield* __getObjects(obj, level + 1);
}
}
function __getRandomObject(seed) {
let objects = [];
for (let obj of __getObjects()) {
objects.push(obj);
}
return objects[seed % objects.length];
}
function __getRandomProperty(obj, seed) {
let properties = __getProperties(obj);
if (!properties.length)
return undefined;
return properties[seed % properties.length];
}
function __callRandomFunction(obj, seed, ...args)
{
let functions = __getProperties(obj, 'function');
if (!functions.length)
return;
let random_function = functions[seed % functions.length];
try {
obj[random_function](...args);
} catch(e) { }
}
function runNearStackLimit(f) {
function t() {
try {
return t();
} catch (e) {
return f();
}
};
try {
return t();
} catch (e) {}
}
// Limit number of times we cause major GCs in tests to reduce hangs
// when called within larger loops.
let __callGC;
(function() {
let countGC = 0;
__callGC = function() {
if (countGC++ < 50) {
gc();
}
};
})();
// Neuter common test functions.
try { this.failWithMessage = nop; } catch(e) { }
try { this.triggerAssertFalse = nop; } catch(e) { }
try { this.quit = nop; } catch(e) { }
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Minimally stub out methods from JSTest's standalone-pre.js.
function description(msg) {}
function debug(msg) {}
function shouldBe(_a) {
print((typeof _a == "function" ? _a() : eval(_a)));
}
function shouldBeTrue(_a) { shouldBe(_a); }
function shouldBeFalse(_a) { shouldBe(_a); }
function shouldBeNaN(_a) { shouldBe(_a); }
function shouldBeNull(_a) { shouldBe(_a); }
function shouldNotThrow(_a) { shouldBe(_a); }
function shouldThrow(_a) { shouldBe(_a); }
function noInline() {}
function finishJSTest() {}
// Stub out $vm.
try {
$vm;
} catch(e) {
const handler = {
get: function(x, prop) {
if (prop == Symbol.toPrimitive) {
return function() { return undefined; };
}
return dummy;
},
};
const dummy = new Proxy(function() { return dummy; }, handler);
this.$vm = dummy;
}
// Other functions.
function ensureArrayStorage() {}
function transferArrayBuffer() {}
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Helper neuter function.
function nop() { return false; }
// Stubs for non-standard functions.
try { gc; } catch(e) {
this.gc = function () {
for (let i = 0; i < 10000; i++) {
let s = new String("AAAA" + Math.random());
}
}
}
try { uneval; } catch(e) { this.uneval = this.nop; }
try {
// For Chakra tests.
WScript;
} catch(e) {
this.WScript = new Proxy({}, {
get(target, name) {
switch (name) {
case 'Echo':
return print;
default:
return {};
}
}
});
}
try { this.alert = console.log; } catch(e) { }
try { this.print = console.log; } catch(e) { }
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Description of this file.
*/
'use strict';
const assert = require('assert');
const fs = require('fs');
const path = require('path');
const program = require('commander');
const corpus = require('./corpus.js');
const differentialScriptMutator = require('./differential_script_mutator.js');
const random = require('./random.js');
const scriptMutator = require('./script_mutator.js');
const sourceHelpers = require('./source_helpers.js');
// Maximum number of test inputs to use for one fuzz test.
const MAX_TEST_INPUTS_PER_TEST = 10;
// Base implementations for default or differential fuzzing.
const SCRIPT_MUTATORS = {
default: scriptMutator.ScriptMutator,
foozzie: differentialScriptMutator.DifferentialScriptMutator,
};
function getRandomInputs(primaryCorpus, secondaryCorpora, count) {
count = random.randInt(2, count);
// Choose 40%-80% of inputs from primary corpus.
const primaryCount = Math.floor(random.uniform(0.4, 0.8) * count);
count -= primaryCount;
let inputs = primaryCorpus.getRandomTestcases(primaryCount);
// Split remainder equally between the secondary corpora.
const secondaryCount = Math.floor(count / secondaryCorpora.length);
for (let i = 0; i < secondaryCorpora.length; i++) {
let currentCount = secondaryCount;
if (i == secondaryCorpora.length - 1) {
// Last one takes the remainder.
currentCount = count;
}
count -= currentCount;
if (currentCount) {
inputs = inputs.concat(
secondaryCorpora[i].getRandomTestcases(currentCount));
}
}
return random.shuffle(inputs);
}
function collect(value, total) {
total.push(value);
return total;
}
function overrideSettings(settings, settingOverrides) {
for (const setting of settingOverrides) {
const parts = setting.split('=');
settings[parts[0]] = parseFloat(parts[1]);
}
}
function* randomInputGen(engine) {
const inputDir = path.resolve(program.input_dir);
const v8Corpus = new corpus.Corpus(inputDir, 'v8');
const chakraCorpus = new corpus.Corpus(inputDir, 'chakra');
const spiderMonkeyCorpus = new corpus.Corpus(inputDir, 'spidermonkey');
const jscCorpus = new corpus.Corpus(inputDir, 'WebKit/JSTests');
const crashTestsCorpus = new corpus.Corpus(inputDir, 'CrashTests');
for (let i = 0; i < program.no_of_files; i++) {
let inputs;
if (engine === 'V8') {
inputs = getRandomInputs(
v8Corpus,
random.shuffle([chakraCorpus, spiderMonkeyCorpus, jscCorpus,
crashTestsCorpus, v8Corpus]),
MAX_TEST_INPUTS_PER_TEST);
} else if (engine == 'chakra') {
inputs = getRandomInputs(
chakraCorpus,
random.shuffle([v8Corpus, spiderMonkeyCorpus, jscCorpus,
crashTestsCorpus]),
MAX_TEST_INPUTS_PER_TEST);
} else if (engine == 'spidermonkey') {
inputs = getRandomInputs(
spiderMonkeyCorpus,
random.shuffle([v8Corpus, chakraCorpus, jscCorpus,
crashTestsCorpus]),
MAX_TEST_INPUTS_PER_TEST);
} else {
inputs = getRandomInputs(
jscCorpus,
random.shuffle([chakraCorpus, spiderMonkeyCorpus, v8Corpus,
crashTestsCorpus]),
MAX_TEST_INPUTS_PER_TEST);
}
if (inputs.length > 0) {
yield inputs;
}
}
}
function* corpusInputGen() {
const inputCorpus = new corpus.Corpus(
path.resolve(program.input_dir),
program.mutate_corpus,
program.extra_strict);
for (const input of inputCorpus.getAllTestcases()) {
yield [input];
}
}
function* enumerate(iterable) {
let i = 0;
for (const value of iterable) {
yield [i, value];
i++;
}
}
function main() {
Error.stackTraceLimit = Infinity;
program
.version('0.0.1')
.option('-i, --input_dir <path>', 'Input directory.')
.option('-o, --output_dir <path>', 'Output directory.')
.option('-n, --no_of_files <n>', 'Output directory.', parseInt)
.option('-c, --mutate_corpus <name>', 'Mutate single files in a corpus.')
.option('-e, --extra_strict', 'Additionally parse files in strict mode.')
.option('-m, --mutate <path>', 'Mutate a file and output results.')
.option('-s, --setting [setting]', 'Settings overrides.', collect, [])
.option('-v, --verbose', 'More verbose printing.')
.option('-z, --zero_settings', 'Zero all settings.')
.parse(process.argv);
const settings = scriptMutator.defaultSettings();
if (program.zero_settings) {
for (const key of Object.keys(settings)) {
settings[key] = 0.0;
}
}
if (program.setting.length > 0) {
overrideSettings(settings, program.setting);
}
let app_name = process.env.APP_NAME;
if (app_name && app_name.endsWith('.exe')) {
app_name = app_name.substr(0, app_name.length - 4);
}
if (app_name === 'd8' || app_name === 'v8_foozzie.py') {
// V8 supports running the raw d8 executable or the differential fuzzing
// harness 'foozzie'.
settings.engine = 'V8';
} else if (app_name === 'ch') {
settings.engine = 'chakra';
} else if (app_name === 'js') {
settings.engine = 'spidermonkey';
} else if (app_name === 'jsc') {
settings.engine = 'jsc';
} else {
console.log('ERROR: Invalid APP_NAME');
process.exit(1);
}
const mode = process.env.FUZZ_MODE || 'default';
assert(mode in SCRIPT_MUTATORS, `Unknown mode ${mode}`);
const mutator = new SCRIPT_MUTATORS[mode](settings);
if (program.mutate) {
const absPath = path.resolve(program.mutate);
const baseDir = path.dirname(absPath);
const fileName = path.basename(absPath);
const input = sourceHelpers.loadSource(
baseDir, fileName, program.extra_strict);
const mutated = mutator.mutateMultiple([input]);
console.log(mutated.code);
return;
}
let inputGen;
if (program.mutate_corpus) {
inputGen = corpusInputGen();
} else {
inputGen = randomInputGen(settings.engine);
}
for (const [i, inputs] of enumerate(inputGen)) {
const outputPath = path.join(program.output_dir, 'fuzz-' + i + '.js');
const start = Date.now();
const paths = inputs.map(input => input.relPath);
try {
const mutated = mutator.mutateMultiple(inputs);
fs.writeFileSync(outputPath, mutated.code);
if (settings.engine === 'V8' && mutated.flags && mutated.flags.length > 0) {
const flagsPath = path.join(program.output_dir, 'flags-' + i + '.js');
fs.writeFileSync(flagsPath, mutated.flags.join(' '));
}
} catch (e) {
if (e.message.startsWith('ENOSPC')) {
console.log('ERROR: No space left. Bailing out...');
console.log(e);
return;
}
console.log(`ERROR: Exception during mutate: ${paths}`);
console.log(e);
continue;
} finally {
if (program.verbose) {
const duration = Date.now() - start;
console.log(`Mutating ${paths} took ${duration} ms.`);
}
}
if ((i + 1) % 10 == 0) {
console.log('Up to ', i + 1);
}
}
}
main();
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Script mutator.
*/
'use strict';
const fs = require('fs');
const path = require('path');
const common = require('./mutators/common.js');
const db = require('./db.js');
const sourceHelpers = require('./source_helpers.js');
const { AddTryCatchMutator } = require('./mutators/try_catch.js');
const { ArrayMutator } = require('./mutators/array_mutator.js');
const { CrossOverMutator } = require('./mutators/crossover_mutator.js');
const { ExpressionMutator } = require('./mutators/expression_mutator.js');
const { FunctionCallMutator } = require('./mutators/function_call_mutator.js');
const { IdentifierNormalizer } = require('./mutators/normalizer.js');
const { NumberMutator } = require('./mutators/number_mutator.js');
const { ObjectMutator } = require('./mutators/object_mutator.js');
const { VariableMutator } = require('./mutators/variable_mutator.js');
const { VariableOrObjectMutator } = require('./mutators/variable_or_object_mutation.js');
function defaultSettings() {
return {
ADD_VAR_OR_OBJ_MUTATIONS: 0.1,
DIFF_FUZZ_EXTRA_PRINT: 0.1,
DIFF_FUZZ_TRACK_CAUGHT: 0.4,
MUTATE_ARRAYS: 0.1,
MUTATE_CROSSOVER_INSERT: 0.05,
MUTATE_EXPRESSIONS: 0.1,
MUTATE_FUNCTION_CALLS: 0.1,
MUTATE_NUMBERS: 0.05,
MUTATE_OBJECTS: 0.1,
MUTATE_VARIABLES: 0.075,
};
}
class Result {
constructor(code, flags) {
this.code = code;
this.flags = flags;
}
}
class ScriptMutator {
constructor(settings, db_path=undefined) {
// Use process.cwd() to bypass pkg's snapshot filesystem.
this.mutateDb = new db.MutateDb(db_path || path.join(process.cwd(), 'db'));
this.mutators = [
new ArrayMutator(settings),
new ObjectMutator(settings),
new VariableMutator(settings),
new NumberMutator(settings),
new CrossOverMutator(settings, this.mutateDb),
new ExpressionMutator(settings),
new FunctionCallMutator(settings),
new VariableOrObjectMutator(settings),
new AddTryCatchMutator(settings),
];
}
_addMjsunitIfNeeded(dependencies, input) {
if (dependencies.has('mjsunit')) {
return;
}
if (!input.absPath.includes('mjsunit')) {
return;
}
// Find mjsunit.js
let mjsunitPath = input.absPath;
while (path.dirname(mjsunitPath) != mjsunitPath &&
path.basename(mjsunitPath) != 'mjsunit') {
mjsunitPath = path.dirname(mjsunitPath);
}
if (path.basename(mjsunitPath) == 'mjsunit') {
mjsunitPath = path.join(mjsunitPath, 'mjsunit.js');
dependencies.set('mjsunit', sourceHelpers.loadDependencyAbs(
input.baseDir, mjsunitPath));
return;
}
console.log('ERROR: Failed to find mjsunit.js');
}
_addSpiderMonkeyShellIfNeeded(dependencies, input) {
// Find shell.js files
const shellJsPaths = new Array();
let currentDir = path.dirname(input.absPath);
while (path.dirname(currentDir) != currentDir) {
const shellJsPath = path.join(currentDir, 'shell.js');
if (fs.existsSync(shellJsPath)) {
shellJsPaths.push(shellJsPath);
}
if (currentDir == 'spidermonkey') {
break;
}
currentDir = path.dirname(currentDir);
}
// Add shell.js dependencies in reverse to add ones that are higher up in
// the directory tree first.
for (let i = shellJsPaths.length - 1; i >= 0; i--) {
if (!dependencies.has(shellJsPaths[i])) {
const dependency = sourceHelpers.loadDependencyAbs(
input.baseDir, shellJsPaths[i]);
dependencies.set(shellJsPaths[i], dependency);
}
}
}
_addJSTestStubsIfNeeded(dependencies, input) {
if (dependencies.has('jstest_stubs') ||
!input.absPath.includes('JSTests')) {
return;
}
dependencies.set(
'jstest_stubs', sourceHelpers.loadResource('jstest_stubs.js'));
}
mutate(source) {
for (const mutator of this.mutators) {
mutator.mutate(source);
}
}
// Returns parsed dependencies for inputs.
resolveInputDependencies(inputs) {
const dependencies = new Map();
// Resolve test harness files.
inputs.forEach(input => {
try {
// TODO(machenbach): Some harness files contain load expressions
// that are not recursively resolved. We already remove them, but we
// also need to load the dependencies they point to.
this._addJSTestStubsIfNeeded(dependencies, input);
this._addMjsunitIfNeeded(dependencies, input)
this._addSpiderMonkeyShellIfNeeded(dependencies, input);
} catch (e) {
console.log(
'ERROR: Failed to resolve test harness for', input.relPath);
throw e;
}
});
// Resolve dependencies loaded within the input files.
inputs.forEach(input => {
try {
input.loadDependencies(dependencies);
} catch (e) {
console.log(
'ERROR: Failed to resolve dependencies for', input.relPath);
throw e;
}
});
// Map.values() returns values in insertion order.
return Array.from(dependencies.values());
}
// Combines input dependencies with fuzzer resources.
resolveDependencies(inputs) {
const dependencies = this.resolveInputDependencies(inputs);
// Add stubs for non-standard functions in the beginning.
dependencies.unshift(sourceHelpers.loadResource('stubs.js'));
// Add our fuzzing support helpers. This also overrides some common test
// functions from earlier dependencies that cause early bailouts.
dependencies.push(sourceHelpers.loadResource('fuzz_library.js'));
return dependencies;
}
// Normalizes, combines and mutates multiple inputs.
mutateInputs(inputs) {
const normalizerMutator = new IdentifierNormalizer();
for (const [index, input] of inputs.entries()) {
try {
normalizerMutator.mutate(input);
} catch (e) {
console.log('ERROR: Failed to normalize ', input.relPath);
throw e;
}
common.setSourceLoc(input, index, inputs.length);
}
// Combine ASTs into one. This is so that mutations have more context to
// cross over content between ASTs (e.g. variables).
const combinedSource = common.concatPrograms(inputs);
this.mutate(combinedSource);
return combinedSource;
}
mutateMultiple(inputs) {
// High level operation:
// 1) Compute dependencies from inputs.
// 2) Normalize, combine and mutate inputs.
// 3) Generate code with dependency code prepended.
const dependencies = this.resolveDependencies(inputs);
const combinedSource = this.mutateInputs(inputs);
const code = sourceHelpers.generateCode(combinedSource, dependencies);
const flags = common.concatFlags(dependencies.concat([combinedSource]));
return new Result(code, flags);
}
}
module.exports = {
defaultSettings: defaultSettings,
ScriptMutator: ScriptMutator,
};
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Source loader.
*/
const fs = require('fs');
const fsPath = require('path');
const { EOL } = require('os');
const babelGenerator = require('@babel/generator').default;
const babelTraverse = require('@babel/traverse').default;
const babelTypes = require('@babel/types');
const babylon = require('@babel/parser');
const exceptions = require('./exceptions.js');
const SCRIPT = Symbol('SCRIPT');
const MODULE = Symbol('MODULE');
const V8_BUILTIN_PREFIX = '__V8Builtin';
const V8_REPLACE_BUILTIN_REGEXP = new RegExp(
V8_BUILTIN_PREFIX + '(\\w+)\\(', 'g');
const BABYLON_OPTIONS = {
sourceType: 'script',
allowReturnOutsideFunction: true,
tokens: false,
ranges: false,
plugins: [
'asyncGenerators',
'bigInt',
'classPrivateMethods',
'classPrivateProperties',
'classProperties',
'doExpressions',
'exportDefaultFrom',
'nullishCoalescingOperator',
'numericSeparator',
'objectRestSpread',
'optionalCatchBinding',
'optionalChaining',
],
}
function _isV8OrSpiderMonkeyLoad(path) {
// 'load' and 'loadRelativeToScript' used by V8 and SpiderMonkey.
return (babelTypes.isIdentifier(path.node.callee) &&
(path.node.callee.name == 'load' ||
path.node.callee.name == 'loadRelativeToScript') &&
path.node.arguments.length == 1 &&
babelTypes.isStringLiteral(path.node.arguments[0]));
}
function _isChakraLoad(path) {
// 'WScript.LoadScriptFile' used by Chakra.
// TODO(ochang): The optional second argument can change semantics ("self",
// "samethread", "crossthread" etc).
// Investigate whether if it still makes sense to include them.
return (babelTypes.isMemberExpression(path.node.callee) &&
babelTypes.isIdentifier(path.node.callee.property) &&
path.node.callee.property.name == 'LoadScriptFile' &&
path.node.arguments.length >= 1 &&
babelTypes.isStringLiteral(path.node.arguments[0]));
}
function _findPath(path, caseSensitive=true) {
// If the path exists, return the path. Otherwise return null. Used to handle
// case insensitive matches for Chakra tests.
if (caseSensitive) {
return fs.existsSync(path) ? path : null;
}
path = fsPath.normalize(fsPath.resolve(path));
const pathComponents = path.split(fsPath.sep);
let realPath = fsPath.resolve(fsPath.sep);
for (let i = 1; i < pathComponents.length; i++) {
// For each path component, do a directory listing to see if there is a case
// insensitive match.
const curListing = fs.readdirSync(realPath);
let realComponent = null;
for (const component of curListing) {
if (i < pathComponents.length - 1 &&
!fs.statSync(fsPath.join(realPath, component)).isDirectory()) {
continue;
}
if (component.toLowerCase() == pathComponents[i].toLowerCase()) {
realComponent = component;
break;
}
}
if (!realComponent) {
return null;
}
realPath = fsPath.join(realPath, realComponent);
}
return realPath;
}
function _findDependentCodePath(filePath, baseDirectory, caseSensitive=true) {
const fullPath = fsPath.join(baseDirectory, filePath);
const realPath = _findPath(fullPath, caseSensitive)
if (realPath) {
// Check base directory of current file.
return realPath;
}
while (fsPath.dirname(baseDirectory) != baseDirectory) {
// Walk up the directory tree.
const testPath = fsPath.join(baseDirectory, filePath);
const realPath = _findPath(testPath, caseSensitive)
if (realPath) {
return realPath;
}
baseDirectory = fsPath.dirname(baseDirectory);
}
return null;
}
/**
* Removes V8/Spidermonkey/Chakra load expressions in a source AST and returns
* their string values in an array.
*
* @param {string} originalFilePath Absolute path to file.
* @param {AST} ast Babel AST of the sources.
*/
function resolveLoads(originalFilePath, ast) {
const dependencies = [];
babelTraverse(ast, {
CallExpression(path) {
const isV8OrSpiderMonkeyLoad = _isV8OrSpiderMonkeyLoad(path);
const isChakraLoad = _isChakraLoad(path);
if (!isV8OrSpiderMonkeyLoad && !isChakraLoad) {
return;
}
let loadValue = path.node.arguments[0].extra.rawValue;
// Normalize Windows path separators.
loadValue = loadValue.replace(/\\/g, fsPath.sep);
// Remove load call.
path.remove();
const resolvedPath = _findDependentCodePath(
loadValue, fsPath.dirname(originalFilePath), !isChakraLoad);
if (!resolvedPath) {
console.log('ERROR: Could not find dependent path for', loadValue);
return;
}
if (exceptions.isTestSkippedAbs(resolvedPath)) {
// Dependency is skipped.
return;
}
// Add the dependency path.
dependencies.push(resolvedPath);
}
});
return dependencies;
}
function isStrictDirective(directive) {
return (directive.value &&
babelTypes.isDirectiveLiteral(directive.value) &&
directive.value.value === 'use strict');
}
function replaceV8Builtins(code) {
return code.replace(/%(\w+)\(/g, V8_BUILTIN_PREFIX + '$1(');
}
function restoreV8Builtins(code) {
return code.replace(V8_REPLACE_BUILTIN_REGEXP, '%$1(');
}
function maybeUseStict(code, useStrict) {
if (useStrict) {
return `'use strict';${EOL}${EOL}${code}`;
}
return code;
}
class Source {
constructor(baseDir, relPath, flags, dependentPaths) {
this.baseDir = baseDir;
this.relPath = relPath;
this.flags = flags;
this.dependentPaths = dependentPaths;
this.sloppy = exceptions.isTestSloppyRel(relPath);
}
get absPath() {
return fsPath.join(this.baseDir, this.relPath);
}
/**
* Specifies if the source isn't compatible with strict mode.
*/
isSloppy() {
return this.sloppy;
}
/**
* Specifies if the source has a top-level 'use strict' directive.
*/
isStrict() {
throw Error('Not implemented');
}
/**
* Generates the code as a string without any top-level 'use strict'
* directives. V8 natives that were replaced before parsing are restored.
*/
generateNoStrict() {
throw Error('Not implemented');
}
/**
* Recursively adds dependencies of a this source file.
*
* @param {Map} dependencies Dependency map to which to add new, parsed
* dependencies unless they are already in the map.
* @param {Map} visitedDependencies A set for avoiding loops.
*/
loadDependencies(dependencies, visitedDependencies) {
visitedDependencies = visitedDependencies || new Set();
for (const absPath of this.dependentPaths) {
if (dependencies.has(absPath) ||
visitedDependencies.has(absPath)) {
// Already added.
continue;
}
// Prevent infinite loops.
visitedDependencies.add(absPath);
// Recursively load dependencies.
const dependency = loadDependencyAbs(this.baseDir, absPath);
dependency.loadDependencies(dependencies, visitedDependencies);
// Add the dependency.
dependencies.set(absPath, dependency);
}
}
}
/**
* Represents sources whose AST can be manipulated.
*/
class ParsedSource extends Source {
constructor(ast, baseDir, relPath, flags, dependentPaths) {
super(baseDir, relPath, flags, dependentPaths);
this.ast = ast;
}
isStrict() {
return !!this.ast.program.directives.filter(isStrictDirective).length;
}
generateNoStrict() {
const allDirectives = this.ast.program.directives;
this.ast.program.directives = this.ast.program.directives.filter(
directive => !isStrictDirective(directive));
try {
const code = babelGenerator(this.ast.program, {comments: true}).code;
return restoreV8Builtins(code);
} finally {
this.ast.program.directives = allDirectives;
}
}
}
/**
* Represents sources with cached code.
*/
class CachedSource extends Source {
constructor(source) {
super(source.baseDir, source.relPath, source.flags, source.dependentPaths);
this.use_strict = source.isStrict();
this.code = source.generateNoStrict();
}
isStrict() {
return this.use_strict;
}
generateNoStrict() {
return this.code;
}
}
/**
* Read file path into an AST.
*
* Post-processes the AST by replacing V8 natives and removing disallowed
* natives, as well as removing load expressions and adding the paths-to-load
* as meta data.
*/
function loadSource(baseDir, relPath, parseStrict=false) {
const absPath = fsPath.resolve(fsPath.join(baseDir, relPath));
const data = fs.readFileSync(absPath, 'utf-8');
if (guessType(data) !== SCRIPT) {
return null;
}
const preprocessed = maybeUseStict(replaceV8Builtins(data), parseStrict);
const ast = babylon.parse(preprocessed, BABYLON_OPTIONS);
removeComments(ast);
cleanAsserts(ast);
neuterDisallowedV8Natives(ast);
annotateWithOriginalPath(ast, relPath);
const flags = loadFlags(data);
const dependentPaths = resolveLoads(absPath, ast);
return new ParsedSource(ast, baseDir, relPath, flags, dependentPaths);
}
function guessType(data) {
if (data.includes('// MODULE')) {
return MODULE;
}
return SCRIPT;
}
/**
* Remove existing comments.
*/
function removeComments(ast) {
babelTraverse(ast, {
enter(path) {
babelTypes.removeComments(path.node);
}
});
}
/**
* Removes "Assert" from strings in spidermonkey shells or from older
* crash tests: https://crbug.com/1068268
*/
function cleanAsserts(ast) {
function replace(string) {
return string.replace(/Assert/g, 'A****t');
}
babelTraverse(ast, {
StringLiteral(path) {
path.node.value = replace(path.node.value);
path.node.extra.raw = replace(path.node.extra.raw);
path.node.extra.rawValue = replace(path.node.extra.rawValue);
},
TemplateElement(path) {
path.node.value.cooked = replace(path.node.value.cooked);
path.node.value.raw = replace(path.node.value.raw);
},
});
}
/**
* Filter out disallowed V8 runtime functions.
*/
function neuterDisallowedV8Natives(ast) {
babelTraverse(ast, {
CallExpression(path) {
if (!babelTypes.isIdentifier(path.node.callee) ||
!path.node.callee.name.startsWith(V8_BUILTIN_PREFIX)) {
return;
}
const functionName = path.node.callee.name.substr(
V8_BUILTIN_PREFIX.length);
if (!exceptions.isAllowedRuntimeFunction(functionName)) {
path.replaceWith(babelTypes.callExpression(
babelTypes.identifier('nop'), []));
}
}
});
}
/**
* Annotate code with original file path.
*/
function annotateWithOriginalPath(ast, relPath) {
if (ast.program && ast.program.body && ast.program.body.length > 0) {
babelTypes.addComment(
ast.program.body[0], 'leading', ' Original: ' + relPath, true);
}
}
// TODO(machenbach): Move this into the V8 corpus. Other test suites don't
// use this flag logic.
function loadFlags(data) {
const result = [];
let count = 0;
for (const line of data.split('\n')) {
if (count++ > 40) {
// No need to process the whole file. Flags are always added after the
// copyright header.
break;
}
const match = line.match(/\/\/ Flags:\s*(.*)\s*/);
if (!match) {
continue;
}
for (const flag of exceptions.filterFlags(match[1].split(/\s+/))) {
result.push(flag);
}
}
return result;
}
// Convenience helper to load sources with absolute paths.
function loadSourceAbs(baseDir, absPath) {
return loadSource(baseDir, fsPath.relative(baseDir, absPath));
}
const dependencyCache = new Map();
function loadDependency(baseDir, relPath) {
const absPath = fsPath.join(baseDir, relPath);
let dependency = dependencyCache.get(absPath);
if (!dependency) {
const source = loadSource(baseDir, relPath);
dependency = new CachedSource(source);
dependencyCache.set(absPath, dependency);
}
return dependency;
}
function loadDependencyAbs(baseDir, absPath) {
return loadDependency(baseDir, fsPath.relative(baseDir, absPath));
}
// Convenience helper to load a file from the resources directory.
function loadResource(fileName) {
return loadDependency(__dirname, fsPath.join('resources', fileName));
}
function generateCode(source, dependencies=[]) {
const allSources = dependencies.concat([source]);
const codePieces = allSources.map(
source => source.generateNoStrict());
if (allSources.some(source => source.isStrict()) &&
!allSources.some(source => source.isSloppy())) {
codePieces.unshift('\'use strict\';');
}
return codePieces.join(EOL + EOL);
}
module.exports = {
BABYLON_OPTIONS: BABYLON_OPTIONS,
generateCode: generateCode,
loadDependencyAbs: loadDependencyAbs,
loadResource: loadResource,
loadSource: loadSource,
loadSourceAbs: loadSourceAbs,
ParsedSource: ParsedSource,
}
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Test helpers.
*/
'use strict';
const assert = require('assert');
const path = require('path');
const fs = require('fs');
const sourceHelpers = require('../source_helpers.js');
const BASE_DIR = path.join(path.dirname(__dirname), 'test_data');
const DB_DIR = path.join(BASE_DIR, 'fake_db');
const HEADER = `// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
`;
/**
* Create a function that returns one of `probs` when called. It rotates
* through the values. Useful to replace `random.random()` in tests using
* the probabilities that trigger different interesting cases.
*/
function cycleProbabilitiesFun(probs) {
let index = 0;
return () => {
index = index % probs.length;
return probs[index++];
};
}
/**
* Replace Math.random with a deterministic pseudo-random function.
*/
function deterministicRandom(sandbox) {
let seed = 1;
function random() {
const x = Math.sin(seed++) * 10000;
return x - Math.floor(x);
}
sandbox.stub(Math, 'random').callsFake(() => { return random(); });
}
function loadTestData(relPath) {
return sourceHelpers.loadSource(BASE_DIR, relPath);
}
function assertExpectedResult(expectedPath, result) {
const absPath = path.join(BASE_DIR, expectedPath);
if (process.env.GENERATE) {
fs.writeFileSync(absPath, HEADER + result.trim() + '\n');
return;
}
// Omit copyright header when comparing files.
const expected = fs.readFileSync(absPath, 'utf-8').trim().split('\n');
expected.splice(0, 4);
assert.strictEqual(expected.join('\n'), result.trim());
}
module.exports = {
BASE_DIR: BASE_DIR,
DB_DIR: DB_DIR,
assertExpectedResult: assertExpectedResult,
cycleProbabilitiesFun: cycleProbabilitiesFun,
deterministicRandom: deterministicRandom,
loadTestData: loadTestData,
}
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Tests for mutating variables
*/
'use strict';
const babelTraverse = require('@babel/traverse').default;
const common = require('../mutators/common.js');
const helpers = require('./helpers.js');
describe('Available variables and functions', () => {
it('test', () => {
const source = helpers.loadTestData('available_variables.js');
const result = new Array();
babelTraverse(source.ast, {
CallExpression(path) {
result.push({
variables: common.availableVariables(path),
functions: common.availableFunctions(path),
});
}
});
helpers.assertExpectedResult(
'available_variables_expected.js',
JSON.stringify(result, null, 2));
});
});
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Corpus loading.
*/
'use strict';
const assert = require('assert');
const sinon = require('sinon');
const exceptions = require('../exceptions.js');
const corpus = require('../corpus.js');
const sandbox = sinon.createSandbox();
function testSoftSkipped(count, softSkipped, paths) {
sandbox.stub(exceptions, 'getSoftSkipped').callsFake(() => {
return softSkipped;
});
const mjsunit = new corpus.Corpus('test_data', 'mjsunit_softskipped');
const cases = mjsunit.getRandomTestcasePaths(count);
assert.deepEqual(paths, cases);
}
describe('Loading corpus', () => {
afterEach(() => {
sandbox.restore();
});
it('keeps all tests with no soft-skipped tests', () => {
sandbox.stub(Math, 'random').callsFake(() => 0.9);
testSoftSkipped(
3,
[],
['mjsunit_softskipped/permitted.js',
'mjsunit_softskipped/object-literal.js',
'mjsunit_softskipped/regress/binaryen-123.js']);
});
it('choose one test with no soft-skipped tests', () => {
sandbox.stub(Math, 'random').callsFake(() => 0.9);
testSoftSkipped(
1,
[],
['mjsunit_softskipped/permitted.js']);
});
it('keeps soft-skipped tests', () => {
sandbox.stub(Math, 'random').callsFake(() => 0.9);
testSoftSkipped(
1,
[/^binaryen.*\.js/, 'object-literal.js'],
['mjsunit_softskipped/permitted.js']);
});
it('keeps no generated soft-skipped tests', () => {
sandbox.stub(Math, 'random').callsFake(() => 0.9);
const softSkipped = [
// Correctly listed full relative path of test case.
'mjsunit_softskipped/regress/binaryen-123.js',
// Only basename doesn't match.
'object-literal.js',
// Only pieces of the path don't match.
'mjsunit_softskipped',
];
sandbox.stub(exceptions, 'getGeneratedSoftSkipped').callsFake(
() => { return new Set(softSkipped); });
testSoftSkipped(
2,
// None soft-skipped for basenames and regexps.
[],
// Only binaryen-123.js gets filtered out.
['mjsunit_softskipped/object-literal.js',
'mjsunit_softskipped/permitted.js']);
});
it('keeps soft-skipped tests by chance', () => {
sandbox.stub(Math, 'random').callsFake(() => 0);
testSoftSkipped(
3,
[/^binaryen.*\.js/, 'object-literal.js'],
['mjsunit_softskipped/object-literal.js',
'mjsunit_softskipped/regress/binaryen-123.js',
'mjsunit_softskipped/permitted.js']);
});
it('caches relative paths', () => {
sandbox.stub(Math, 'random').callsFake(() => 0);
sandbox.stub(exceptions, 'getSoftSkipped').callsFake(
() => { return ['object-literal.js']; });
const generatedSoftSkipped = [
'mjsunit_softskipped/regress/binaryen-123.js',
];
sandbox.stub(exceptions, 'getGeneratedSoftSkipped').callsFake(
() => { return new Set(generatedSoftSkipped); });
const mjsunit = new corpus.Corpus('test_data' , 'mjsunit_softskipped');
assert.deepEqual(
['mjsunit_softskipped/object-literal.js',
'mjsunit_softskipped/regress/binaryen-123.js'],
mjsunit.softSkippedFiles);
assert.deepEqual(
['mjsunit_softskipped/permitted.js'],
mjsunit.permittedFiles);
assert.deepEqual(
['mjsunit_softskipped/permitted.js',
'mjsunit_softskipped/object-literal.js',
'mjsunit_softskipped/regress/binaryen-123.js'],
Array.from(mjsunit.relFiles()));
});
});
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Tests for differential fuzzing.
*/
'use strict';
const assert = require('assert');
const program = require('commander');
const sinon = require('sinon');
const helpers = require('./helpers.js');
const scriptMutator = require('../script_mutator.js');
const sourceHelpers = require('../source_helpers.js');
const random = require('../random.js');
const { DifferentialFuzzMutator, DifferentialFuzzSuppressions } = require(
'../mutators/differential_fuzz_mutator.js');
const { DifferentialScriptMutator } = require(
'../differential_script_mutator.js');
const sandbox = sinon.createSandbox();
function testMutators(settings, mutatorClass, inputFile, expectedFile) {
const source = helpers.loadTestData('differential_fuzz/' + inputFile);
const mutator = new mutatorClass(settings);
mutator.mutate(source);
const mutated = sourceHelpers.generateCode(source);
helpers.assertExpectedResult(
'differential_fuzz/' + expectedFile, mutated);
}
describe('Differential fuzzing', () => {
beforeEach(() => {
// Zero settings for all mutators.
this.settings = scriptMutator.defaultSettings();
for (const key of Object.keys(this.settings)) {
this.settings[key] = 0.0;
}
// By default, deterministically use all mutations of differential
// fuzzing.
this.settings['DIFF_FUZZ_EXTRA_PRINT'] = 1.0;
this.settings['DIFF_FUZZ_TRACK_CAUGHT'] = 1.0;
// Fake fuzzer being called with --input_dir flag.
this.oldInputDir = program.input_dir;
program.input_dir = helpers.BASE_DIR;
});
afterEach(() => {
sandbox.restore();
program.input_dir = this.oldInputDir;
});
it('applies suppressions', () => {
// This selects the first random variable when replacing .arguments.
sandbox.stub(random, 'single').callsFake(a => a[0]);
testMutators(
this.settings,
DifferentialFuzzSuppressions,
'suppressions.js',
'suppressions_expected.js');
});
it('adds extra printing', () => {
testMutators(
this.settings,
DifferentialFuzzMutator,
'mutations.js',
'mutations_expected.js');
});
it('does no extra printing', () => {
this.settings['DIFF_FUZZ_EXTRA_PRINT'] = 0.0;
testMutators(
this.settings,
DifferentialFuzzMutator,
'exceptions.js',
'exceptions_expected.js');
});
it('runs end to end', () => {
// Don't choose any zeroed settings or IGNORE_DEFAULT_PROB in try-catch
// mutator. Choose using original flags with >= 2%.
const chooseOrigFlagsProb = 0.2;
sandbox.stub(random, 'choose').callsFake((p) => p >= chooseOrigFlagsProb);
// Fake build directory from which two json configurations for flags are
// loaded.
const env = {
APP_DIR: 'test_data/differential_fuzz',
GENERATE: process.env.GENERATE,
};
sandbox.stub(process, 'env').value(env);
// Fake loading resources and instead load one fixed fake file for each.
sandbox.stub(sourceHelpers, 'loadResource').callsFake(() => {
return helpers.loadTestData('differential_fuzz/fake_resource.js');
});
// Load input files.
const files = [
'differential_fuzz/input1.js',
'differential_fuzz/input2.js',
];
const sources = files.map(helpers.loadTestData);
// Apply top-level fuzzing, with all probabilistic configs switched off.
this.settings['DIFF_FUZZ_EXTRA_PRINT'] = 0.0;
this.settings['DIFF_FUZZ_TRACK_CAUGHT'] = 0.0;
const mutator = new DifferentialScriptMutator(
this.settings, helpers.DB_DIR);
const mutated = mutator.mutateMultiple(sources);
helpers.assertExpectedResult(
'differential_fuzz/combined_expected.js', mutated.code);
// Flags for v8_foozzie.py are calculated from v8_fuzz_experiments.json and
// v8_fuzz_flags.json in test_data/differential_fuzz.
const expectedFlags = [
'--first-config=ignition',
'--second-config=ignition_turbo',
'--second-d8=d8',
'--second-config-extra-flags=--foo1',
'--second-config-extra-flags=--foo2',
'--first-config-extra-flags=--flag1',
'--second-config-extra-flags=--flag1',
'--first-config-extra-flags=--flag2',
'--second-config-extra-flags=--flag2',
'--first-config-extra-flags=--flag3',
'--second-config-extra-flags=--flag3',
'--first-config-extra-flags=--flag4',
'--second-config-extra-flags=--flag4'
];
assert.deepEqual(expectedFlags, mutated.flags);
});
});
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Tests for the differential-fuzzing library files.
*/
'use strict';
const assert = require('assert');
const fs = require('fs');
const path = require('path');
const libPath = path.resolve(
path.join(__dirname, '..', 'resources', 'differential_fuzz_library.js'));
const code = fs.readFileSync(libPath, 'utf-8');
// We wire the print function to write to this result variable.
const resultDummy = 'let result; const print = text => { result = text; };';
// The prettyPrinted function from mjsunit is reused in the library.
const prettyPrint = 'let prettyPrinted = value => value;';
const hookedUpCode = resultDummy + prettyPrint + code;
// Runs the library, adds test code and verifies the result.
function testLibrary(testCode, expected) {
// The code isn't structured as a module. The test code is expected to
// evaluate to a result which we store in actual.
const actual = eval(hookedUpCode + testCode);
assert.deepEqual(expected, actual);
}
describe('Differential fuzzing library', () => {
it('prints objects', () => {
testLibrary(
'__prettyPrint([0, 1, 2, 3]); result;',
'[0, 1, 2, 3]');
testLibrary(
'__prettyPrint({0: 1, 2: 3}); result;',
'Object{0: 1, 2: 3}');
testLibrary(
'const o = {}; o.k = 42;__prettyPrint(o); result;',
'Object{k: 42}');
});
it('cuts off deep nesting', () => {
// We print only until a nesting depth of 4.
testLibrary(
'__prettyPrint({0: [1, 2, [3, {4: []}]]}); result;',
'Object{0: [1, 2, [3, Object{4: ...}]]}');
});
it('cuts off long strings', () => {
const long = new Array(66).join('a');
const head = new Array(55).join('a');
const tail = new Array(10).join('a');
testLibrary(
`__prettyPrint("${long}"); result;`,
`${head}[...]${tail}`);
// If the string gets longer, the cut-off version is still the same.
const veryLong = new Array(100).join('a');
testLibrary(
`__prettyPrint("${veryLong}"); result;`,
`${head}[...]${tail}`);
});
it('tracks hash difference', () => {
// Test that we track a hash value for each string we print.
const long = new Array(66).join('a');
testLibrary(
`__prettyPrint("${long}"); __hash;`,
2097980794);
// Test that the hash value differs, also when the cut-off result doesn't.
const veryLong = new Array(100).join('a');
testLibrary(
`__prettyPrint("${veryLong}"); __hash;`,
-428472866);
// Test that repeated calls update the hash.
testLibrary(
`__prettyPrint("${long}");__prettyPrint("${long}"); __hash;`,
-909224493);
});
it('limits extra printing', () => {
// Test that after exceeding the limit for calling extra printing, there
// is no new string printed (in the test case no new result added).
testLibrary(
'for (let i = 0; i < 20; i++) __prettyPrintExtra(i); result;',
'19');
testLibrary(
'for (let i = 0; i < 101; i++) __prettyPrintExtra(i); result;',
'99');
testLibrary(
'for (let i = 0; i < 102; i++) __prettyPrintExtra(i); result;',
'99');
});
it('tracks hash after limit', () => {
// Test that after exceeding the limit for calling extra printing, the
// hash is still updated.
testLibrary(
'for (let i = 0; i < 20; i++) __prettyPrintExtra(i); __hash;',
-945753644);
testLibrary(
'for (let i = 0; i < 101; i++) __prettyPrintExtra(i); __hash;',
1907055979);
testLibrary(
'for (let i = 0; i < 102; i++) __prettyPrintExtra(i); __hash;',
-590842070);
});
});
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Test normalization.
*/
'use strict';
const sinon = require('sinon');
const helpers = require('./helpers.js');
const sourceHelpers = require('../source_helpers.js');
const { ScriptMutator } = require('../script_mutator.js');
const sandbox = sinon.createSandbox();
function testLoad(testPath, expectedPath) {
const mutator = new ScriptMutator({}, helpers.DB_DIR);
const source = helpers.loadTestData(testPath);
const dependencies = mutator.resolveInputDependencies([source]);
const code = sourceHelpers.generateCode(source, dependencies);
helpers.assertExpectedResult(expectedPath, code);
}
describe('V8 dependencies', () => {
it('test', () => {
testLoad(
'mjsunit/test_load.js',
'mjsunit/test_load_expected.js');
});
it('does not loop indefinitely', () => {
testLoad(
'mjsunit/test_load_self.js',
'mjsunit/test_load_self_expected.js');
});
});
describe('Chakra dependencies', () => {
it('test', () => {
testLoad(
'chakra/load.js',
'chakra/load_expected.js');
});
});
describe('JSTest dependencies', () => {
afterEach(() => {
sandbox.restore();
});
it('test', () => {
const fakeStubs = sourceHelpers.loadSource(
helpers.BASE_DIR, 'JSTests/fake_stub.js');
sandbox.stub(sourceHelpers, 'loadResource').callsFake(() => fakeStubs);
testLoad('JSTests/load.js', 'JSTests/load_expected.js');
});
});
describe('SpiderMonkey dependencies', () => {
it('test', () => {
testLoad(
'spidermonkey/test/load.js',
'spidermonkey/test/load_expected.js');
});
});
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Tests for mutating arrays
*/
'use strict';
const sinon = require('sinon');
const babylon = require('@babel/parser');
const common = require('../mutators/common.js');
const helpers = require('./helpers.js');
const scriptMutator = require('../script_mutator.js');
const sourceHelpers = require('../source_helpers.js');
const {ArrayMutator} = require('../mutators/array_mutator.js');
const sandbox = sinon.createSandbox();
describe('Mutate arrays', () => {
afterEach(() => {
sandbox.restore();
});
it('performs all mutations', () => {
// Make random operations deterministic.
sandbox.stub(common, 'randomValue').callsFake(
() => babylon.parseExpression('""'));
helpers.deterministicRandom(sandbox);
const source = helpers.loadTestData('mutate_arrays.js');
const settings = scriptMutator.defaultSettings();
settings['MUTATE_ARRAYS'] = 1.0;
const mutator = new ArrayMutator(settings);
mutator.mutate(source);
const mutated = sourceHelpers.generateCode(source);
helpers.assertExpectedResult(
'mutate_arrays_expected.js', mutated);
});
});
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Tests for mutating expressions
*/
'use strict';
const assert = require('assert');
const babelTypes = require('@babel/types');
const sinon = require('sinon');
const common = require('../mutators/common.js');
const expressionMutator = require('../mutators/expression_mutator.js');
const helpers = require('./helpers.js');
const scriptMutator = require('../script_mutator.js');
const sourceHelpers = require('../source_helpers.js');
const random = require('../random.js');
const sandbox = sinon.createSandbox();
function testCloneSiblings(expected_file) {
const source = helpers.loadTestData('mutate_expressions.js');
const settings = scriptMutator.defaultSettings();
settings['MUTATE_EXPRESSIONS'] = 1.0;
const mutator = new expressionMutator.ExpressionMutator(settings);
mutator.mutate(source);
const mutated = sourceHelpers.generateCode(source);
helpers.assertExpectedResult(expected_file, mutated);
}
describe('Mutate expressions', () => {
beforeEach(() => {
// Select the previous sibling.
sandbox.stub(random, 'randInt').callsFake((a, b) => b);
// This chooses cloning siblings.
sandbox.stub(random, 'random').callsFake(() => 0.8);
});
afterEach(() => {
sandbox.restore();
});
it('clones previous to current', () => {
// Keep the order of [previous, current], select previous.
sandbox.stub(random, 'shuffle').callsFake(a => a);
// Insert after. Keep returning true for the MUTATE_EXPRESSIONS check.
sandbox.stub(random, 'choose').callsFake(a => a === 1);
testCloneSiblings('mutate_expressions_previous_expected.js');
});
it('clones current to previous', () => {
// Switch the order of [previous, current], select current.
sandbox.stub(random, 'shuffle').callsFake(a => [a[1], a[0]]);
// Insert before.
sandbox.stub(random, 'choose').callsFake(() => true);
testCloneSiblings('mutate_expressions_current_expected.js');
});
});
describe('Cloning', () => {
// Ensure that the source location we add are not cloned.
it('is not copying added state', () => {
const source = helpers.loadTestData('mutate_expressions.js');
common.setSourceLoc(source, 5, 10);
const noopNode = source.ast.program.body[0];
assert.equal(0.5, common.getSourceLoc(noopNode));
const cloned = babelTypes.cloneDeep(noopNode);
assert.equal(undefined, common.getSourceLoc(cloned));
});
});
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Tests for mutating funciton calls.
*/
'use strict';
const sinon = require('sinon');
const helpers = require('./helpers.js');
const random = require('../random.js');
const scriptMutator = require('../script_mutator.js');
const sourceHelpers = require('../source_helpers.js');
const functionCallMutator = require('../mutators/function_call_mutator.js');
const sandbox = sinon.createSandbox();
function loadAndMutate(input_file) {
const source = helpers.loadTestData(input_file);
const settings = scriptMutator.defaultSettings();
settings['engine'] = 'V8';
settings['MUTATE_FUNCTION_CALLS'] = 1.0;
const mutator = new functionCallMutator.FunctionCallMutator(settings);
mutator.mutate(source);
return source;
}
describe('Mutate functions', () => {
afterEach(() => {
sandbox.restore();
});
it('is robust without available functions', () => {
// This chooses replacing fuctions.
sandbox.stub(random, 'random').callsFake(() => { return 0.4; });
// We just ensure here that mutating this file doesn't throw.
loadAndMutate('mutate_function_call.js');
});
it('optimizes functions in V8', () => {
// This omits function replacement and chooses V8 optimizations.
sandbox.stub(random, 'random').callsFake(() => { return 0.6; });
const source = loadAndMutate('mutate_function_call.js');
const mutated = sourceHelpers.generateCode(source);
helpers.assertExpectedResult(
'mutate_function_call_expected.js', mutated);
});
it('deoptimizes functions in V8', () => {
// This chooses V8 deoptimization.
sandbox.stub(random, 'random').callsFake(() => { return 0.8; });
const source = loadAndMutate('mutate_function_call.js');
const mutated = sourceHelpers.generateCode(source);
helpers.assertExpectedResult(
'mutate_function_call_deopt_expected.js', mutated);
});
});
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Tests for mutating variables
*/
'use strict';
const babelTypes = require('@babel/types');
const sinon = require('sinon');
const common = require('../mutators/common.js');
const helpers = require('./helpers.js');
const scriptMutator = require('../script_mutator.js');
const sourceHelpers = require('../source_helpers.js');
const numberMutator = require('../mutators/number_mutator.js');
const random = require('../random.js');
const sandbox = sinon.createSandbox();
describe('Mutate numbers', () => {
beforeEach(() => {
sandbox.stub(common, 'nearbyRandomNumber').callsFake(
() => { return babelTypes.numericLiteral(-3) });
sandbox.stub(common, 'randomInterestingNumber').callsFake(
() => { return babelTypes.numericLiteral(-4) });
sandbox.stub(random, 'randInt').callsFake(() => { return -5 });
// Interesting cases from number mutator.
const interestingProbs = [0.009, 0.05, 0.5];
sandbox.stub(random, 'random').callsFake(
helpers.cycleProbabilitiesFun(interestingProbs));
});
afterEach(() => {
sandbox.restore();
});
it('test', () => {
const source = helpers.loadTestData('mutate_numbers.js');
const settings = scriptMutator.defaultSettings();
settings['MUTATE_NUMBERS'] = 1.0;
const mutator = new numberMutator.NumberMutator(settings);
mutator.mutate(source);
const mutated = sourceHelpers.generateCode(source);
helpers.assertExpectedResult(
'mutate_numbers_expected.js', mutated);
});
});
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Tests for mutating object expressions
*/
'use strict';
const sinon = require('sinon');
const babylon = require('@babel/parser');
const common = require('../mutators/common.js');
const helpers = require('./helpers.js');
const scriptMutator = require('../script_mutator.js');
const sourceHelpers = require('../source_helpers.js');
const {ObjectMutator} = require('../mutators/object_mutator.js');
const sandbox = sinon.createSandbox();
describe('Mutate objects', () => {
afterEach(() => {
sandbox.restore();
});
it('performs all mutations', () => {
// Make random operations deterministic.
sandbox.stub(common, 'randomValue').callsFake(
() => babylon.parseExpression('""'));
helpers.deterministicRandom(sandbox);
const source = helpers.loadTestData('mutate_objects.js');
const settings = scriptMutator.defaultSettings();
settings['MUTATE_OBJECTS'] = 1.0;
const mutator = new ObjectMutator(settings);
mutator.mutate(source);
const mutated = sourceHelpers.generateCode(source);
helpers.assertExpectedResult(
'mutate_objects_expected.js', mutated);
});
});
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Test variable-or-object mutator.
*/
'use strict';
const babylon = require('@babel/parser');
const sinon = require('sinon');
const common = require('../mutators/common.js');
const helpers = require('./helpers.js');
const variableOrObject = require('../mutators/variable_or_object_mutation.js');
const random = require('../random.js');
const sourceHelpers = require('../source_helpers.js');
const sandbox = sinon.createSandbox();
function testMutations(testPath, expectedPath) {
const source = helpers.loadTestData(testPath);
const mutator = new variableOrObject.VariableOrObjectMutator(
{ ADD_VAR_OR_OBJ_MUTATIONS: 1.0 });
mutator.mutate(source);
const mutated = sourceHelpers.generateCode(source);
helpers.assertExpectedResult(expectedPath, mutated);
}
describe('Variable or object mutator', () => {
beforeEach(() => {
// Make before/after insertion deterministic. This also chooses
// random objects.
sandbox.stub(random, 'choose').callsFake(() => { return true; });
// This stubs out the random seed.
sandbox.stub(random, 'randInt').callsFake(() => { return 123; });
// Random value is itself dependent on too much randomization.
sandbox.stub(common, 'randomValue').callsFake(
() => { return babylon.parseExpression('0'); });
});
afterEach(() => {
sandbox.restore();
});
it('test', () => {
let index = 0;
// Test different cases of _randomVariableOrObjectMutations in
// variable_or_object_mutation.js.
const choices = [
0.2, // Trigger recursive case.
0.3, // Recursion 1: Delete.
0.4, // Recursion 2: Property access.
0.5, // Random assignment.
// 0.6 case for randomFunction omitted as it has too much randomization.
0.7, // Variable assignment.
0.8, // Object.defineProperty.
0.9, // Object.defineProperty recursive.
0.3, // Recursion 1: Delete.
0.4, // Recursion 2: Property access.
];
sandbox.stub(random, 'random').callsFake(
() => { return choices[index++]; });
testMutations(
'mutate_var_or_obj.js',
'mutate_var_or_obj_expected.js');
});
});
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Tests for mutating variables
*/
'use strict';
const babelTypes = require('@babel/types');
const sinon = require('sinon');
const common = require('../mutators/common.js');
const helpers = require('./helpers.js');
const scriptMutator = require('../script_mutator.js');
const sourceHelpers = require('../source_helpers.js');
const variableMutator = require('../mutators/variable_mutator.js');
const sandbox = sinon.createSandbox();
describe('Mutate variables', () => {
beforeEach(() => {
sandbox.stub(
common, 'randomVariable').callsFake(
() => { return babelTypes.identifier('REPLACED') });
});
afterEach(() => {
sandbox.restore();
});
it('test', () => {
const source = helpers.loadTestData('mutate_variables.js');
const settings = scriptMutator.defaultSettings();
settings['MUTATE_VARIABLES'] = 1.0;
const mutator = new variableMutator.VariableMutator(settings);
mutator.mutate(source);
const mutated = sourceHelpers.generateCode(source);
helpers.assertExpectedResult(
'mutate_variables_expected.js', mutated);
});
});
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Test normalization.
*/
'use strict';
const helpers = require('./helpers.js');
const normalizer = require('../mutators/normalizer.js');
const sourceHelpers = require('../source_helpers.js');
describe('Normalize', () => {
it('test basic', () => {
const source = helpers.loadTestData('normalize.js');
const mutator = new normalizer.IdentifierNormalizer();
mutator.mutate(source);
const normalized_0 = sourceHelpers.generateCode(source);
helpers.assertExpectedResult(
'normalize_expected_0.js', normalized_0);
mutator.mutate(source);
const normalized_1 = sourceHelpers.generateCode(source);
helpers.assertExpectedResult(
'normalize_expected_1.js', normalized_1);
});
it('test simple_test.js', () => {
const source = helpers.loadTestData('simple_test.js');
const mutator = new normalizer.IdentifierNormalizer();
mutator.mutate(source);
const normalized = sourceHelpers.generateCode(source);
helpers.assertExpectedResult(
'simple_test_expected.js', normalized);
});
});
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Test random utilities.
*/
'use strict';
const assert = require('assert');
const sinon = require('sinon');
const { twoBucketSample } = require('../random.js');
const sandbox = sinon.createSandbox();
describe('Two-bucket choosing', () => {
afterEach(() => {
sandbox.restore();
});
it('with one empty', () => {
sandbox.stub(Math, 'random').callsFake(() => 0.5);
assert.deepEqual([1, 2], twoBucketSample([0, 1, 2], [], 1, 2));
assert.deepEqual([1, 2], twoBucketSample([], [0, 1, 2], 1, 2));
assert.deepEqual([0], twoBucketSample([0], [], 1, 1));
assert.deepEqual([0], twoBucketSample([], [0], 1, 1));
});
it('chooses with 0.3', () => {
sandbox.stub(Math, 'random').callsFake(() => 0.3);
assert.deepEqual([1, 2], twoBucketSample([0, 1, 2], [3, 4, 5], 1, 2));
// Higher factor.
assert.deepEqual([3, 5], twoBucketSample([0, 1, 2], [3, 4, 5], 4, 2));
});
it('chooses with 0.7', () => {
sandbox.stub(Math, 'random').callsFake(() => 0.7);
assert.deepEqual([4, 3], twoBucketSample([0, 1, 2], [3, 4, 5], 1, 2));
});
it('chooses with 0.5', () => {
sandbox.stub(Math, 'random').callsFake(() => 0.5);
assert.deepEqual([3], twoBucketSample([0, 1], [2, 3, 4, 5], 1, 1));
assert.deepEqual([3], twoBucketSample([0, 1, 2, 3], [4, 5], 1, 1));
// Higher factor.
assert.deepEqual([4], twoBucketSample([0, 1, 2, 3], [4, 5], 2, 1));
});
});
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Regression tests.
*/
'use strict';
const assert = require('assert');
const { execSync } = require("child_process");
const fs = require('fs');
const sinon = require('sinon');
const tempfile = require('tempfile');
const tempy = require('tempy');
const exceptions = require('../exceptions.js');
const helpers = require('./helpers.js');
const scriptMutator = require('../script_mutator.js');
const sandbox = sinon.createSandbox();
const SYNTAX_ERROR_RE = /.*SyntaxError.*/
function createFuzzTest(fake_db, settings, inputFiles) {
const sources = inputFiles.map(input => helpers.loadTestData(input));
const mutator = new scriptMutator.ScriptMutator(settings, fake_db);
const result = mutator.mutateMultiple(sources);
const output_file = tempfile('.js');
fs.writeFileSync(output_file, result.code);
return output_file;
}
function execFile(jsFile) {
execSync("node " + jsFile, {stdio: ['pipe']});
}
function buildDb(inputDir, corpusName, outputDir) {
execSync(
`node build_db.js -i ${inputDir} -o ${outputDir} ${corpusName}`,
{stdio: ['pipe']});
}
function assertFuzzWithDbThrows(dbInputDir, corpusName, settings, regexp) {
const outPath = tempy.directory();
buildDb(dbInputDir, corpusName, outPath);
settings['MUTATE_CROSSOVER_INSERT'] = 1.0;
assert.throws(
() => {
createFuzzTest(
outPath, settings,
['regress/build_db/cross_over_mutator_input.js']);
},
err => {
assert(regexp.test(err));
return true;
},
'unexpected error',
);
}
describe('Regression tests', () => {
beforeEach(() => {
helpers.deterministicRandom(sandbox);
this.settings = {
ADD_VAR_OR_OBJ_MUTATIONS: 0.0,
MUTATE_CROSSOVER_INSERT: 0.0,
MUTATE_EXPRESSIONS: 0.0,
MUTATE_FUNCTION_CALLS: 0.0,
MUTATE_NUMBERS: 0.0,
MUTATE_VARIABLES: 0.0,
engine: 'V8',
testing: true,
}
});
afterEach(() => {
sandbox.restore();
});
it('combine strict and with', () => {
// Test that when a file with "use strict" is used in the inputs,
// the result is only strict if no other file contains anything
// prohibited in strict mode (here a with statement).
// It is assumed that such input files are marked as sloppy in the
// auto generated exceptions.
sandbox.stub(exceptions, 'getGeneratedSloppy').callsFake(
() => { return new Set(['regress/strict/input_with.js']); });
const file = createFuzzTest(
'test_data/regress/strict/db',
this.settings,
['regress/strict/input_strict.js', 'regress/strict/input_with.js']);
execFile(file);
});
it('combine strict and delete', () => {
// As above with unqualified delete.
sandbox.stub(exceptions, 'getGeneratedSloppy').callsFake(
() => { return new Set(['regress/strict/input_delete.js']); });
const file = createFuzzTest(
'test_data/regress/strict/db',
this.settings,
['regress/strict/input_strict.js', 'regress/strict/input_delete.js']);
execFile(file);
});
it('mutates negative value', () => {
// This tests that the combination of number, function call and expression
// mutator does't produce an update expression.
// Previously the 1 in -1 was replaced with another negative number leading
// to e.g. -/*comment/*-2. Then cloning the expression removed the
// comment and produced --2 in the end.
this.settings['MUTATE_NUMBERS'] = 1.0;
this.settings['MUTATE_FUNCTION_CALLS'] = 1.0;
this.settings['MUTATE_EXPRESSIONS'] = 1.0;
const file = createFuzzTest(
'test_data/regress/numbers/db',
this.settings,
['regress/numbers/input_negative.js']);
execFile(file);
});
it('mutates indices', () => {
// Test that indices are not replaced with a negative number causing a
// syntax error (e.g. {-1: ""}).
this.settings['MUTATE_NUMBERS'] = 1.0;
const file = createFuzzTest(
'test_data/regress/numbers/db',
this.settings,
['regress/numbers/input_indices.js']);
execFile(file);
});
it('create call expression', () => {
// TODO(machenbach): Build_db extracts a function expression without
// parentheses, re-parsing this later fails in cross-over mutator.
assertFuzzWithDbThrows(
'test_data/regress/build_db',
'destructuring',
this.settings,
SYNTAX_ERROR_RE);
});
it('create assignment expression', () => {
// TODO(machenbach): Build_db extracts some assignment expressions with a
// spurious dependency. This leads to an "unknown substitution" error
// when applying the template.
assertFuzzWithDbThrows(
'test_data/regress/build_db',
'this',
this.settings,
/.*Unknown substitution.*/);
});
});
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Test normalization.
*/
'use strict';
const sinon = require('sinon');
const common = require('../mutators/common.js');
const helpers = require('./helpers.js');
const random = require('../random.js');
const sourceHelpers = require('../source_helpers.js');
const tryCatch = require('../mutators/try_catch.js');
const sandbox = sinon.createSandbox();
function loadSource() {
return helpers.loadTestData('try_catch.js');
}
function testTryCatch(source, expected) {
const mutator = new tryCatch.AddTryCatchMutator();
mutator.mutate(source);
const mutated = sourceHelpers.generateCode(source);
helpers.assertExpectedResult(expected, mutated);
}
describe('Try catch', () => {
afterEach(() => {
sandbox.restore();
});
// Wrap on exit, hence wrap everything nested.
it('wraps all', () => {
sandbox.stub(random, 'choose').callsFake(() => { return false; });
sandbox.stub(random, 'random').callsFake(() => { return 0.7; });
testTryCatch(loadSource(), 'try_catch_expected.js');
});
// Wrap on enter and skip.
it('wraps toplevel', () => {
sandbox.stub(random, 'choose').callsFake(() => { return false; });
sandbox.stub(random, 'random').callsFake(() => { return 0.04; });
const source = loadSource();
// Fake source fraction 0.1 (i.e. the second of 10 files).
// Probability for toplevel try-catch is 0.05.
common.setSourceLoc(source, 1, 10);
testTryCatch(source, 'try_catch_toplevel_expected.js');
});
// Choose the rare case of skipping try-catch.
it('wraps nothing', () => {
sandbox.stub(random, 'choose').callsFake(() => { return false; });
sandbox.stub(random, 'random').callsFake(() => { return 0.01; });
const source = loadSource();
// Fake source fraction 0.1 (i.e. the second of 10 files).
// Probability for skipping is 0.02.
common.setSourceLoc(source, 1, 10);
testTryCatch(source, 'try_catch_nothing_expected.js');
});
// Choose to alter the target probability to 0.9 resulting in skipping
// all try-catch.
it('wraps nothing with high target probability', () => {
sandbox.stub(random, 'choose').callsFake(() => { return true; });
sandbox.stub(random, 'uniform').callsFake(() => { return 0.9; });
sandbox.stub(random, 'random').callsFake(() => { return 0.8; });
const source = loadSource();
// Fake source fraction 0.9 (i.e. the last of 10 files).
// Probability for skipping is 0.81 (0.9 * 0.9).
common.setSourceLoc(source, 9, 10);
testTryCatch(source, 'try_catch_alternate_expected.js');
});
});
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
print("Fake stub");
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
print("JSTest");
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original: JSTests/fake_stub.js
print("Fake stub");
// Original: JSTests/load.js
print("JSTest");
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
let __v_0 = 0;
let __v_1 = 0;
console.log(__v_0, __v_1, __f_0, __f_1);
function __f_0() {
let __v_2 = 0;
console.log(__v_0, __v_1, __v_2, __f_0, __f_1);
}
let __v_3 = 0;
console.log(__v_0, __v_1, __v_3, __f_0, __f_1);
function __f_1(__v_7) {
let __v_4 = 0;
console.log(__v_0, __v_1, __v_3, __v_4, __v_7, __f_0, __f_1);
{
let __v_5 = 0;
var __v_6 = 0;
console.log(__v_0, __v_1, __v_3, __v_4, __v_5, __v_6, __v_7, __f_0, __f_1, __f_2);
function __f_2 () {};
console.log(__v_0, __v_1, __v_3, __v_4, __v_5, __v_6, __v_7, __f_0, __f_1, __f_2);
}
// TODO(machenbach): __f_2 is missing as available identifier.
console.log(__v_0, __v_1, __v_3, __v_4, __v_6, __v_7, __f_0, __f_1, __f_2);
}
console.log(__v_0, __v_1, __v_3, __f_0, __f_1);
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
[
{
"variables": [
{
"type": "Identifier",
"name": "__v_0"
},
{
"type": "Identifier",
"name": "__v_1"
}
],
"functions": [
{
"type": "Identifier",
"name": "__f_0"
},
{
"type": "Identifier",
"name": "__f_1"
}
]
},
{
"variables": [
{
"type": "Identifier",
"name": "__v_2"
},
{
"type": "Identifier",
"name": "__v_0"
},
{
"type": "Identifier",
"name": "__v_1"
}
],
"functions": [
{
"type": "Identifier",
"name": "__f_0"
},
{
"type": "Identifier",
"name": "__f_1"
}
]
},
{
"variables": [
{
"type": "Identifier",
"name": "__v_0"
},
{
"type": "Identifier",
"name": "__v_1"
},
{
"type": "Identifier",
"name": "__v_3"
}
],
"functions": [
{
"type": "Identifier",
"name": "__f_0"
},
{
"type": "Identifier",
"name": "__f_1"
}
]
},
{
"variables": [
{
"type": "Identifier",
"name": "__v_7"
},
{
"type": "Identifier",
"name": "__v_4"
},
{
"type": "Identifier",
"name": "__v_0"
},
{
"type": "Identifier",
"name": "__v_1"
},
{
"type": "Identifier",
"name": "__v_3"
}
],
"functions": [
{
"type": "Identifier",
"name": "__f_0"
},
{
"type": "Identifier",
"name": "__f_1"
}
]
},
{
"variables": [
{
"type": "Identifier",
"name": "__v_5"
},
{
"type": "Identifier",
"name": "__v_7"
},
{
"type": "Identifier",
"name": "__v_4"
},
{
"type": "Identifier",
"name": "__v_6"
},
{
"type": "Identifier",
"name": "__v_0"
},
{
"type": "Identifier",
"name": "__v_1"
},
{
"type": "Identifier",
"name": "__v_3"
}
],
"functions": [
{
"type": "Identifier",
"name": "__f_2"
},
{
"type": "Identifier",
"name": "__f_0"
},
{
"type": "Identifier",
"name": "__f_1"
}
]
},
{
"variables": [
{
"type": "Identifier",
"name": "__v_5"
},
{
"type": "Identifier",
"name": "__v_7"
},
{
"type": "Identifier",
"name": "__v_4"
},
{
"type": "Identifier",
"name": "__v_6"
},
{
"type": "Identifier",
"name": "__v_0"
},
{
"type": "Identifier",
"name": "__v_1"
},
{
"type": "Identifier",
"name": "__v_3"
}
],
"functions": [
{
"type": "Identifier",
"name": "__f_2"
},
{
"type": "Identifier",
"name": "__f_0"
},
{
"type": "Identifier",
"name": "__f_1"
}
]
},
{
"variables": [
{
"type": "Identifier",
"name": "__v_7"
},
{
"type": "Identifier",
"name": "__v_4"
},
{
"type": "Identifier",
"name": "__v_6"
},
{
"type": "Identifier",
"name": "__v_0"
},
{
"type": "Identifier",
"name": "__v_1"
},
{
"type": "Identifier",
"name": "__v_3"
}
],
"functions": [
{
"type": "Identifier",
"name": "__f_0"
},
{
"type": "Identifier",
"name": "__f_1"
}
]
},
{
"variables": [
{
"type": "Identifier",
"name": "__v_0"
},
{
"type": "Identifier",
"name": "__v_1"
},
{
"type": "Identifier",
"name": "__v_3"
}
],
"functions": [
{
"type": "Identifier",
"name": "__f_0"
},
{
"type": "Identifier",
"name": "__f_1"
}
]
}
]
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
WScript.LoadScriptFile("..\\load2.js", "self");
console.log('load3');
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
if (this.WScript && this.WScript.LoadScriptFile) {
WScript.LoadScriptFile("load1.js");
}
console.log('load.js');
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Test case insensitivity.
WScript.LoadScriptFile("DIR\\LoAd3.js");
console.log('load1.js');
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
console.log('load2.js');
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original: chakra/load2.js
console.log('load2.js');
// Original: chakra/dir/load3.js
console.log('load3');
// Original: chakra/load1.js
console.log('load1.js');
// Original: chakra/load.js
if (this.WScript && this.WScript.LoadScriptFile) {}
console.log('load.js');
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original: differential_fuzz/fake_resource.js
print("I'm a resource.");
// Original: differential_fuzz/fake_resource.js
print("I'm a resource.");
// Original: differential_fuzz/fake_resource.js
print("I'm a resource.");
// Original: differential_fuzz/fake_resource.js
print("I'm a resource.");
// Original: differential_fuzz/fake_resource.js
print("I'm a resource.");
/* DifferentialFuzzMutator: Print variables and exceptions from section */
try {
print("Hash: " + __hash);
print("Caught: " + __caught);
} catch (e) {}
print("v8-foozzie source: differential_fuzz/input1.js");
// Original: differential_fuzz/input1.js
try {
var __v_0 = 0;
} catch (e) {}
try {
/* DifferentialFuzzMutator: Pretty printing */
__prettyPrintExtra(__v_0);
} catch (e) {}
/* DifferentialFuzzMutator: Print variables and exceptions from section */
try {
print("Hash: " + __hash);
print("Caught: " + __caught);
__prettyPrint(__v_0);
} catch (e) {}
print("v8-foozzie source: differential_fuzz/input2.js");
// Original: differential_fuzz/input2.js
let __v_1 = 1;
/* DifferentialFuzzMutator: Print variables and exceptions from section */
try {
print("Hash: " + __hash);
print("Caught: " + __caught);
__prettyPrint(__v_0);
__prettyPrint(__v_1);
} catch (e) {}
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
try {
let __v_0 = boom;
} catch (e) {}
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original: differential_fuzz/exceptions.js
try {
let __v_0 = boom;
} catch (e) {
__caught++;
}
/* DifferentialFuzzMutator: Print variables and exceptions from section */
try {
print("Hash: " + __hash);
print("Caught: " + __caught);
} catch (e) {}
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file represents anything loaded from the resources directory.
print("I'm a resource.");
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --flag1 --flag2
// Flags: --flag3
var a = 0;
print(a);
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --flag4
let b = 1;
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Print after declaration.
var __v_0 = [1, 2, 3];
// Don't print after declarations or assigments in loops.
for (let __v_1 = 0; __v_1 < 3; __v_1 += 1) {
// Print after multiple declarations.
let __v_2, __v_3 = 0;
// Print after assigning to member.
__v_0.foo = undefined;
// Replace with deep printing.
print(0);
// Print exception.
try {
// Print after assignment.
__v_1 += 1;
} catch(e) {}
}
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original: differential_fuzz/mutations.js
var __v_0 = [1, 2, 3];
/* DifferentialFuzzMutator: Extra variable printing */
__prettyPrintExtra(__v_0);
for (let __v_1 = 0; __v_1 < 3; __v_1 += 1) {
let __v_2,
__v_3 = 0;
/* DifferentialFuzzMutator: Extra variable printing */
__prettyPrintExtra(__v_2);
__prettyPrintExtra(__v_3);
__v_0.foo = undefined;
/* DifferentialFuzzMutator: Extra variable printing */
__prettyPrintExtra(__v_0);
/* DifferentialFuzzMutator: Pretty printing */
__prettyPrintExtra(0);
try {
__v_1 += 1;
/* DifferentialFuzzMutator: Extra variable printing */
__prettyPrintExtra(__v_1);
} catch (e) {
__prettyPrintExtra(e);
}
}
/* DifferentialFuzzMutator: Print variables and exceptions from section */
try {
print("Hash: " + __hash);
print("Caught: " + __caught);
__prettyPrint(__v_0);
} catch (e) {}
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// These statements might come from a CrashTest.
print("v8-foozzie source: some/file/name");
print('v8-foozzie source: some/file/name');
function foo(__v_0) {
// This is an unsupported language feature.
return 1 in foo.arguments;
}
// This leads to precision differences in optimized code.
print(192 ** -0.5);
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original: differential_fuzz/suppressions.js
print(
/* DifferentialFuzzSuppressions: Replaced magic string */
"v***************e: some/file/name");
print(
/* DifferentialFuzzSuppressions: Replaced magic string */
"v***************e: some/file/name");
function foo(__v_0) {
return 1 in
/* DifferentialFuzzSuppressions: Replaced .arguments */
__v_0;
}
print(
/* DifferentialFuzzSuppressions: Replaced ** */
192 + -0.5);
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var fakeMjsunit = 'fake';
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var testLoad = 'test_load';
load('test_data/mjsunit/test_load_1.js');
load('test_load_0.js');
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
load('test_data/mjsunit/test_load_1.js');
load('test_load_2.js');
load('test_load_3.js');
var testLoad0 = 'test_load_0';
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
load('test_load_2.js');
var testLoad1 = 'test_load_1';
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var testLoad2 = 'test_load_2';
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var testLoad3 = 'test_load_3';
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original: mjsunit/mjsunit.js
var fakeMjsunit = 'fake';
// Original: mjsunit/test_load_2.js
var testLoad2 = 'test_load_2';
// Original: mjsunit/test_load_1.js
var testLoad1 = 'test_load_1';
// Original: mjsunit/test_load_3.js
var testLoad3 = 'test_load_3';
// Original: mjsunit/test_load_0.js
var testLoad0 = 'test_load_0';
// Original: mjsunit/test_load.js
var testLoad = 'test_load';
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
load("test_load_self.js");
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original: mjsunit/mjsunit.js
var fakeMjsunit = 'fake';
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Fake file
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Fake file
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Fake file
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
[];
[];
[];
[];
[];
[];
[];
[];
[];
[];
[1, 2, 3];
[1, 2, 3];
[1, 2, 3];
[1, 2, 3];
[1, 2, 3];
[1, 2, 3];
[1, 2, 3];
[1, 2, 3];
[1, 2, 3];
[1, 2, 3];
[1, 2, 3];
[1, 2, 3];
[1, 2, 3];
[1, 2, 3];
[1, 2, 3];
[1, 2, 3];
[1, 2, 3];
[1, 2, 3];
[1, 2, 3];
[1, 2, 3];
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original: mutate_arrays.js
/* ArrayMutator: Remove elements */
/* ArrayMutator: Insert a hole */
[];
[];
/* ArrayMutator: Shuffle array */
[];
/* ArrayMutator: Insert a random value */
[""];
/* ArrayMutator: Insert a random value (replaced) */
[""];
/* ArrayMutator: Insert a hole (replaced) */
[,];
[];
/* ArrayMutator: Insert a hole (replaced) */
[,];
/* ArrayMutator: Remove elements */
[];
/* ArrayMutator: Remove elements */
[];
/* ArrayMutator: Duplicate an element */
[1, 1, 2, 3];
/* ArrayMutator: Insert a random value (replaced) */
[1, "", 3];
/* ArrayMutator: Remove elements */
[];
/* ArrayMutator: Duplicate an element */
[1, 2, 3, 2];
/* ArrayMutator: Remove elements */
[3];
/* ArrayMutator: Duplicate an element (replaced) */
[1, 2, 3];
/* ArrayMutator: Insert a hole (replaced) */
/* ArrayMutator: Duplicate an element (replaced) */
[1, 2,,];
/* ArrayMutator: Remove elements */
[1, 2];
/* ArrayMutator: Insert a hole (replaced) */
/* ArrayMutator: Duplicate an element */
[1, 1, 2,,];
/* ArrayMutator: Shuffle array */
[2, 1, 3];
/* ArrayMutator: Remove elements */
/* ArrayMutator: Remove elements */
[3];
/* ArrayMutator: Duplicate an element (replaced) */
[1, 2, 1];
/* ArrayMutator: Duplicate an element (replaced) */
/* ArrayMutator: Duplicate an element (replaced) */
[1, 2, 2];
/* ArrayMutator: Insert a random value */
[1, 2, 3, ""];
/* ArrayMutator: Duplicate an element */
[1, 2, 3, 3];
/* ArrayMutator: Remove elements */
/* ArrayMutator: Duplicate an element */
[1, 2];
/* ArrayMutator: Insert a random value (replaced) */
/* ArrayMutator: Duplicate an element (replaced) */
[1, 2, ""];
/* ArrayMutator: Insert a random value (replaced) */
/* ArrayMutator: Insert a random value (replaced) */
["", 2, 3];
/* ArrayMutator: Duplicate an element */
/* ArrayMutator: Remove elements */
[1, 1, 3];
/* ArrayMutator: Remove elements */
[1, 2];
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
1;
let foo = undefined;
2;
3;
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original: mutate_expressions.js
1;
/* ExpressionMutator: Cloned sibling */
2;
let foo = undefined;
/* ExpressionMutator: Cloned sibling */
3;
2;
3;
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original: mutate_expressions.js
1;
let foo = undefined;
2;
3;
/* ExpressionMutator: Cloned sibling */
2;
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
__f_0(1);
a = __f_0(1);
foo(1, __f_0());
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var _temp, _temp2;
// Original: mutate_function_call.js
/* FunctionCallMutator: Deoptimizing __f_0 */
__f_0(1);
%DeoptimizeFunction(__f_0);
a = (
/* FunctionCallMutator: Deoptimizing __f_0 */
_temp = __f_0(1), %DeoptimizeFunction(__f_0), _temp);
foo(1, (
/* FunctionCallMutator: Deoptimizing __f_0 */
_temp2 = __f_0(), %DeoptimizeFunction(__f_0), _temp2));
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
%PrepareFunctionForOptimization(__f_0);
__f_0(1);
__f_0(1);
%OptimizeFunctionOnNextCall(__f_0);
// Original: mutate_function_call.js
/* FunctionCallMutator: Optimizing __f_0 */
__f_0(1);
a = (
/* FunctionCallMutator: Optimizing __f_0 */
%PrepareFunctionForOptimization(__f_0), __f_0(1), __f_0(1), %OptimizeFunctionOnNextCall(__f_0), __f_0(1));
foo(1, (
/* FunctionCallMutator: Optimizing __f_0 */
%PrepareFunctionForOptimization(__f_0), __f_0(), __f_0(), %OptimizeFunctionOnNextCall(__f_0), __f_0()));
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';
function foo() {
let a = 123;
for (let i = 0; i < 456; i++) {
a += 1;
}
let b = 0;
while (b < 10) {
b += 2;
}
a += 1;
}
var a = {0: "", 1: "", get 1(){}};
var b = -10;
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';
// Original: mutate_numbers.js
function foo() {
let a =
/* NumberMutator: Replaced 123 with -5 */
-5;
for (let i = 0; i < 456; i++) {
a +=
/* NumberMutator: Replaced 1 with -4 */
-4;
}
let b =
/* NumberMutator: Replaced 0 with -3 */
-3;
while (b < 10) {
b += 2;
}
a +=
/* NumberMutator: Replaced 1 with -5 */
-5;
}
var a = {
/* NumberMutator: Replaced 0 with 4 */
4: "",
/* NumberMutator: Replaced 1 with 3 */
3: "",
get
/* NumberMutator: Replaced 1 with 5 */
5() {}
};
var b =
/* NumberMutator: Replaced -10 with -4 */
-4;
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Empty objects are not manipulated.
a = {};
a = {};
a = {};
a = {};
a = {};
a = {};
// Small objects only get some mutations.
a = {1: 0};
a = {a: 0};
a = {"s": 0};
a = {1: 0};
a = {a: 0};
a = {"s": 0};
// Larger objects get all mutations.
a = {1: "a", 2: "b", 3: "c"};
a = {1: "a", 2: "b", 3: "c"};
a = {1: "a", 2: "b", 3: "c"};
a = {1: "a", 2: "b", 3: "c"};
a = {1: "a", 2: "b", 3: "c"};
a = {1: "a", 2: "b", 3: "c"};
a = {1: "a", 2: "b", 3: "c"};
a = {1: "a", 2: "b", 3: "c"};
a = {1: "a", 2: "b", 3: "c"};
a = {1: "a", 2: "b", 3: "c"};
// Getters and setters are ignored.
a = {get bar() { return 0 }, 1: 0, set bar(t) {}};
a = {get bar() { return 0 }, 1: 0, set bar(t) {}};
a = {get bar() { return 0 }, 1: 0, set bar(t) {}};
// Recursive.
a = {1: {4: "4", 5: "5", 6: "6"}, 2: {3: "3"}};
a = {1: {4: "4", 5: "5", 6: "6"}, 2: {3: "3"}};
a = {1: {4: "4", 5: "5", 6: "6"}, 2: {3: "3"}};
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original: mutate_objects.js
a = {};
a = {};
a = {};
a = {};
a = {};
a = {};
a =
/* ObjectMutator: Insert a random value */
{
1: ""
};
a = {
a: 0
};
a =
/* ObjectMutator: Insert a random value */
{
"s": ""
};
a =
/* ObjectMutator: Stringify a property key */
{
"1": 0
};
a =
/* ObjectMutator: Remove a property */
{};
a = {
"s": 0
};
a =
/* ObjectMutator: Swap properties */
{
1: "c",
2: "b",
3: "a"
};
a =
/* ObjectMutator: Remove a property */
{
2: "b",
3: "c"
};
a =
/* ObjectMutator: Insert a random value */
{
1: "a",
2: "",
3: "c"
};
a =
/* ObjectMutator: Swap properties */
{
1: "b",
2: "a",
3: "c"
};
a =
/* ObjectMutator: Swap properties */
{
1: "c",
2: "b",
3: "a"
};
a =
/* ObjectMutator: Stringify a property key */
{
"1": "a",
2: "b",
3: "c"
};
a =
/* ObjectMutator: Remove a property */
{
2: "b",
3: "c"
};
a =
/* ObjectMutator: Swap properties */
{
1: "b",
2: "a",
3: "c"
};
a =
/* ObjectMutator: Duplicate a property value */
{
1: "c",
2: "b",
3: "c"
};
a =
/* ObjectMutator: Duplicate a property value */
{
1: "a",
2: "b",
3: "b"
};
a = {
get bar() {
return 0;
},
1: 0,
set bar(t) {}
};
a =
/* ObjectMutator: Insert a random value */
{
get bar() {
return 0;
},
1: "",
set bar(t) {}
};
a =
/* ObjectMutator: Remove a property */
{
get bar() {
return 0;
},
set bar(t) {}
};
a =
/* ObjectMutator: Duplicate a property value */
{
1:
/* ObjectMutator: Remove a property */
{},
2:
/* ObjectMutator: Stringify a property key */
{
"3": "3"
}
};
a =
/* ObjectMutator: Duplicate a property value */
{
1:
/* ObjectMutator: Swap properties */
{
4: "4",
5: "6",
6: "5"
},
2:
/* ObjectMutator: Remove a property */
{
5: "5",
6: "6"
}
};
a =
/* ObjectMutator: Duplicate a property value */
{
1:
/* ObjectMutator: Swap properties */
{
4: "6",
5: "5",
6: "4"
},
2:
/* ObjectMutator: Stringify a property key */
{
4: "4",
5: "5",
"6": "6"
}
};
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
let __v_0 = {};
Math.pow(1, 2);
Math.pow(1, 2);
Math.pow(1, 2);
Math.pow(1, 2);
Math.pow(1, 2);
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original: mutate_var_or_obj.js
let __v_0 = {};
/* VariableOrObjectMutator: Random mutation */
delete __getRandomObject(123)[__getRandomProperty(__getRandomObject(123), 123)], __callGC();
__getRandomObject(123)[__getRandomProperty(__getRandomObject(123), 123)], __callGC();
Math.pow(1, 2);
/* VariableOrObjectMutator: Random mutation */
__getRandomObject(123)[__getRandomProperty(__getRandomObject(123), 123)] = 0, __callGC();
Math.pow(1, 2);
/* VariableOrObjectMutator: Random mutation */
__v_0 = __getRandomObject(123), __callGC();
Math.pow(1, 2);
/* VariableOrObjectMutator: Random mutation */
if (__getRandomObject(123) != null && typeof __getRandomObject(123) == "object") Object.defineProperty(__getRandomObject(123), __getRandomProperty(__getRandomObject(123), 123), {
value: 0
});
Math.pow(1, 2);
/* VariableOrObjectMutator: Random mutation */
if (__getRandomObject(123) != null && typeof __getRandomObject(123) == "object") Object.defineProperty(__getRandomObject(123), __getRandomProperty(__getRandomObject(123), 123), {
get: function () {
delete __getRandomObject(123)[__getRandomProperty(__getRandomObject(123), 123)], __callGC();
return 0;
},
set: function (value) {
__getRandomObject(123)[__getRandomProperty(__getRandomObject(123), 123)], __callGC();
}
});
Math.pow(1, 2);
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function __f_0(__v_10, __v_11) {
let __v_4 = 4;
let __v_5 = 5;
let __v_6 = 6;
let __v_7 = 7;
console.log(__v_4);
console.log(__v_5);
console.log(__v_6);
console.log(__v_7);
for (let __v_9 = 0; __v_9 < 10; __v_9++) {
console.log(__v_4);
}
let __v_8 = 0;
while (__v_8 < 10) {
__v_8++;
}
}
let __v_0 = 1;
let __v_1 = 2;
let __v_2 = 3;
let __v_3 = 4;
console.log(__v_0);
console.log(__v_1);
console.log(__v_2);
console.log(__v_3);
__f_0();
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original: mutate_variables.js
function __f_0(__v_10, __v_11) {
let __v_4 = 4;
let __v_5 = 5;
let __v_6 = 6;
let __v_7 = 7;
console.log(
/* VariableMutator: Replaced __v_4 with REPLACED */
REPLACED);
console.log(
/* VariableMutator: Replaced __v_5 with REPLACED */
REPLACED);
console.log(
/* VariableMutator: Replaced __v_6 with REPLACED */
REPLACED);
console.log(
/* VariableMutator: Replaced __v_7 with REPLACED */
REPLACED);
for (let __v_9 = 0; __v_9 < 10; __v_9++) {
console.log(
/* VariableMutator: Replaced __v_4 with REPLACED */
REPLACED);
}
let __v_8 = 0;
while (__v_8 < 10) {
__v_8++;
}
}
let __v_0 = 1;
let __v_1 = 2;
let __v_2 = 3;
let __v_3 = 4;
console.log(
/* VariableMutator: Replaced __v_0 with REPLACED */
REPLACED);
console.log(
/* VariableMutator: Replaced __v_1 with REPLACED */
REPLACED);
console.log(
/* VariableMutator: Replaced __v_2 with REPLACED */
REPLACED);
console.log(
/* VariableMutator: Replaced __v_3 with REPLACED */
REPLACED);
__f_0();
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';
class Class {
constructor() {
this.abc = 789;
this.selfRef = Class;
}
}
function foo() {
let a = 123;
console.log(a);
}
foo();
let a = 456;
console.log(a);
let b = new Class();
console.log(b.abc);
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';
// Original: normalize.js
class __c_0 {
constructor() {
this.abc = 789;
this.selfRef = __c_0;
}
}
function __f_0() {
let __v_2 = 123;
console.log(__v_2);
}
__f_0();
let __v_0 = 456;
console.log(__v_0);
let __v_1 = new __c_0();
console.log(__v_1.abc);
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';
// Original: normalize.js
class __c_1 {
constructor() {
this.abc = 789;
this.selfRef = __c_1;
}
}
function __f_1() {
let __v_5 = 123;
console.log(__v_5);
}
__f_1();
let __v_3 = 456;
console.log(__v_3);
let __v_4 = new __c_1();
console.log(__v_4.abc);
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
class __C {
foo() {
let __v_0 = 2;
let __v_1 = 2;
Math.pow(__v_0, __v_1);
}
}
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
let x = 2;
let y = 2;
Math.pow(x, y);
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
let x, y;
(function([ x = y = 1 ]) {}([]));
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function C() {
this.c = "c";
}
var c = new C();
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
let a = {
0: "",
1: "",
2: "",
3: "",
4: "",
};
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
foo(-1);
foo(-1);
foo(-1);
foo(-1);
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
print("Won't see this.");
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
loadRelativeToScript('PatternAsserts.js');
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var x;
delete x;
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
"use strict";
print("Hello");
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
with (Math) {
print(PI);
}
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Test comment.
// Flags: --gc-interval = 1
var abs = Math.abs;
var v1 = 5, v2; var v3;
if (v1) {
var v4 = 3;
for (var v5 = 0; v5 < 4; v5++) {
console.log('Value of v5: ' +
v5);
}
}
let v6 = 3;
const v7 = 5 + \u{0076}6;
v1 = {['p' + v6]: ''};
v1 = `test\`
value is ${ v6 + v7 }` + '\0\400\377'
v1 = (v8=2, {v9 = eval('v8')},) => { return v8 + v9 + 4; };
v1 = () => 4 + 5;
v1 = v10 => { return v10 + 4; }
v1 = async v11 => v11 + 4;
v12 = [0, 1, 2,];
v13 = [3, 4, 5];
v14 = [...v12, ...v13];
v15 = ([v16, v17] = [1, 2], {v31: v18} = {v31: v16 + v17}) => v16 + v17 + v18;
v16 = 170%16/16 + 2**32;
v17 = 0o1 + 0O1 + 01 + 0b011 + 0B011;
for (var v18 of [1, 2, 3]) console.log(v18);
function f1(v19,) {}
f1();
%OptimizeFunctionOnNextCall(f1);
function f2() {
var v20 = 5;
return v20 + 6;
}
(async function f3() {
var v21 = await 1;
console.log(v21);
})();
function* f4(v22=2, ...v23) {
yield* [1, 2, 3];
}
function* f5() { (yield 3) + (yield); }
{ function f6() { } }
v23 = { v6, [v6]: 3, f7() { }, get f8 () { }, *f9 () { }, async f10 () { } }
var [v24, v25, ...v26] = [10, 20], {v27, v28} = {v27: 10, v28: 20};
class c1 {
f11(v29) {
return v29 + 1;
}
static* f12() {
yield 'a' + super.f12();
}
constructor(v30) {
console.log(new.target.name);
}
[0]() { }
}
class c2 extends c1 { }
do ; while(0);
v16 **= 4;
for (const v32 = 1; v32 < 1;);
for (let v33 = 1; v33 < 5; v33++);
for (var v34 = 1; v34 < 5; v34++);
for (const {v35 = 0, v36 = 3} = {}; v36 < 1;);
for (let {v37 = 0, v38 = 3} = {}; v38 != 0; v38--);
for (var {v39 = 0, v40 = 3} = {}; v40 != 0; v40--);
for (const v41 of [1, 2, 3]);
for (let v42 of [1, 2, 3]);
for (var v43 of [1, 2, 3]);
for (const v44 in [1, 2, 3]);
for (let v45 in [1, 2, 3]);
for (var v46 in [1, 2, 3]);
label: function f13() { }
var a = function b() {
b();
};
var c = class C {
constructor() {
console.log(C.name);
}
};
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original: simple_test.js
var __v_0 = Math.abs;
var __v_1 = 5,
__v_2;
var __v_3;
if (__v_1) {
var __v_4 = 3;
for (var __v_5 = 0; __v_5 < 4; __v_5++) {
console.log('Value of v5: ' + __v_5);
}
}
let __v_6 = 3;
const __v_7 = 5 + __v_6;
__v_1 = {
['p' + __v_6]: ''
};
__v_1 = `test\`
value is ${__v_6 + __v_7}` + '\0\400\377';
__v_1 = (__v_21 = 2, {
v9: __v_22 = eval('v8')
}) => {
return __v_21 + __v_22 + 4;
};
__v_1 = () => 4 + 5;
__v_1 = __v_23 => {
return __v_23 + 4;
};
__v_1 = async __v_24 => __v_24 + 4;
__v_25 = [0, 1, 2];
__v_26 = [3, 4, 5];
__v_27 = [...__v_25, ...__v_26];
__v_28 = ([__v_29, __v_30] = [1, 2], {
v31: __v_31
} = {
v31: __v_29 + __v_30
}) => __v_29 + __v_30 + __v_31;
__v_42 = 170 % 16 / 16 + 2 ** 32;
__v_33 = 0o1 + 0O1 + 01 + 0b011 + 0B011;
for (var __v_8 of [1, 2, 3]) console.log(__v_8);
function __f_0(__v_34) {}
__f_0();
%OptimizeFunctionOnNextCall(__f_0);
function __f_1() {
var __v_35 = 5;
return __v_35 + 6;
}
(async function __f_5() {
var __v_36 = await 1;
console.log(__v_36);
})();
function* __f_2(__v_37 = 2, ...__v_38) {
yield* [1, 2, 3];
}
function* __f_3() {
(yield 3) + (yield);
}
{
function __f_6() {}
}
__v_39 = {
v6: __v_6,
[__v_6]: 3,
f7() {},
get f8() {},
*f9() {},
async f10() {}
};
var [__v_9, __v_10, ...__v_11] = [10, 20],
{
v27: __v_12,
v28: __v_13
} = {
v27: 10,
v28: 20
};
class __c_0 {
f11(__v_40) {
return __v_40 + 1;
}
static *f12() {
yield 'a' + super.f12();
}
constructor(__v_41) {
console.log(new.target.name);
}
[0]() {}
}
class __c_1 extends __c_0 {}
do ; while (0);
__v_42 **= 4;
for (const __v_43 = 1; __v_43 < 1;);
for (let __v_44 = 1; __v_44 < 5; __v_44++);
for (var __v_14 = 1; __v_14 < 5; __v_14++);
for (const {
v35: __v_45 = 0,
v36: __v_46 = 3
} = {}; __v_46 < 1;);
for (let {
v37: __v_47 = 0,
v38: __v_48 = 3
} = {}; __v_48 != 0; __v_48--);
for (var {
v39: __v_15 = 0,
v40: __v_16 = 3
} = {}; __v_16 != 0; __v_16--);
for (const __v_49 of [1, 2, 3]);
for (let __v_50 of [1, 2, 3]);
for (var __v_17 of [1, 2, 3]);
for (const __v_51 in [1, 2, 3]);
for (let __v_52 in [1, 2, 3]);
for (var __v_18 in [1, 2, 3]);
label: function __f_4() {}
var __v_19 = function __f_7() {
__f_7();
};
var __v_20 = class __c_2 {
constructor() {
console.log(__c_2.name);
}
};
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
console.log('load1.js');
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
console.log('/shell.js');
if (!ok)
throw new Error(`Assertion failed: ${f} did not throw as expected`);
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
load('load1.js');
loadRelativeToScript('load2.js');
console.log('load.js');
if (!ok)
throw new Error(`Assertion failed: Some text`);
print("Assertion failed: Some text");
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
console.log('load2.js');
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original: spidermonkey/shell.js
console.log('/shell.js');
if (!ok) throw new Error(`A****tion failed: ${f} did not throw as expected`);
// Original: spidermonkey/test/shell.js
console.log('/test/shell.js');
// Original: spidermonkey/load1.js
console.log('load1.js');
// Original: spidermonkey/test/load2.js
console.log('load2.js');
// Original: spidermonkey/test/load.js
console.log('load.js');
if (!ok) throw new Error(`A****tion failed: Some text`);
print("A****tion failed: Some text");
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
console.log('/test/shell.js');
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function blah() {
try {
var a = 10;
console.log(a);
} catch (e) {}
label: for (var i = 0; i < 100; i++) {
var b = 0;
while (b < 10) {
console.log(b);
b += 2;
continue label;
}
}
}
blah();
blah();
(function () {1;1;})();
if (true) {
2;2;
} else {
3;3;
}
let a = 0;
switch (a) {
case 1: 1;
}
with (Math) {
cos(PI);
}
let module = new WebAssembly.Module(builder.toBuffer());
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/* AddTryCatchMutator: Target skip probability 0.9 and toplevel probability 0.9 */
// Original: try_catch.js
function blah() {
try {
var a = 10;
console.log(a);
} catch (e) {}
label: for (var i = 0; i < 100; i++) {
var b = 0;
while (b < 10) {
console.log(b);
b += 2;
continue label;
}
}
}
blah();
blah();
(function () {
1;
1;
})();
if (true) {
2;
2;
} else {
3;
3;
}
let a = 0;
switch (a) {
case 1:
1;
}
with (Math) {
cos(PI);
}
let module = new WebAssembly.Module(builder.toBuffer());
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original: try_catch.js
function blah() {
try {
try {
var a = 10;
} catch (e) {}
try {
console.log(a);
} catch (e) {}
} catch (e) {}
try {
label: for (var i = 0; i < 100; i++) {
try {
var b = 0;
} catch (e) {}
try {
while (b < 10) {
try {
console.log(b);
} catch (e) {}
try {
b += 2;
} catch (e) {}
continue label;
}
} catch (e) {}
}
} catch (e) {}
}
try {
blah();
} catch (e) {}
try {
blah();
} catch (e) {}
try {
(function () {
try {
1;
} catch (e) {}
try {
1;
} catch (e) {}
})();
} catch (e) {}
try {
if (true) {
try {
2;
} catch (e) {}
try {
2;
} catch (e) {}
} else {
try {
3;
} catch (e) {}
try {
3;
} catch (e) {}
}
} catch (e) {}
let a = 0;
try {
switch (a) {
case 1:
try {
1;
} catch (e) {}
}
} catch (e) {}
try {
with (Math) {
try {
cos(PI);
} catch (e) {}
}
} catch (e) {}
let module = function () {
try {
return new WebAssembly.Module(builder.toBuffer());
} catch (e) {}
}();
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original: try_catch.js
function blah() {
try {
var a = 10;
console.log(a);
} catch (e) {}
label: for (var i = 0; i < 100; i++) {
var b = 0;
while (b < 10) {
console.log(b);
b += 2;
continue label;
}
}
}
blah();
blah();
(function () {
1;
1;
})();
if (true) {
2;
2;
} else {
3;
3;
}
let a = 0;
switch (a) {
case 1:
1;
}
with (Math) {
cos(PI);
}
let module = new WebAssembly.Module(builder.toBuffer());
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original: try_catch.js
function blah() {
try {
try {
var a = 10;
} catch (e) {}
try {
console.log(a);
} catch (e) {}
} catch (e) {}
try {
label: for (var i = 0; i < 100; i++) {
var b = 0;
while (b < 10) {
console.log(b);
b += 2;
continue label;
}
}
} catch (e) {}
}
try {
blah();
} catch (e) {}
try {
blah();
} catch (e) {}
try {
(function () {
1;
1;
})();
} catch (e) {}
try {
if (true) {
2;
2;
} else {
3;
3;
}
} catch (e) {}
let a = 0;
try {
switch (a) {
case 1:
1;
}
} catch (e) {}
try {
with (Math) {
cos(PI);
}
} catch (e) {}
let module = function () {
try {
return new WebAssembly.Module(builder.toBuffer());
} catch (e) {}
}();
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Test all expressions in DB.
*/
const fs = require('fs');
const fsPath = require('path');
const program = require('commander');
const sinon = require('sinon');
const crossOverMutator = require('./mutators/crossover_mutator.js');
const db = require('./db.js');
const random = require('./random.js');
const sourceHelpers = require('./source_helpers.js');
const sandbox = sinon.createSandbox();
function main() {
program
.version('0.0.1')
.option('-i, --input_dir <path>', 'DB directory.')
.parse(process.argv);
if (!program.input_dir) {
console.log('Need to specify DB dir.');
return;
}
const loader = new sourceHelpers.V8SourceLoader();
const mutateDb = new db.MutateDb(program.input_dir);
const mutator = new crossOverMutator.CrossOverMutator(
{ MUTATE_CROSSOVER_INSERT: 1.0, testing: true }, mutateDb);
let nPass = 0;
let nFail = 0;
// Iterate over all statements saved in the DB.
for (const statementPath of mutateDb.index.all) {
const expression = JSON.parse(fs.readFileSync(
fsPath.join(program.input_dir, statementPath)), 'utf-8');
// Stub out choosing random variables in cross-over mutator.
sandbox.stub(random, 'single').callsFake((a) => { return a[0]; });
// Ensure we are selecting the statement of the current iteration.
sandbox.stub(mutateDb, 'getRandomStatement').callsFake(
() => { return expression; });
// Use a source that will try to insert one statement, allowing
// super.
const source = loader.load(
__dirname,
'test_data/regress/build_db/cross_over_mutator_class_input.js');
try {
mutator.mutate(source);
nPass++;
} catch (e) {
console.log('******************************************************')
console.log(expression);
console.log(e.message);
nFail++;
}
sandbox.restore();
}
console.log(`Result: ${nPass} passed, ${nFail} failed.`)
}
main();
#!/usr/bin/env python
# Copyright 2020 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
Helper script to execute a single-processed fuzzing session.
Creates fuzz tests in workdir/output/dir-<dir number>/fuzz-XXX.js.
Expects the <dir number> as single parameter.
"""
import os
import subprocess
import sys
import time
BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
APP_DIR = os.path.join(BASE_PATH, 'workdir', 'app_dir')
FUZZ_EXE = os.path.join(BASE_PATH, 'workdir', 'fuzzer', 'ochang_js_fuzzer')
INPUT_DIR = os.path.join(BASE_PATH, 'workdir', 'input')
TEST_CASES = os.path.join(BASE_PATH, 'workdir', 'output')
COUNT = 64
FUZZ = ('FUZZ_MODE=foozzie APP_NAME=d8 APP_DIR=%s %s -o %%s -n %s -i %s > %%s'
% (APP_DIR, FUZZ_EXE, COUNT, INPUT_DIR))
assert(len(sys.argv) > 1)
dir_number = int(sys.argv[1])
assert(dir_number >= 0)
path = os.path.join(TEST_CASES, 'dir-%d' % dir_number)
assert not os.path.exists(path), 'Need fresh workdir for fuzzing'
os.makedirs(path)
start = time.time()
subprocess.check_call(
FUZZ % (path, os.path.join(path, 'out.log')), shell=True)
duration = int(time.time() - start)
with open(os.path.join(path, 'duration.log'), 'w') as f:
f.write(str(duration))
#!/usr/bin/env python
# Copyright 2020 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
Helper script to forge a command line for clusterfuzz' minimizer for
each failure found during a fuzzing session with workbench.py.
Expects the path to the minimizer tools, e.g. something like:
path/to/src/python/bot/minimizer
"""
import json
from multiprocessing import cpu_count
import os
import sys
PROCESSES = cpu_count()
BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
OUT_PATH = os.path.join(BASE_PATH, 'out.js')
FAILURES_JSON_PATH = os.path.join(
BASE_PATH, 'workdir', 'output', 'failures.json')
assert(len(sys.argv) > 1, 'Need to specify minimizer path.')
minimizer_path = sys.argv[1]
def getcmd(command):
parts = command.split(' ')
prefix = command[:-(len(parts[-1]) + 1)]
return ('python %s/run.py -t%d -mjs -o %s "%s" %s' %
(minimizer_path, PROCESSES, OUT_PATH, prefix, parts[-1]))
with open(FAILURES_JSON_PATH) as f:
failures = json.load(f)
for failure in failures:
print('*********************************************************')
print('Source: ' + failure['source'])
print('Command:')
print(failure['command'])
print('Minimize:')
print(getcmd(failure['command']))
#!/usr/bin/env python
# Copyright 2020 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
Helper script to execute fuzz tests in a single process.
Expects fuzz tests in workdir/output/dir-<dir number>/fuzz-XXX.js.
Expects the <dir number> as single parameter.
"""
import json
import os
import random
import re
import subprocess
import sys
BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
FOOZZIE = os.path.join(BASE_PATH, 'workdir', 'app_dir', 'v8_foozzie.py')
TEST_CASES = os.path.join(BASE_PATH, 'workdir', 'output')
# Output pattern from foozzie.py when it finds a failure.
FAILURE_RE = re.compile(
r'# V8 correctness failure.'
r'# V8 correctness configs: (?P<configs>.*).'
r'# V8 correctness sources: (?P<source>.*).'
r'# V8 correctness suppression:.*', re.S)
assert(len(sys.argv) > 1)
dir_number = int(sys.argv[1])
assert(dir_number >= 0)
test_dir = os.path.join(TEST_CASES, 'dir-%d' % dir_number)
assert os.path.exists(test_dir)
def failure_state(command, stdout):
return dict(FAILURE_RE.search(stdout).groupdict(), command=command)
def random_seed():
"""Returns random, non-zero seed."""
seed = 0
while not seed:
seed = random.SystemRandom().randint(-2147483648, 2147483647)
return seed
def run(fuzz_file, flag_file):
"""Executes the differential-fuzzing harness foozzie with one fuzz test."""
with open(flag_file) as f:
flags = f.read().split(' ')
args = [FOOZZIE, '--random-seed=%d' % random_seed()] + flags + [fuzz_file]
cmd = ' '.join(args)
try:
output = subprocess.check_output(cmd, stderr=subprocess.PIPE, shell=True)
return (cmd, output)
except Exception as e:
return (cmd, e.output)
def list_tests():
"""Iterates all fuzz tests and corresponding flags in the given base dir."""
for f in os.listdir(test_dir):
if f.startswith('fuzz'):
n = int(re.match(r'fuzz-(\d+)\.js', f).group(1))
ff = 'flags-%d.js' % n
yield (os.path.join(test_dir, f), os.path.join(test_dir, ff))
# Some counters for the statistics.
count = 0
count_timeout = 0
count_crash = 0
count_failure = 0
failures = []
# Execute all tests in the given directory. Interpret foozzie's output and add
# it to the statistics.
for fuzz_file, flag_file in list_tests():
cmd, output = run(fuzz_file, flag_file)
count += 1
if '# V8 correctness - pass' in output:
continue
if '# V8 correctness - T-I-M-E-O-U-T' in output:
count_timeout += 1
continue
if '# V8 correctness - C-R-A-S-H' in output:
count_crash += 1
continue
count_failure += 1
failures.append(failure_state(cmd, output))
with open(os.path.join(test_dir, 'failures.json'), 'w') as f:
json.dump(failures, f)
stats = {
'total': count,
'timeout': count_timeout,
'crash': count_crash,
'failure': count_failure,
}
with open(os.path.join(test_dir, 'stats.json'), 'w') as f:
json.dump(stats, f)
#!/usr/bin/env python
# Copyright 2020 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
Tool to execute multiprocessed fuzzing and testing sessions.
Expects a single parameter with the number of sessions.
Regularly updates a stats.json and failures.json during executions. E.g.
stay up-to-date with:
cat workdir/output/stats.json | python -m json.tool
"""
# TODO(machenbach): This is currently tailored for differential fuzzing
# with foozzie. It could be generalized, but that'd require duplicating
# clusterfuzz' stack analysis to some degree. E.g. understanding asan
# or DCHECK failures.
from __future__ import print_function
import json
import math
from multiprocessing import Pool, cpu_count
import os
import random
import subprocess
import sys
PROCESSES = cpu_count()
BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEST_CASES = os.path.join(BASE_PATH, 'workdir', 'output')
FUZZ_ONE = os.path.join(BASE_PATH, 'tools', 'fuzz_one.py')
RUN_ONE = os.path.join(BASE_PATH, 'tools', 'run_one.py')
os.chdir(BASE_PATH)
assert not os.path.exists(TEST_CASES)
os.makedirs(TEST_CASES)
# Use ~40000 for 24 hours of fuzzing on a modern work station.
RUNS = 8
if len(sys.argv) > 1:
RUNS = int(sys.argv[1])
def run(n):
"""Multiprocessed function that executes a single fuzz session and
afterwards executes all fuzz tests and collects the statistics.
Args:
n: Subdirectory index of this run.
"""
subprocess.check_call([sys.executable, FUZZ_ONE, str(n)])
subprocess.check_call([sys.executable, RUN_ONE, str(n)])
test_dir = os.path.join(TEST_CASES, 'dir-%d' % n)
with open(os.path.join(test_dir, 'stats.json')) as f:
stats = json.load(f)
with open(os.path.join(test_dir, 'failures.json')) as f:
failures = json.load(f)
return (stats, failures)
class Stats(object):
def __init__(self):
self.total = 0
self.crash = 0
self.timeout = 0
self.failure = 0
self.dupe = 0
self.failures = []
self.known_states = set()
def add(self, stats, failures):
# Aggregate common stats.
self.total += stats['total']
self.crash += stats['crash']
self.timeout += stats['timeout']
# Dedupe failures.
for failure in failures:
if failure['source'] in self.known_states:
self.dupe += 1
continue
self.known_states.add(failure['source'])
self.failure += 1
self.failures.append(failure)
@property
def stats(self):
return {
'total': self.total,
'crash': self.crash,
'failure': self.failure,
'dupe': self.dupe,
'timeout': self.timeout,
}
all_stats = Stats()
count = 0
pool = Pool(processes=PROCESSES)
# Iterate over all runs multiprocessed and merge the statistics and
# failure data of the single runs.
for stats, failures in pool.imap_unordered(run, range(RUNS)):
all_stats.add(stats, failures)
count += 1
if count % max(1, int(RUNS / 20)) == 0:
print('Progress: %d runs (%d%%)' % (count, count * 100 / RUNS))
# Update overall stats.
with open(os.path.join(TEST_CASES, 'stats.json'), 'w') as f:
json.dump(all_stats.stats, f)
with open(os.path.join(TEST_CASES, 'failures.json'), 'w') as f:
json.dump(all_stats.failures, f)
print('Ran %(total)d test cases (%(timeout)d timeouts, '
'%(crash)d crashes, %(failure)d failures, %(dupe)d dupes)'
% all_stats.stats)
for failure in all_stats.failures:
print(failure)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment