= {
+ value: Options[K];
+ source: OptionSource;
+};
+export type OptionsWithSource = { [P in keyof Options]: OptionWithSource };
+
+type OptionWithPrintableSource = {
+ value: Options[K];
+ source: string;
+};
+
+export type OptionsWithPrintableSource = {
+ [P in keyof Options]: OptionWithPrintableSource;
+};
+
+// These options can be set from the Jest fuzz test.
+const allowedFuzzTestOptions = [
+ "dictionaryEntries",
+ "fuzzerOptions",
+ "sync",
+ "timeout",
+] as const;
+export type AllowedFuzzTestOptions = (typeof allowedFuzzTestOptions)[number];
+
+export const defaultCLIOptions: Options = Object.freeze({
coverage: false,
coverageDirectory: "coverage",
coverageReporters: ["json", "text", "lcov", "clover"], // default Jest reporters
+ customHooks: [],
+ dictionaryEntries: [],
disableBugDetectors: [],
+ dryRun: false,
+ excludes: ["node_modules"],
+ expectedErrors: [],
+ fuzzEntryPoint: "fuzz",
+ fuzzerOptions: [],
+ fuzzTarget: "",
+ idSyncFile: "",
+ includes: ["*"],
mode: "fuzzing",
+ sync: false,
+ timeout: 5000, // default Jest timeout
verbose: false,
});
+export const defaultJestOptions: Options = Object.freeze({
+ ...defaultCLIOptions,
+ mode: "regression",
+});
+
export type KeyFormatSource = (key: string) => string;
export const fromCamelCase: KeyFormatSource = (key: string): string => key;
@@ -104,166 +137,335 @@ export const fromSnakeCaseWithPrefix: (prefix: string) => KeyFormatSource = (
};
};
-// Parameters can be passed in via environment variables, command line or
-// configuration file, and subsequently overwrite the default ones and each other.
-// The passed in values have to be set for externally provided parameters, e.g.
-// CLI parameters, before resolving the final options object.
+// Source of an option is considered when merging options.
// Higher index means higher priority.
-export enum ParameterResolverIndex {
- DefaultOptions = 1,
+export enum OptionSource {
+ DefaultCLIOptions,
+ DefaultJestOptions,
+ InternalJestTimeout,
ConfigurationFile,
EnvironmentVariables,
CommandLineArguments,
+ JestFuzzTestOptions,
}
-type ParameterResolver = {
+
+type DefaultSourceInfo = {
name: string;
transformKey: KeyFormatSource;
failOnUnknown: boolean;
- parameters: object;
+ parameters?: Options | object;
};
-type ParameterResolvers = Record;
-const defaultResolvers: ParameterResolvers = {
- [ParameterResolverIndex.DefaultOptions]: {
- name: "Default options",
+const defaultOptions: Record = {
+ [OptionSource.DefaultCLIOptions]: {
+ name: "Default CLI options",
+ transformKey: fromCamelCase,
+ failOnUnknown: true,
+ parameters: defaultCLIOptions,
+ },
+ [OptionSource.DefaultJestOptions]: {
+ name: "Default Jest options",
+ transformKey: fromCamelCase,
+ failOnUnknown: true,
+ parameters: defaultJestOptions,
+ },
+ [OptionSource.InternalJestTimeout]: {
+ name: "Internal Jest timeout",
transformKey: fromCamelCase,
failOnUnknown: true,
- parameters: defaultOptions,
},
- [ParameterResolverIndex.ConfigurationFile]: {
+ [OptionSource.ConfigurationFile]: {
name: "Configuration file",
transformKey: fromCamelCase,
failOnUnknown: true,
- parameters: {},
},
- [ParameterResolverIndex.EnvironmentVariables]: {
+ [OptionSource.EnvironmentVariables]: {
name: "Environment variables",
transformKey: fromSnakeCaseWithPrefix("JAZZER"),
failOnUnknown: false,
parameters: process.env as object,
},
- [ParameterResolverIndex.CommandLineArguments]: {
+ [OptionSource.CommandLineArguments]: {
name: "Command line arguments",
- transformKey: fromSnakeCase,
+ transformKey: fromCamelCase,
failOnUnknown: true,
- parameters: {},
},
-};
+ [OptionSource.JestFuzzTestOptions]: {
+ name: "Jest fuzz test options",
+ transformKey: fromCamelCase,
+ failOnUnknown: true,
+ },
+} as const;
-/**
- * Set the value object of a parameter resolver. Every resolver expects value
- * object parameter names in a specific format, e.g. camel case or snake case,
- * see the resolver definitions for details.
- */
-export function setParameterResolverValue(
- index: ParameterResolverIndex,
- inputs: Partial,
-) {
- // Includes and excludes must be set together.
- if (inputs && inputs.includes && !inputs.excludes) {
- inputs.excludes = [];
- } else if (inputs && inputs.excludes && !inputs.includes) {
- inputs.includes = [];
- }
- defaultResolvers[index].parameters = inputs;
-}
+export class OptionsManager {
+ private readonly _options: OptionsWithSource;
-/**
- * Build a complete `Option` object based on the parameter resolver chain.
- * Add externally passed in values via the `setParameterResolverValue` function,
- * before calling `buildOptions`.
- */
-export function buildOptions(): Options {
- const options = Object.keys(defaultResolvers)
- .sort() // Don't presume an ordered object, this could be implementation specific.
- .reduce((accumulator, currentValue) => {
- const resolver =
- defaultResolvers[parseInt(currentValue) as ParameterResolverIndex];
- return mergeOptions(
- resolver.parameters,
- accumulator,
- resolver.transformKey,
- resolver.failOnUnknown,
+ constructor(obj: OptionSource);
+ constructor(obj: OptionsWithSource);
+ /**
+ * Manages merging of options from different sources.
+ * WARNING: each fuzz test needs a copy (use the `clone()` function) of the OptionsManager, otherwise the fuzz tests will overwrite each other's options.
+ * @param sourceOrOptions - build options given the `OptionSource`; or use provided options as is.
+ */
+ constructor(sourceOrOptions: OptionSource | OptionsWithSource) {
+ if (typeof sourceOrOptions === "number") {
+ const source = sourceOrOptions;
+ const initialOptions = defaultOptions[source].parameters as Options;
+ if (!initialOptions) {
+ throw new Error(
+ `Default options for ${source} do not exist. Consider adding them or use a different source.`,
+ );
+ }
+ this._options = OptionsManager.copyOptions(
+ OptionsManager.attachSource(initialOptions, source),
);
- }, defaultResolvers[ParameterResolverIndex.DefaultOptions].parameters as Options);
+ this.merge(process.env, OptionSource.EnvironmentVariables);
+ } else if (typeof sourceOrOptions === "object") {
+ // only used by clone()
+ this._options = OptionsManager.copyOptions(sourceOrOptions);
+ } else {
+ throw new Error("Invalid argument");
+ }
+ }
- // Set verbose mode environment variable via option or node DEBUG environment variable.
- if (options.verbose || process.env.DEBUG) {
- process.env.JAZZER_DEBUG = "1";
+ /**
+ * Get the value of an option.
+ * @param key
+ */
+ get(key: K): Options[K] {
+ return this._options[key].value;
+ }
+
+ /**
+ * Get raw options without the source information.
+ * @returns a copy of the options without source information
+ */
+ getOptions(): Options {
+ return OptionsManager.detachSource(this._options);
}
- return options;
-}
-function mergeOptions(
- input: unknown,
- defaults: Options,
- transformKey: (key: string) => string,
- errorOnUnknown = true,
-): Options {
- // Deep close the default options to avoid mutation.
- const options: Options = JSON.parse(JSON.stringify(defaults));
- if (!options || !input || typeof input !== "object") {
- return options;
+ getOptionsWithSource(): OptionsWithSource {
+ return this._options;
}
- Object.keys(input as object).forEach((key) => {
- const transformedKey = transformKey(key);
- // Use hasOwnProperty to still support node v14.
- // eslint-disable-next-line no-prototype-builtins
- if (!(options as object).hasOwnProperty(transformedKey)) {
- if (errorOnUnknown) {
- throw new Error(`Unknown Jazzer.js option '${key}'`);
+
+ /**
+ * Merge new options from `input` given the `source` (aka priority). Same `source` options will result in an error---accumulate the options before writing.
+ * `input` gets deep cloned to avoid reference keeping and unintended mutations.
+ * @param input - new options to merge
+ * @param source - priority of all the options in `input`
+ */
+ merge(input: unknown, source: OptionSource) {
+ const transformKey = defaultOptions[source].transformKey;
+ const errorOnUnknown = defaultOptions[source].failOnUnknown;
+
+ let includes: typeof this._options.includes.value | undefined = undefined;
+ let excludes: typeof this._options.excludes.value | undefined = undefined;
+
+ Object.keys(input as object).forEach((k) => {
+ const transformedKey = transformKey(k);
+
+ // Use hasOwnProperty to still support node v14.
+ // eslint-disable-next-line no-prototype-builtins
+ if (!defaultCLIOptions.hasOwnProperty(transformedKey)) {
+ if (errorOnUnknown) {
+ throw new Error(`Unknown Jazzer.js option '${k}'`);
+ }
+ return;
}
- return;
- }
- // No way to dynamically resolve the types here, use (implicit) any for now.
- // @ts-ignore
- let resultValue = input[key];
- // Try to parse strings as JSON values to support setting arrays and
- // objects via environment variables.
- if (typeof resultValue === "string" || resultValue instanceof String) {
- try {
- resultValue = JSON.parse(resultValue.toString());
- } catch (ignore) {
- // Ignore parsing errors and continue with the string value.
+ const key = transformedKey as keyof Options;
+ if (!validateOptionPermissions(key, source, this._options)) {
+ return;
}
- }
- //@ts-ignore
- const keyType = typeof options[transformedKey];
- if (typeof resultValue !== keyType) {
+
+ const keyType = typeof defaultCLIOptions[key];
+
+ // No way to dynamically resolve the types here, use (implicit) any for now.
// @ts-ignore
- throw new Error(
- `Invalid type for Jazzer.js option '${key}', expected type '${keyType}'`,
- );
+ let resultValue = input[k];
+ // Try to parse strings as JSON values to support setting arrays and
+ // objects via environment variables and command line arguments.
+ if (
+ [
+ OptionSource.CommandLineArguments,
+ OptionSource.EnvironmentVariables,
+ ].includes(source) &&
+ keyType !== "string" &&
+ (typeof resultValue === "string" || resultValue instanceof String)
+ ) {
+ try {
+ resultValue = JSON.parse(resultValue.toString());
+ } catch (ignore) {
+ // Ignore parsing errors and continue with the string value.
+ }
+ }
+
+ if (typeof resultValue !== keyType) {
+ throw new Error(
+ `Invalid type for Jazzer.js option '${key}', expected type '${keyType}', got '${typeof resultValue}'`,
+ );
+ }
+ // Deep copy the new value to avoid reference keeping and unintended mutations.
+ resultValue = OptionsManager.copyOptionValue(resultValue);
+ setProperty(this._options, key, { value: resultValue, source: source });
+
+ if (key === "includes") {
+ includes = resultValue;
+ } else if (key === "excludes") {
+ excludes = resultValue;
+ }
+ });
+
+ // Includes and excludes must be set together.
+ if (input && includes && !excludes) {
+ this._options.excludes.value = [];
+ } else if (input && excludes && !includes) {
+ this._options.includes.value = [];
}
- // Deep clone value to avoid reference keeping and unintended mutations.
- // @ts-ignore
- options[transformedKey] = JSON.parse(JSON.stringify(resultValue));
- });
- return options;
-}
-export function buildFuzzerOption(options: Options) {
- if (process.env.JAZZER_DEBUG) {
- console.debug("DEBUG: [core] Jazzer.js initial fuzzer arguments: ");
- console.debug(options);
+ // Set verbose mode environment variable via option or node DEBUG environment variable.
+ // Subsequent changes to the `verbose` option will be ignored.
+ if (this.get("verbose") || process.env.DEBUG) {
+ process.env.JAZZER_DEBUG = "1";
+ }
+ return this;
+ }
+
+ clone(): OptionsManager {
+ return new OptionsManager(this._options);
}
+ static copyOptions(newOptions: OptionsWithSource): OptionsWithSource {
+ const result: OptionsWithSource = Object.create(null);
+ Object.entries(newOptions).forEach(([k]) => {
+ const key = k as keyof Options;
+ const option = newOptions[key];
+ const value = OptionsManager.copyOptionValue(option.value);
+ const source = option.source;
+ setProperty(result, key, {
+ value,
+ source,
+ });
+ });
+ return result;
+ }
+
+ static copyOptionValue(
+ input: T[K],
+ ): T[K] {
+ // simple types
+ if (!input || typeof input !== "object") {
+ return input;
+ }
+
+ if (Array.isArray(input)) {
+ // (Uint8Array | Int8Array)[] - each sub-array gets copied
+ if (
+ input.some(
+ (element) =>
+ element instanceof Uint8Array || element instanceof Int8Array,
+ )
+ ) {
+ return input.map((element) => {
+ if (element instanceof Uint8Array || element instanceof Int8Array) {
+ return element.slice();
+ }
+ return element;
+ }) as T[K];
+ }
+
+ // string[] - the array can be copied directly
+ return input.slice() as T[K];
+ }
+
+ throw new Error("copyOptionValue: unsupported type: " + typeof input);
+ }
+
+ /**
+ * Build options with source information attached.
+ *
+ * @param options
+ * @returns a copy of the options with source information
+ */
+ static attachSource(
+ options: Options,
+ source: OptionSource,
+ ): OptionsWithSource {
+ const result: OptionsWithSource = Object.create(null);
+ Object.entries(options).forEach(([k]) => {
+ const key = k as keyof Options;
+ setProperty(result, key, {
+ value: options[key],
+ source: source,
+ });
+ });
+ return result;
+ }
+
+ /**
+ * Remove source information from options.
+ *
+ * @param options
+ * @returns a copy of the options without source information
+ */
+ static detachSource(options: OptionsWithSource): Options {
+ const result: Options = Object.create(null);
+ Object.entries(options).forEach(([k]) => {
+ const key = k as keyof Options;
+ const value = options[key]?.value;
+ setProperty(result, key, value);
+ });
+ return result;
+ }
+}
+
+function setProperty(obj: T, key: K, value: T[K]) {
+ obj[key] = value;
+}
+
+export function buildFuzzerOption(options: OptionsManager) {
let params: string[] = [];
params = optionDependentParams(options, params);
params = forkedExecutionParams(params);
- params = useDictionaryByParams(params);
+ params = useDictionaryByParams(params, options.get("dictionaryEntries"));
// libFuzzer has to ignore SIGINT and SIGTERM, as it interferes
// with the Node.js signal handling.
params = params.concat("-handle_int=0", "-handle_term=0", "-handle_segv=0");
- if (process.env.JAZZER_DEBUG) {
- console.debug("DEBUG: [core] Jazzer.js actually used fuzzer arguments: ");
- console.debug(params);
- }
+ printOptions(options);
logInfoAboutFuzzerOptions(params);
return params;
}
+export function printOptions(options: OptionsManager, infix = "") {
+ if (process.env.JAZZER_DEBUG) {
+ console.error(
+ util.formatWithOptions(
+ // Print everything in the options object.
+ { maxArrayLength: null, depth: null, colors: false },
+ `DEBUG: [core] Jazzer.js options ${infix}: \n%O`,
+ toOptionsWithPrintableSources(options),
+ ),
+ );
+ }
+}
+
+function toOptionsWithPrintableSources(
+ options: OptionsManager,
+): OptionsWithPrintableSource {
+ const result: OptionsWithPrintableSource = Object.create(null);
+ const opts = options.getOptionsWithSource();
+ Object.entries(opts).forEach(([k]) => {
+ const key = k as keyof Options;
+ const value = opts[key]?.value;
+ const sourceIndex = opts[key]?.source;
+ if (sourceIndex !== undefined) {
+ const source = defaultOptions[sourceIndex].name;
+ setProperty(result, key, { value, source });
+ }
+ });
+ return result;
+}
+
function logInfoAboutFuzzerOptions(fuzzerOptions: string[]) {
fuzzerOptions.slice(1).forEach((element) => {
if (element.length > 0 && element[0] != "-") {
@@ -272,21 +474,24 @@ function logInfoAboutFuzzerOptions(fuzzerOptions: string[]) {
});
}
-function optionDependentParams(options: Options, params: string[]): string[] {
- if (!options || !options.fuzzerOptions) {
+function optionDependentParams(
+ options: OptionsManager,
+ params: string[],
+): string[] {
+ if (!options || !options.get("fuzzerOptions")) {
return params;
}
- let opts = options.fuzzerOptions;
- if (options.mode === "regression") {
+ let opts = options.get("fuzzerOptions");
+ if (options.get("mode") === "regression") {
// The last provided option takes precedence
opts = opts.concat("-runs=0");
}
- if (options.timeout <= 0) {
+ if (options.get("timeout") <= 0) {
throw new Error("timeout must be > 0");
}
- const inSeconds = Math.ceil(options.timeout / 1000);
+ const inSeconds = Math.ceil(options.get("timeout") / 1000);
opts = opts.concat(`-timeout=${inSeconds}`);
return opts;
@@ -353,3 +558,46 @@ ${jazzerArgs.map((s) => '"' + s + '"').join(" ")} -- ${isWindows ? "%*" : "$@"}
return scriptTempFile.name;
}
+
+// Check two things:
+// 1) `dictionaryEntries` can only be set from "Jest fuzz test" source;
+// 2) only few approved options can be set from "Jest fuzz test" source.
+export function validateKeySource(key: keyof Options, source: OptionSource) {
+ const sourceName = defaultOptions[source].name;
+
+ // Only "Jest fuzz test" is allowed to set `dictionaryEntries` option.
+ if (
+ key === "dictionaryEntries" &&
+ source !== OptionSource.JestFuzzTestOptions
+ ) {
+ const allowedSource = defaultOptions[OptionSource.JestFuzzTestOptions].name;
+ throw new Error(
+ `Tried setting option '${key}' from ${sourceName}, but this option is only available in ${allowedSource}`,
+ );
+ }
+
+ // Only selected options can be set from the Jest fuzz test
+ if (
+ source === OptionSource.JestFuzzTestOptions &&
+ !allowedFuzzTestOptions.includes(key as AllowedFuzzTestOptions)
+ ) {
+ throw new Error(`Option '${key}' is not available from "${sourceName}."`);
+ }
+}
+
+// Check if the key can be set from the new source.
+//
+function validateOptionPermissions(
+ key: keyof Options,
+ source: OptionSource,
+ options: OptionsWithSource,
+): boolean {
+ validateKeySource(key, source);
+ // Overwriting options from the same source is not allowed---accumulate the options before writing.
+ if (source === options[key].source) {
+ throw new Error(
+ `Option '${key}' already set from ${defaultOptions[source].name}`,
+ );
+ }
+ return source > options[key].source;
+}
diff --git a/packages/core/package.json b/packages/core/package.json
index e61c5f72c..b633dd334 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -1,6 +1,6 @@
{
"name": "@jazzer.js/core",
- "version": "2.1.0",
+ "version": "3.1.0",
"description": "Jazzer.js CLI",
"homepage": "https://github.com/CodeIntelligenceTesting/jazzer.js#readme",
"author": "Code Intelligence",
@@ -19,18 +19,18 @@
"jazzer": "dist/cli.js"
},
"dependencies": {
- "@jazzer.js/bug-detectors": "2.1.0",
- "@jazzer.js/fuzzer": "2.1.0",
- "@jazzer.js/hooking": "2.1.0",
- "@jazzer.js/instrumentor": "2.1.0",
- "tmp": "^0.2.1",
+ "@jazzer.js/bug-detectors": "3.1.0",
+ "@jazzer.js/fuzzer": "3.1.0",
+ "@jazzer.js/hooking": "3.1.0",
+ "@jazzer.js/instrumentor": "3.1.0",
+ "tmp": "^0.2.3",
"istanbul-lib-coverage": "^3.2.2",
"istanbul-lib-report": "^3.0.1",
- "istanbul-reports": "^3.1.6",
+ "istanbul-reports": "^3.1.7",
"yargs": "^17.7.2"
},
"devDependencies": {
- "@types/yargs": "^17.0.32"
+ "@types/yargs": "^17.0.33"
},
"engines": {
"node": ">= 14.0.0",
diff --git a/packages/core/utils.test.ts b/packages/core/utils.test.ts
index 9df50c70f..703364c79 100644
--- a/packages/core/utils.test.ts
+++ b/packages/core/utils.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,12 +40,12 @@ describe("core", () => {
const args = {
_: ["-some_arg=value", "-other_arg", 123],
corpus: ["directory1", "directory2"],
- fuzz_target: "filename.js",
+ fuzzTarget: "filename.js",
};
const options = prepareArgs(args);
expect(options).toEqual({
- fuzz_target: "file://" + path.join(process.cwd(), "filename.js"),
- fuzzer_options: [
+ fuzzTarget: "file://" + path.join(process.cwd(), "filename.js"),
+ fuzzerOptions: [
"directory1",
"directory2",
"-some_arg=value",
diff --git a/packages/core/utils.ts b/packages/core/utils.ts
index 5fcaf19ce..5d439583e 100644
--- a/packages/core/utils.ts
+++ b/packages/core/utils.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -69,11 +69,14 @@ export function ensureFilepath(filePath: string): string {
export function prepareArgs(args: any) {
const options = {
...args,
- fuzz_target: ensureFilepath(args.fuzz_target),
- fuzzer_options: (args.corpus ?? [])
+ fuzzTarget: ensureFilepath(args.fuzzTarget),
+ fuzzerOptions: (args.corpus ?? [])
.concat(args._)
.map((e: unknown) => e + ""),
};
+ if (options.fuzzerOptions.length === 0) {
+ delete options.fuzzerOptions;
+ }
delete options._;
delete options.corpus;
delete options.$0;
diff --git a/packages/fuzzer/.gitignore b/packages/fuzzer/.gitignore
index 9e45caba3..94ce2116e 100644
--- a/packages/fuzzer/.gitignore
+++ b/packages/fuzzer/.gitignore
@@ -1,4 +1,3 @@
.cache
build
-prebuilds
cmake-build-debug
diff --git a/packages/fuzzer/addon.ts b/packages/fuzzer/addon.ts
index 51e70325f..fc939bc1c 100644
--- a/packages/fuzzer/addon.ts
+++ b/packages/fuzzer/addon.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-import { default as bind } from "bindings";
+import * as fs from "fs";
+import * as path from "path";
export type FuzzTargetAsyncOrValue = (
data: Buffer,
@@ -67,4 +68,16 @@ type NativeAddon = {
startFuzzingAsync: StartFuzzingAsyncFn;
};
-export const addon: NativeAddon = bind("jazzerjs");
+function addonFilename(): string {
+ let dirName: string;
+ if (fs.existsSync(path.join(__dirname, "prebuilds"))) {
+ dirName = path.join(__dirname, "prebuilds");
+ } else if (fs.existsSync(path.join(__dirname, "..", "prebuilds"))) {
+ dirName = path.join(__dirname, "..", "prebuilds");
+ } else {
+ throw new Error("Could not find prebuilds directory");
+ }
+ return path.join(dirName, `fuzzer-${process.platform}-${process.arch}.node`);
+}
+
+export const addon: NativeAddon = require(addonFilename());
diff --git a/packages/fuzzer/coverage.ts b/packages/fuzzer/coverage.ts
index d375df3e0..0f0cedded 100644
--- a/packages/fuzzer/coverage.ts
+++ b/packages/fuzzer/coverage.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/fuzzer/fuzzer.test.ts b/packages/fuzzer/fuzzer.test.ts
index d2b1e909b..c18580c4e 100644
--- a/packages/fuzzer/fuzzer.test.ts
+++ b/packages/fuzzer/fuzzer.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/fuzzer/fuzzer.ts b/packages/fuzzer/fuzzer.ts
index bdca092ab..1330bb44a 100644
--- a/packages/fuzzer/fuzzer.ts
+++ b/packages/fuzzer/fuzzer.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/fuzzer/fuzzing_async.cpp b/packages/fuzzer/fuzzing_async.cpp
index 50693974b..ef7a4dd0c 100644
--- a/packages/fuzzer/fuzzing_async.cpp
+++ b/packages/fuzzer/fuzzing_async.cpp
@@ -66,14 +66,27 @@ using FinalizerDataType = void;
TSFN gTSFN;
-const std::string SEGFAULT_ERROR_MESSAGE =
- "Segmentation fault found in fuzz target";
+// Keeps track of how many times the user pressed CTRL+C.
+volatile int nSigInts = 0;
+// Store the execution context of the fuzz target function. The execution will
+// jump back to this stored context in case of a segfault.
+std::jmp_buf executionContext;
-std::jmp_buf errorBuffer;
+void sigintHandler(int signum) {
+ std::cerr << std::endl; // Print a newline after the ^C.
+ // Pressing CTRL+C more than once will terminate the process immediately.
+ // If the first CTRL+C had no effect, the fuzz target is probably in an
+ // endless loop, or the current input takes long time to process. In this case
+ // it's ok to terminate the process.
+ if (nSigInts > 0) {
+ _Exit(libfuzzer::RETURN_CONTINUE);
+ }
+ nSigInts++;
+}
// See comment on `ErrorSignalHandler` in `fuzzing_sync.cpp` for what this is
// for
-void ErrorSignalHandler(int signum) { std::longjmp(errorBuffer, signum); }
+void ErrorSignalHandler(int signum) { std::longjmp(executionContext, signum); }
// The callback invoked by libFuzzer. It has no access to the JavaScript
// environment and thus can only call the JavaScript fuzz target via the
@@ -115,11 +128,20 @@ void CallJsFuzzCallback(Napi::Env env, Napi::Function jsFuzzCallback,
// Execute the fuzz target and reject the deferred on any raised exception by
// C++ code or returned error by JS interop to stop fuzzing.
try {
+
+ // Pressing CTRL+C will gracefully end the fuzzing.
+ if (nSigInts > 0) {
+ data->promise->set_value(libfuzzer::RETURN_EXIT);
+ context->deferred.Resolve(env.Undefined());
+ context->is_resolved = true;
+ return;
+ }
+
// Return point for the segfault error handler
// This MUST BE called from the thread that executes the fuzz target (and
// thus is the thread with the segfault) otherwise longjmp's behavior is
// undefined
- if (setjmp(errorBuffer) != 0) {
+ if (setjmp(executionContext) == SIGSEGV) {
std::cerr << "==" << (unsigned long)GetPID() << "== Segmentation Fault"
<< std::endl;
libfuzzer::PrintCrashingInput();
@@ -304,6 +326,7 @@ Napi::Value StartFuzzingAsync(const Napi::CallbackInfo &info) {
context->native_thread = std::thread(
[](const std::vector &fuzzer_args) {
signal(SIGSEGV, ErrorSignalHandler);
+ signal(SIGINT, sigintHandler);
StartLibFuzzer(fuzzer_args, FuzzCallbackAsync);
gTSFN.Release();
},
diff --git a/packages/fuzzer/fuzzing_sync.cpp b/packages/fuzzer/fuzzing_sync.cpp
index 29d3df1ed..694d2bc6b 100644
--- a/packages/fuzzer/fuzzing_sync.cpp
+++ b/packages/fuzzer/fuzzing_sync.cpp
@@ -30,9 +30,6 @@
#include "utils.h"
namespace {
-const std::string SEGFAULT_ERROR_MESSAGE =
- "Segmentation fault found in fuzz target";
-
// Information about a JS fuzz target.
struct FuzzTargetInfo {
Napi::Env env;
@@ -47,14 +44,27 @@ struct FuzzTargetInfo {
// to its target function.
std::optional gFuzzTarget;
-// Track if SIGINT signal handler was called.
-// This is only necessary in the sync fuzzing case, as async can be handled
-// much nicer directly in JavaScript.
-volatile std::sig_atomic_t gSignalStatus;
-std::jmp_buf errorBuffer;
+// Signal handlers store the signal number in this variable.
+volatile std::sig_atomic_t gSignalStatus = 0;
+// Keeps track of how many times the user pressed CTRL+C.
+volatile int nSigInts = 0;
+// Store the execution context of the fuzz target function. The execution will
+// jump back to this stored context in case of a segfault.
+std::jmp_buf executionContext;
} // namespace
-void sigintHandler(int signum) { gSignalStatus = signum; }
+void sigintHandler(int signum) {
+ std::cerr << std::endl; // Print a newline after the ^C.
+ gSignalStatus = signum;
+ // Pressing CTRL+C more than once will terminate the process immediately.
+ // If the first CTRL+C had no effect, the fuzz target is probably in an
+ // endless loop, or the current input takes long time to process. In this case
+ // it's ok to terminate the process.
+ if (nSigInts > 0) {
+ _Exit(libfuzzer::RETURN_CONTINUE);
+ }
+ nSigInts++;
+}
// This handles signals that indicate an unrecoverable error (currently only
// segfaults). Our handling of segfaults is odd because it avoids using our
@@ -66,7 +76,7 @@ void sigintHandler(int signum) { gSignalStatus = signum; }
// is good enough
void ErrorSignalHandler(int signum) {
gSignalStatus = signum;
- std::longjmp(errorBuffer, signum);
+ std::longjmp(executionContext, signum);
}
// The libFuzzer callback when fuzzing synchronously
@@ -91,7 +101,7 @@ int FuzzCallbackSync(const uint8_t *Data, size_t Size) {
// the JS buffer is going to be garbage-collected. But it would still be
// nice for efficiency if we could use a pointer instead of copying.
auto data = Napi::Buffer::Copy(gFuzzTarget->env, Data, Size);
- if (setjmp(errorBuffer) == 0) {
+ if (setjmp(executionContext) == 0) {
auto result = gFuzzTarget->target.Call({data});
if (result.IsPromise()) {
AsyncReturnsHandler();
diff --git a/packages/fuzzer/package.json b/packages/fuzzer/package.json
index 446bc1b50..b3527568c 100644
--- a/packages/fuzzer/package.json
+++ b/packages/fuzzer/package.json
@@ -1,6 +1,6 @@
{
"name": "@jazzer.js/fuzzer",
- "version": "2.1.0",
+ "version": "3.1.0",
"description": "Jazzer.js libfuzzer-based fuzzer for Node.js",
"homepage": "https://github.com/CodeIntelligenceTesting/jazzer.js#readme",
"author": "Code Intelligence",
@@ -16,9 +16,8 @@
"main": "dist/fuzzer.js",
"types": "dist/fuzzer.d.ts",
"scripts": {
- "prebuild": "prebuild --runtime napi --backend cmake-js --all --strip --verbose",
- "install": "prebuild-install --runtime napi || npm run prebuild",
- "build": "cmake-js build --out build",
+ "prebuild": "cmake-js build --out build",
+ "build": "node ../../scripts/build-fuzzer.js",
"format:fix": "clang-format -i *.cpp shared/*.cpp shared/*.h",
"lint": "find . -path ./build -prune -type f -o -iname '*.h' -o -iname '*.cpp' | xargs clang-tidy"
},
@@ -30,14 +29,12 @@
"dependencies": {
"bindings": "^1.5.0",
"cmake-js": "^7.3.0",
- "node-addon-api": "^7.1.0",
- "prebuild-install": "^7.1.1"
+ "node-addon-api": "^7.1.0"
},
"devDependencies": {
"@types/bindings": "^1.5.5",
- "@types/node": "^20.11.17",
- "clang-format": "^1.8.0",
- "prebuild": "^12.1.0"
+ "@types/node": "^20.14.11",
+ "clang-format": "^1.8.0"
},
"engines": {
"node": ">= 14.0.0",
diff --git a/packages/fuzzer/trace.ts b/packages/fuzzer/trace.ts
index ff195c4ea..753f468ba 100644
--- a/packages/fuzzer/trace.ts
+++ b/packages/fuzzer/trace.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/hooking/hook.ts b/packages/hooking/hook.ts
index c8f8e4d12..0d59dfb64 100644
--- a/packages/hooking/hook.ts
+++ b/packages/hooking/hook.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,6 +42,7 @@ export type AfterHookFn = (
export type HookFn = BeforeHookFn | ReplaceHookFn | AfterHookFn;
export class Hook {
+ registered = false;
constructor(
public readonly type: HookType,
public readonly target: string,
diff --git a/packages/hooking/index.ts b/packages/hooking/index.ts
index b2ac5abb4..252e208d2 100644
--- a/packages/hooking/index.ts
+++ b/packages/hooking/index.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/hooking/manager.test.ts b/packages/hooking/manager.test.ts
index 5d8ab6030..1875e40a3 100644
--- a/packages/hooking/manager.test.ts
+++ b/packages/hooking/manager.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
*/
import { HookType } from "./hook";
-import { hookManager } from "./manager";
+import { getFunction, hookManager, setFunction } from "./manager";
describe("Hooks manager", () => {
describe("Matching hooks", () => {
@@ -103,6 +103,49 @@ describe("Hooks manager", () => {
);
});
});
+
+ describe("getFunction", () => {
+ it("non-existing function", () => {
+ expect(getFunction({}, ["foo", "bar", "lambda"])).toBeUndefined();
+ });
+
+ it("non-existing function", () => {
+ expect(
+ getFunction({ foo: { bar: { lambda: "test" } } }, [
+ "foo",
+ "bar",
+ "lambda",
+ ]),
+ ).toBe("test");
+ });
+ });
+
+ describe("setFunction", () => {
+ it("non-existing function", () => {
+ const obj = {};
+ setFunction(obj, ["foo", "bar", "lambda"], () => {});
+ expect(obj).toStrictEqual({});
+ });
+
+ it("change an existing function to a number - should fail", () => {
+ const originalFn = () => {};
+ const obj = { foo: { bar: { lambda: originalFn } } };
+ const accessorChain = ["foo", "bar", "lambda"];
+ setFunction(obj, accessorChain, 10);
+ expect(getFunction(obj, accessorChain)).toStrictEqual(originalFn);
+ });
+
+ it("change an existing function to a new function", () => {
+ const originalFn = () => {};
+ const newFunction = (a: number) => {
+ return a;
+ };
+ const obj = { foo: { bar: { lambda: originalFn } } };
+ const accessorChain = ["foo", "bar", "lambda"];
+ setFunction(obj, accessorChain, newFunction);
+ expect(getFunction(obj, accessorChain)).toStrictEqual(newFunction);
+ });
+ });
});
function registerHook(
diff --git a/packages/hooking/manager.ts b/packages/hooking/manager.ts
index e71821fda..22c08be34 100644
--- a/packages/hooking/manager.ts
+++ b/packages/hooking/manager.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,6 +15,7 @@
*/
import { builtinModules } from "module";
+import * as vm from "vm";
import {
AfterHookFn,
@@ -120,14 +121,14 @@ export class HookManager {
* initialization steps for the hooks to work. This method must be called
* after all hooks have been registered.
*/
- async finalizeHooks() {
+ async finalizeHooks(vmContext: vm.Context | typeof globalThis) {
// Built-in functions cannot be hooked by the instrumentor, so that is
// explicitly done here instead.
// Loading build-in modules is asynchronous, so we need to wait, which
// is not possible in the instrumentor.
for (const builtinModule of builtinModules) {
- const matchedHooks = this._hooks.filter((hook) =>
- builtinModule.includes(hook.pkg),
+ const matchedHooks = this._hooks.filter(
+ (hook) => builtinModule.includes(hook.pkg) && hook.pkg !== "",
);
for (const hook of matchedHooks) {
try {
@@ -135,13 +136,32 @@ export class HookManager {
} catch (e) {
if (process.env.JAZZER_DEBUG) {
console.error(
- "DEBUG: [Hook] Error when trying to hook the built-in function: " +
- e,
+ "DEBUG: [hooking] Could not hook built-in function: " +
+ hook.pkg +
+ " : " +
+ hook.target,
);
+ console.error(e);
}
}
}
}
+
+ // Hook global functions (functions without module names)
+ const globalHooks = this._hooks.filter((hook) => hook.pkg === "");
+ for (const hook of globalHooks) {
+ try {
+ hookGlobalFunction(hook, vmContext);
+ } catch (e) {
+ if (process.env.JAZZER_DEBUG) {
+ console.error(
+ "DEBUG: [hooking] Could not hook the global function: " +
+ hook.target,
+ );
+ console.error(e);
+ }
+ }
+ }
}
registerHook(
@@ -249,28 +269,129 @@ export function registerAfterHook(
hookManager.registerHook(HookType.After, target, pkg, async, hookFn);
}
+export function getFunction(
+ module: object,
+ propertyAccessors: string[],
+): unknown {
+ let current = module;
+
+ for (const propertyAccessor of propertyAccessors) {
+ try {
+ // @ts-ignore
+ current = current[propertyAccessor];
+ } catch (e) {
+ return undefined;
+ }
+ }
+ return current;
+}
+
+export function setFunction(
+ module: object,
+ propertyAccessors: string[],
+ newFunction: unknown,
+): void {
+ if (!(newFunction instanceof Function || typeof newFunction === "function")) {
+ if (process.env.JAZZER_DEBUG) {
+ console.error(
+ "DEBUG: [hooking] Could not hook built-in function: " +
+ propertyAccessors.join(".") +
+ "\n" +
+ " provided newFunction is not a function",
+ );
+ }
+ return;
+ }
+
+ let current = module;
+ for (const propertyAccessor of propertyAccessors.slice(0, -1)) {
+ try {
+ // @ts-ignore
+ current = current[propertyAccessor];
+ } catch (e) {
+ if (process.env.JAZZER_DEBUG) {
+ console.error(
+ "DEBUG: [hooking] Could not hook built-in function: " +
+ propertyAccessors.join("."),
+ );
+ }
+ return;
+ }
+ }
+ // @ts-ignore
+ current[propertyAccessors[propertyAccessors.length - 1]] = newFunction;
+}
+
/**
* Replaces a built-in function with a custom implementation while preserving
* the original function for potential use within the replacement function.
*/
export async function hookBuiltInFunction(hook: Hook): Promise {
+ if (hook.registered) return;
+ hook.registered = true;
const { default: module } = await import(hook.pkg);
- const originalFn = module[hook.target];
+ const targetPropertyAccessors = hook.target.split(".");
+ const originalFn = getFunction(module, targetPropertyAccessors);
+ hookFunction(module, hook, originalFn, targetPropertyAccessors);
+}
+
+function hookGlobalFunction(
+ hook: Hook,
+ context: vm.Context | typeof globalThis,
+): void {
+ const originalFn = vm.isContext(context)
+ ? vm.runInContext(hook.target, context)
+ : vm.runInThisContext(hook.target);
+
+ if (originalFn) {
+ hookFunction(context, hook, originalFn);
+ const newFunction = getFunction(context, hook.target.split("."));
+ // assign prototype of the original function to the prototype of the new function
+ if (newFunction instanceof Function || typeof newFunction === "function") {
+ newFunction.prototype = originalFn.prototype;
+ }
+ }
+}
+
+function hookFunction(
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ obj: any,
+ hook: Hook,
+ originalFn: unknown | ((...args: unknown[]) => unknown),
+ targetPropertyAccessors: string[] = hook.target.split("."),
+) {
+ if (!(originalFn instanceof Function || typeof originalFn === "function")) {
+ if (process.env.JAZZER_DEBUG) {
+ console.error(
+ "DEBUG: [hooking] Could not hook built-in function: " +
+ hook.pkg +
+ " : " +
+ hook.target,
+ );
+ }
+ return;
+ }
+
const id = callSiteId(hookManager.hookIndex(hook), hook.pkg, hook.target);
if (hook.type == HookType.Before) {
- module[hook.target] = (...args: unknown[]) => {
- (hook.hookFunction as BeforeHookFn)(null, args, id);
- return originalFn(...args);
- };
+ setFunction(obj, targetPropertyAccessors, function (...args: unknown[]) {
+ // @ts-ignore
+ (hook.hookFunction as BeforeHookFn)(this, args, id);
+ // @ts-ignore
+ return originalFn.apply(this, args);
+ });
} else if (hook.type == HookType.Replace) {
- module[hook.target] = (...args: unknown[]) => {
- return (hook.hookFunction as ReplaceHookFn)(null, args, id, originalFn);
- };
+ setFunction(obj, targetPropertyAccessors, function (...args: unknown[]) {
+ // @ts-ignore
+ return (hook.hookFunction as ReplaceHookFn)(this, args, id, originalFn);
+ });
} else if (hook.type == HookType.After) {
- module[hook.target] = (...args: unknown[]) => {
- const result: unknown = originalFn(...args);
- return (hook.hookFunction as AfterHookFn)(null, args, id, result);
- };
+ setFunction(obj, targetPropertyAccessors, function (...args: unknown[]) {
+ // @ts-ignore
+ const result: unknown = originalFn.apply(this, args);
+ // @ts-ignore
+ return (hook.hookFunction as AfterHookFn)(this, args, id, result);
+ });
} else {
throw new Error(`Unknown hook type ${hook.type}`);
}
diff --git a/packages/hooking/package.json b/packages/hooking/package.json
index 795a7557e..d21ad982c 100644
--- a/packages/hooking/package.json
+++ b/packages/hooking/package.json
@@ -1,6 +1,6 @@
{
"name": "@jazzer.js/hooking",
- "version": "2.1.0",
+ "version": "3.1.0",
"description": "Jazzer.js hooking framework",
"homepage": "https://github.com/CodeIntelligenceTesting/jazzer.js#readme",
"author": "Code Intelligence",
@@ -15,12 +15,6 @@
},
"main": "dist/index.js",
"types": "dist/index.d.js",
- "dependencies": {
- "@babel/core": "^7.23.9"
- },
- "devDependencies": {
- "@types/babel__core": "^7.20.5"
- },
"engines": {
"node": ">= 14.0.0",
"npm": ">= 7.0.0"
diff --git a/packages/hooking/tracker.ts b/packages/hooking/tracker.ts
index f874eb5a2..cbc0be5c4 100644
--- a/packages/hooking/tracker.ts
+++ b/packages/hooking/tracker.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/instrumentor/README.md b/packages/instrumentor/README.md
index 8029a9142..e4a3ba275 100644
--- a/packages/instrumentor/README.md
+++ b/packages/instrumentor/README.md
@@ -23,7 +23,5 @@ npm install --save-dev @jazzer.js/instrumentor
## Documentation
See
-[Jazzer.js README](https://github.com/CodeIntelligenceTesting/jazzer.js#readme)
-for more information or the
-[issues](https://github.com/CodeIntelligenceTesting/jazzer.js/issues?q=is%3Aissue+is%3Aopen)
-associated with it.
+[Jazzer.js README](https://github.com/CodeIntelligenceTesting/jazzer.js-commercial#readme)
+for more information.
diff --git a/packages/instrumentor/SourceMapRegistry.ts b/packages/instrumentor/SourceMapRegistry.ts
index 3aee73bc3..c8ee4e2eb 100644
--- a/packages/instrumentor/SourceMapRegistry.ts
+++ b/packages/instrumentor/SourceMapRegistry.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -95,7 +95,7 @@ export class SourceMapRegistry {
? {
map: sourceMap,
url: source,
- }
+ }
: null;
},
});
diff --git a/packages/instrumentor/edgeIdStrategy.ts b/packages/instrumentor/edgeIdStrategy.ts
index 416189256..dfc0c25e3 100644
--- a/packages/instrumentor/edgeIdStrategy.ts
+++ b/packages/instrumentor/edgeIdStrategy.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -144,7 +144,7 @@ export class FileSyncIdStrategy extends IncrementingEdgeIdStrategy {
this.firstEdgeId =
idInfo.length !== 0
? idInfo[idInfo.length - 1].firstId +
- idInfo[idInfo.length - 1].idCount
+ idInfo[idInfo.length - 1].idCount
: 0;
break;
case 1:
diff --git a/packages/instrumentor/guard.ts b/packages/instrumentor/guard.ts
index ee4270b08..71d9e6631 100644
--- a/packages/instrumentor/guard.ts
+++ b/packages/instrumentor/guard.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/instrumentor/instrument.test.ts b/packages/instrumentor/instrument.test.ts
index 9498a6446..832ae63dc 100644
--- a/packages/instrumentor/instrument.test.ts
+++ b/packages/instrumentor/instrument.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/instrumentor/instrument.ts b/packages/instrumentor/instrument.ts
index bc85d0cbf..0f07c5784 100644
--- a/packages/instrumentor/instrument.ts
+++ b/packages/instrumentor/instrument.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -104,12 +104,23 @@ export class Instrumentor {
this.idStrategy.startForSourceFile(filename);
}
- const result = this.transform(
- filename,
- code,
- transformations,
- this.asInputSourceOption(inputSourceMap),
- );
+ let result: BabelFileResult | null = null;
+
+ try {
+ result = this.transform(
+ filename,
+ code,
+ transformations,
+ this.asInputSourceOption(inputSourceMap),
+ );
+ } catch (e) {
+ if (process.env.JAZZER_DEBUG) {
+ const message = e instanceof Error ? e.message : e;
+ console.error(
+ `Instrumentation error in file ${filename}:\n ${message}`,
+ );
+ }
+ }
if (shouldInstrumentFile) {
this.idStrategy.commitIdCount(filename);
}
diff --git a/packages/instrumentor/package.json b/packages/instrumentor/package.json
index 9d8205638..d409db682 100644
--- a/packages/instrumentor/package.json
+++ b/packages/instrumentor/package.json
@@ -1,6 +1,6 @@
{
"name": "@jazzer.js/instrumentor",
- "version": "2.1.0",
+ "version": "3.1.0",
"description": "Jazzer.js source code instrumentor",
"homepage": "https://github.com/CodeIntelligenceTesting/jazzer.js#readme",
"author": "Code Intelligence",
@@ -16,23 +16,23 @@
"main": "dist/instrument.js",
"types": "dist/instrument.d.js",
"dependencies": {
- "@babel/core": "^7.23.9",
- "@babel/generator": "^7.23.5",
- "@jazzer.js/fuzzer": "2.1.0",
- "@jazzer.js/hooking": "2.1.0",
+ "@babel/core": "^7.25.2",
+ "@babel/generator": "^7.25.6",
+ "@jazzer.js/fuzzer": "3.1.0",
+ "@jazzer.js/hooking": "3.1.0",
"istanbul-lib-hook": "^3.0.0",
"proper-lockfile": "^4.1.2",
- "istanbul-lib-instrument": "^6.0.1",
+ "istanbul-lib-instrument": "^6.0.3",
"source-map-support": "^0.5.21"
},
"devDependencies": {
"@types/babel__core": "^7.20.5",
"@types/istanbul-lib-hook": "^2.0.4",
"@types/istanbul-lib-instrument": "^1.7.7",
- "@types/node": "^20.11.17",
+ "@types/node": "^20.14.11",
"@types/proper-lockfile": "^4.1.4",
"@types/source-map-support": "^0.5.10",
- "typescript": "^5.3.3"
+ "typescript": "^5.6.2"
},
"engines": {
"node": ">= 14.0.0",
diff --git a/packages/instrumentor/plugin.ts b/packages/instrumentor/plugin.ts
index 4ce9e90cc..53fe4d0c5 100644
--- a/packages/instrumentor/plugin.ts
+++ b/packages/instrumentor/plugin.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/instrumentor/plugins/codeCoverage.test.ts b/packages/instrumentor/plugins/codeCoverage.test.ts
index ee04c96cb..51aa3fe0a 100644
--- a/packages/instrumentor/plugins/codeCoverage.test.ts
+++ b/packages/instrumentor/plugins/codeCoverage.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/instrumentor/plugins/codeCoverage.ts b/packages/instrumentor/plugins/codeCoverage.ts
index 5631e18a5..00092ff89 100644
--- a/packages/instrumentor/plugins/codeCoverage.ts
+++ b/packages/instrumentor/plugins/codeCoverage.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/instrumentor/plugins/compareHooks.test.ts b/packages/instrumentor/plugins/compareHooks.test.ts
index db3a262cb..038f25c57 100644
--- a/packages/instrumentor/plugins/compareHooks.test.ts
+++ b/packages/instrumentor/plugins/compareHooks.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/instrumentor/plugins/compareHooks.ts b/packages/instrumentor/plugins/compareHooks.ts
index 18753184d..5414f0db7 100644
--- a/packages/instrumentor/plugins/compareHooks.ts
+++ b/packages/instrumentor/plugins/compareHooks.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/instrumentor/plugins/functionHooks.test.ts b/packages/instrumentor/plugins/functionHooks.test.ts
index 68cdad455..476bbb0f7 100644
--- a/packages/instrumentor/plugins/functionHooks.test.ts
+++ b/packages/instrumentor/plugins/functionHooks.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -880,21 +880,20 @@ describe("function hooks instrumentation", () => {
|
|foo(1, 2);`;
- const dbgMock = withDebug(
- () =>
- expectInstrumentationEval>(input, output)?.then(
- (result: number) => {
- expect(result).toEqual(3);
- expect(beforeHookCallMap.size).toEqual(1);
- expectHook(0, beforeHookCallMap);
- expect(afterHookCallMap.size).toEqual(1);
- expectHook(0, afterHookCallMap);
- expectTrackedHooks(hookTracker.applied, ["foo"]);
- expectTrackedHooks(hookTracker.available, ["bar"]);
- expectTrackedHooksUnknown(beforeHookCallMap, 0);
- expectTrackedHooksUnknown(afterHookCallMap, 0);
- },
- ),
+ const dbgMock = withDebug(() =>
+ expectInstrumentationEval>(input, output)?.then(
+ (result: number) => {
+ expect(result).toEqual(3);
+ expect(beforeHookCallMap.size).toEqual(1);
+ expectHook(0, beforeHookCallMap);
+ expect(afterHookCallMap.size).toEqual(1);
+ expectHook(0, afterHookCallMap);
+ expectTrackedHooks(hookTracker.applied, ["foo"]);
+ expectTrackedHooks(hookTracker.available, ["bar"]);
+ expectTrackedHooksUnknown(beforeHookCallMap, 0);
+ expectTrackedHooksUnknown(afterHookCallMap, 0);
+ },
+ ),
);
expectLogHooks(dbgMock, 2, "Before", "foo");
diff --git a/packages/instrumentor/plugins/functionHooks.ts b/packages/instrumentor/plugins/functionHooks.ts
index 26f6deee4..aadb2a636 100644
--- a/packages/instrumentor/plugins/functionHooks.ts
+++ b/packages/instrumentor/plugins/functionHooks.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/instrumentor/plugins/helpers.ts b/packages/instrumentor/plugins/helpers.ts
index d97a2a434..85efe49f2 100644
--- a/packages/instrumentor/plugins/helpers.ts
+++ b/packages/instrumentor/plugins/helpers.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/instrumentor/plugins/sourceCodeCoverage.test.ts b/packages/instrumentor/plugins/sourceCodeCoverage.test.ts
index dcf679c76..51b600956 100644
--- a/packages/instrumentor/plugins/sourceCodeCoverage.test.ts
+++ b/packages/instrumentor/plugins/sourceCodeCoverage.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/instrumentor/plugins/sourceCodeCoverage.ts b/packages/instrumentor/plugins/sourceCodeCoverage.ts
index abb960a1b..bae53ac16 100644
--- a/packages/instrumentor/plugins/sourceCodeCoverage.ts
+++ b/packages/instrumentor/plugins/sourceCodeCoverage.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/instrumentor/plugins/testhelpers.ts b/packages/instrumentor/plugins/testhelpers.ts
index cdae21d2d..22cede85f 100644
--- a/packages/instrumentor/plugins/testhelpers.ts
+++ b/packages/instrumentor/plugins/testhelpers.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/jest-runner/config.test.ts b/packages/jest-runner/config.test.ts
index eb99262e4..b46a55d9f 100644
--- a/packages/jest-runner/config.test.ts
+++ b/packages/jest-runner/config.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,40 +14,44 @@
* limitations under the License.
*/
-import { defaultOptions } from "@jazzer.js/core";
+import { OptionsManager, OptionSource } from "@jazzer.js/core";
-import { loadConfig, TIMEOUT_PLACEHOLDER } from "./config";
+import { loadConfig } from "./config";
+
+const defaultJestOptions = new OptionsManager(OptionSource.DefaultJestOptions);
describe("Config", () => {
describe("loadConfig", () => {
it("return default configuration if nothing found", () => {
- const defaults = { ...defaultOptions, timeout: TIMEOUT_PLACEHOLDER };
- defaults.mode = "regression";
- expect(loadConfig()).toEqual(defaults);
+ expect(loadConfig().getOptions()).toEqual(
+ defaultJestOptions.getOptions(),
+ );
});
it("merge found and default options", () => {
const config = loadConfig({}, "test-jazzerjs");
- expect(config).not.toEqual(defaultOptions);
- expect(config.includes).toContain("target");
- expect(config.excludes).toContain("nothing");
+ expect(config.getOptions()).not.toEqual(defaultJestOptions.getOptions());
+ expect(config.get("includes")).toContain("target");
+ expect(config.get("excludes")).toContain("nothing");
});
it("merge explicitly passed in options", () => {
const config = loadConfig({ fuzzTarget: "foo" }, "test-jazzerjs");
- expect(config.fuzzTarget).toEqual("foo");
+ expect(config.get("fuzzTarget")).toEqual("foo");
});
it("deep copy configurations", () => {
const config1 = loadConfig();
- config1.fuzzerOptions.push("-runs=100");
+ config1.get("fuzzerOptions").push("-runs=100");
const config2 = loadConfig({}, "merge-test-jazzerjs");
- expect(config1.fuzzerOptions).not.toEqual(config2.fuzzerOptions);
+ expect(config1.get("fuzzerOptions")).not.toEqual(
+ config2.get("fuzzerOptions"),
+ );
});
it("default to regression mode", () => {
- expect(loadConfig().mode).toEqual("regression");
+ expect(loadConfig().get("mode")).toEqual("regression");
});
it("set fuzzing mode based on environment variable", () => {
try {
process.env.JAZZER_FUZZ = "1";
- expect(loadConfig().mode).toEqual("fuzzing");
+ expect(loadConfig().get("mode")).toEqual("fuzzing");
} finally {
delete process.env.JAZZER_FUZZ;
}
diff --git a/packages/jest-runner/config.ts b/packages/jest-runner/config.ts
index 47c9c00ce..fa6e1a8f2 100644
--- a/packages/jest-runner/config.ts
+++ b/packages/jest-runner/config.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,39 +16,26 @@
import { cosmiconfigSync } from "cosmiconfig";
-import {
- buildOptions,
- Options,
- ParameterResolverIndex,
- setParameterResolverValue,
-} from "@jazzer.js/core";
+import { Options, OptionsManager, OptionSource } from "@jazzer.js/core";
export const TIMEOUT_PLACEHOLDER = Number.MIN_SAFE_INTEGER;
-// Lookup `Options` via the `.jazzerjsrc` configuration files.
+// Load Jazzer.js `Options` from the `.jazzerjsrc` configuration files and environment variables.
export function loadConfig(
options: Partial = {},
optionsKey = "jazzerjs",
-): Options {
- const result = cosmiconfigSync(optionsKey).search();
- const config = result?.config ?? {};
- // If no timeout is specified, use a placeholder value so that no
- // default timeout is used. Afterwards remove the placeholder value,
- // if not already overwritten by the user.
- if (config.timeout === undefined) {
- config.timeout = TIMEOUT_PLACEHOLDER;
- }
- // Jazzer.js normally runs in "fuzzing" mode, but,
- // if not specified otherwise, Jest uses "regression" mode.
- if (!config.mode) {
- config.mode = "regression";
- }
+): OptionsManager {
+ const config = cosmiconfigSync(optionsKey).search()?.config ?? {};
+
// Switch to fuzzing mode if environment variable `JAZZER_FUZZ` is set.
if (process.env.JAZZER_FUZZ) {
config.mode = "fuzzing";
}
// Merge explicitly passed in options, e.g. coverage settings from Jest.
Object.assign(config, options);
- setParameterResolverValue(ParameterResolverIndex.ConfigurationFile, config);
- return buildOptions();
+
+ return new OptionsManager(OptionSource.DefaultJestOptions).merge(
+ config,
+ OptionSource.ConfigurationFile,
+ );
}
diff --git a/packages/jest-runner/corpus.test.ts b/packages/jest-runner/corpus.test.ts
index c4e402446..654d87eca 100644
--- a/packages/jest-runner/corpus.test.ts
+++ b/packages/jest-runner/corpus.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/jest-runner/corpus.ts b/packages/jest-runner/corpus.ts
index c25909345..ff1041184 100644
--- a/packages/jest-runner/corpus.ts
+++ b/packages/jest-runner/corpus.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/jest-runner/errorUtils.test.ts b/packages/jest-runner/errorUtils.test.ts
index 144e6e279..316361a23 100644
--- a/packages/jest-runner/errorUtils.test.ts
+++ b/packages/jest-runner/errorUtils.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,11 +14,7 @@
* limitations under the License.
*/
-import {
- cleanupJestError,
- removeTopFrames,
- removeTopFramesFromError,
-} from "./errorUtils";
+import { cleanupJestError } from "./errorUtils";
describe("ErrorUtils", () => {
const error = new Error();
diff --git a/packages/jest-runner/errorUtils.ts b/packages/jest-runner/errorUtils.ts
index 3214e668f..99d2212ff 100644
--- a/packages/jest-runner/errorUtils.ts
+++ b/packages/jest-runner/errorUtils.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/jest-runner/fuzz.test.ts b/packages/jest-runner/fuzz.test.ts
index 23ec9b383..2fe814309 100644
--- a/packages/jest-runner/fuzz.test.ts
+++ b/packages/jest-runner/fuzz.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,8 @@ import * as tmp from "tmp";
import {
FindingAwareFuzzTarget,
- Options,
+ OptionsManager,
+ OptionSource,
startFuzzingNoInit,
} from "@jazzer.js/core";
import { FuzzTarget } from "@jazzer.js/fuzzer";
@@ -48,12 +49,14 @@ jest.mock("./corpus", () => {
// Mock core package to intercept calls to startFuzzing.
const skipMock = jest.fn();
jest.mock("@jazzer.js/core", () => {
+ globalThis.JazzerJS = new Map();
+ const core = jest.requireActual("@jazzer.js/core");
// noinspection JSUnusedGlobalSymbols
return {
- startFuzzingNoInit: jest.fn().mockImplementation(async (args: unknown) => {
+ ...core,
+ startFuzzingNoInit: jest.fn().mockImplementation(async (args) => {
return args;
}),
- asFindingAwareFuzzFn: (fn: object) => fn,
};
});
@@ -70,13 +73,20 @@ describe("fuzz", () => {
describe("runInFuzzingMode", () => {
it("execute test matching original test name pattern", async () => {
+ const inputPaths = mockInputPaths();
+ const fuzzingConfig = new OptionsManager(
+ OptionSource.DefaultJestOptions,
+ ).merge({ mode: "fuzzing" }, OptionSource.ConfigurationFile);
await withMockTest(() => {
const originalTestNamePattern = jest
.fn()
.mockReturnValue(/^myFuzzTest$/);
- invokeFuzz({ originalTestNamePattern })("myFuzzTest", jest.fn());
+ invokeFuzz({ originalTestNamePattern, fuzzingConfig })(
+ "myFuzzTest",
+ jest.fn(),
+ );
});
- expect(startFuzzingNoInit).toBeCalledTimes(1);
+ expect(startFuzzingNoInit).toHaveBeenCalledTimes(1);
});
it("skip test not matching original test name pattern", async () => {
@@ -86,7 +96,7 @@ describe("fuzz", () => {
.mockReturnValue(/^not_existing$/);
invokeFuzz({ originalTestNamePattern })("myFuzzTest", jest.fn());
});
- expect(startFuzzingNoInit).toBeCalledTimes(0);
+ expect(startFuzzingNoInit).toHaveBeenCalledTimes(0);
});
});
@@ -100,7 +110,7 @@ describe("fuzz", () => {
"fuzz",
asFindingAwareFuzzFn(testFn),
corpus,
- {} as Options,
+ new OptionsManager(OptionSource.DefaultJestOptions),
globalThis as Global.Global,
"standard",
);
@@ -120,7 +130,7 @@ describe("fuzz", () => {
done();
}),
mockDefaultCorpus(),
- {} as Options,
+ new OptionsManager(OptionSource.DefaultJestOptions),
globalThis as Global.Global,
"standard",
);
@@ -142,7 +152,7 @@ describe("fuzz", () => {
});
}),
mockDefaultCorpus(),
- {} as Options,
+ new OptionsManager(OptionSource.DefaultJestOptions),
globalThis as Global.Global,
"standard",
);
@@ -162,7 +172,7 @@ describe("fuzz", () => {
});
}),
mockDefaultCorpus(),
- {} as Options,
+ new OptionsManager(OptionSource.DefaultJestOptions),
globalThis as Global.Global,
"standard",
);
@@ -186,7 +196,7 @@ describe("fuzz", () => {
resolve("done called multiple times");
}),
mockDefaultCorpus(),
- {} as Options,
+ new OptionsManager(OptionSource.DefaultJestOptions),
globalThis as Global.Global,
"standard",
);
@@ -204,7 +214,7 @@ describe("fuzz", () => {
"fuzz",
asFindingAwareFuzzFn(testFn),
corpus,
- {} as Options,
+ new OptionsManager(OptionSource.DefaultJestOptions),
globalThis as Global.Global,
"standard",
);
@@ -274,7 +284,7 @@ function invokeFuzz(
params: Partial<{
globals: Global.Global;
testFile: string;
- fuzzingConfig: Options;
+ fuzzingConfig: OptionsManager;
currentTestState: () => Circus.DescribeBlock | undefined;
currentTestTimeout: () => number | undefined;
originalTestNamePattern: () => RegExp | undefined;
@@ -284,10 +294,7 @@ function invokeFuzz(
const paramsWithDefaults = {
globals: globalThis as Global.Global,
testFile: "testfile",
- fuzzingConfig: {
- fuzzerOptions: [""],
- mode: "fuzzing",
- } as Options,
+ fuzzingConfig: new OptionsManager(OptionSource.DefaultJestOptions),
currentTestState: jest.fn().mockReturnValue({}),
currentTestTimeout: jest.fn().mockReturnValue(undefined),
originalTestNamePattern: jest.fn().mockReturnValue(undefined),
diff --git a/packages/jest-runner/fuzz.ts b/packages/jest-runner/fuzz.ts
index eb19c0cf7..3f4a941a0 100644
--- a/packages/jest-runner/fuzz.ts
+++ b/packages/jest-runner/fuzz.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,19 +19,19 @@ import * as fs from "fs";
import { Circus, Global } from "@jest/types";
import {
+ AllowedFuzzTestOptions,
asFindingAwareFuzzFn,
- defaultOptions,
FindingAwareFuzzTarget,
- Options,
- startFuzzingNoInit,
-} from "@jazzer.js/core";
-import {
FuzzTarget,
FuzzTargetAsyncOrValue,
FuzzTargetCallback,
-} from "@jazzer.js/fuzzer";
+ Options,
+ OptionsManager,
+ OptionSource,
+ printOptions,
+ startFuzzingNoInit,
+} from "@jazzer.js/core";
-import { TIMEOUT_PLACEHOLDER } from "./config";
import { Corpus } from "./corpus";
import { removeTopFramesFromError } from "./errorUtils";
@@ -41,7 +41,7 @@ export class FuzzerError extends Error {}
export type FuzzTest = (
name: Global.TestNameLike,
fn: FuzzTarget,
- timeout?: number,
+ timeoutOrOptions?: number | Partial>,
) => void;
export const skip: (globals: Global.Global) => FuzzTest =
@@ -76,16 +76,37 @@ function printTestNameIfRequested(testStatePath: string[]) {
export function fuzz(
globals: Global.Global,
testFile: string,
- fuzzingConfig: Options,
+ fuzzingConfig: OptionsManager,
currentTestState: () => Circus.DescribeBlock | undefined,
currentTestTimeout: () => number | undefined,
originalTestNamePattern: () => RegExp | undefined,
mode: JestTestMode,
): FuzzTest {
- return (name, fn, timeout) => {
+ return (name, fn, timeoutOrOptions) => {
// Deep clone the fuzzing config, so that each test can modify it without
// affecting other tests, e.g. set a test specific timeout.
- const localConfig = JSON.parse(JSON.stringify(fuzzingConfig));
+ const localConfig = fuzzingConfig.clone();
+
+ if (currentTestTimeout()) {
+ localConfig.merge(
+ { timeout: currentTestTimeout() },
+ OptionSource.InternalJestTimeout,
+ );
+ }
+
+ let paramsToMerge: Partial = {};
+
+ if (typeof timeoutOrOptions === "number") {
+ paramsToMerge = { timeout: timeoutOrOptions };
+ } else if (typeof timeoutOrOptions === "object") {
+ paramsToMerge = timeoutOrOptions;
+ } else if (timeoutOrOptions !== undefined) {
+ throw new FuzzerError(
+ `Invalid timeout or options argument "${timeoutOrOptions}"`,
+ );
+ }
+
+ localConfig.merge(paramsToMerge, OptionSource.JestFuzzTestOptions);
const state = currentTestState();
if (!state) {
@@ -101,7 +122,7 @@ export function fuzz(
const skip =
testStatePath !== undefined &&
- testNamePattern != undefined &&
+ testNamePattern !== undefined &&
!testNamePattern.test(testStatePath.join(" "));
if (skip) {
globals.test.skip(name, () => {
@@ -110,31 +131,23 @@ export function fuzz(
return;
}
- const corpus = new Corpus(testFile, testStatePath, localConfig.coverage);
-
- // Timeout priority is:
- // 1. Use timeout directly defined in test function
- // 2. Use timeout defined in fuzzing config
- // 3. Use jest timeout
- if (timeout != undefined) {
- localConfig.timeout = timeout;
- } else {
- const jestTimeout = currentTestTimeout();
- if (jestTimeout != undefined && localConfig.timeout == undefined) {
- localConfig.timeout = jestTimeout;
- } else if (localConfig.timeout === TIMEOUT_PLACEHOLDER) {
- localConfig.timeout = defaultOptions.timeout;
- }
- }
+ const corpus = new Corpus(
+ testFile,
+ testStatePath,
+ localConfig.get("coverage"),
+ );
- const wrappedFn = asFindingAwareFuzzFn(fn, localConfig.mode === "fuzzing");
+ const wrappedFn = asFindingAwareFuzzFn(
+ fn,
+ localConfig.get("mode") === "fuzzing",
+ );
- if (localConfig.mode === "regression") {
+ if (localConfig.get("mode") === "regression") {
runInRegressionMode(name, wrappedFn, corpus, localConfig, globals, mode);
- } else if (localConfig.mode === "fuzzing") {
+ } else if (localConfig.get("mode") === "fuzzing") {
runInFuzzingMode(name, wrappedFn, corpus, localConfig, globals, mode);
} else {
- throw new Error(`Unknown mode ${localConfig.mode}`);
+ throw new Error(`Unknown mode ${localConfig.get("mode")}`);
}
};
}
@@ -143,17 +156,17 @@ export const runInFuzzingMode = (
name: Global.TestNameLike,
fn: FindingAwareFuzzTarget,
corpus: Corpus,
- options: Options,
+ options: OptionsManager,
globals: Global.Global,
mode: JestTestMode,
) => {
handleMode(mode, globals.test)(name, async () => {
- options.fuzzerOptions.unshift(corpus.seedInputsDirectory);
- options.fuzzerOptions.unshift(corpus.generatedInputsDirectory);
- options.fuzzerOptions.push(
- "-artifact_prefix=" + corpus.seedInputsDirectory,
- );
- return startFuzzingNoInit(fn, options).then(({ error }) => {
+ const newOptions = options.clone();
+ const fuzzerOptions = newOptions.get("fuzzerOptions");
+ fuzzerOptions.unshift(corpus.seedInputsDirectory);
+ fuzzerOptions.unshift(corpus.generatedInputsDirectory);
+ fuzzerOptions.push("-artifact_prefix=" + corpus.seedInputsDirectory);
+ return startFuzzingNoInit(fn, newOptions).then(({ error }) => {
// Throw the found error to mark the test as failed.
if (error) throw error;
});
@@ -164,10 +177,12 @@ export const runInRegressionMode = (
name: Global.TestNameLike,
fn: FindingAwareFuzzTarget,
corpus: Corpus,
- options: Options,
+ options: OptionsManager,
globals: Global.Global,
mode: JestTestMode,
) => {
+ printOptions(options, `for test "${name}"`);
+
handleMode(mode, globals.describe)(name, () => {
function executeTarget(content: Buffer) {
return new Promise((resolve, reject) => {
@@ -187,7 +202,7 @@ export const runInRegressionMode = (
globals.test(
"",
async () => executeTarget(Buffer.from("")),
- options.timeout,
+ options.get("timeout"),
);
// Execute the fuzz test with each input file as no libFuzzer is required.
@@ -195,7 +210,7 @@ export const runInRegressionMode = (
globals.test(
seed,
async () => executeTarget(await fs.promises.readFile(path)),
- options.timeout,
+ options.get("timeout"),
);
});
});
diff --git a/packages/jest-runner/globalsInterceptor.test.ts b/packages/jest-runner/globalsInterceptor.test.ts
index 8980fc676..2da6ebd85 100644
--- a/packages/jest-runner/globalsInterceptor.test.ts
+++ b/packages/jest-runner/globalsInterceptor.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ import { fuzz } from "./fuzz";
import { interceptGlobals } from "./globalsInterceptor";
const internalFuzz = jest.fn();
+
jest.mock("./fuzz", () => ({
fuzz: jest.fn().mockImplementation(() => {
return internalFuzz;
diff --git a/packages/jest-runner/globalsInterceptor.ts b/packages/jest-runner/globalsInterceptor.ts
index 8f14ae8b7..ce9ae03b6 100644
--- a/packages/jest-runner/globalsInterceptor.ts
+++ b/packages/jest-runner/globalsInterceptor.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
import Runtime from "jest-runtime";
-import { Options } from "@jazzer.js/core";
+import { OptionsManager } from "@jazzer.js/core";
import { fuzz } from "./fuzz";
import { InterceptedTestState } from "./testStateInterceptor";
@@ -24,7 +24,7 @@ import { InterceptedTestState } from "./testStateInterceptor";
export function interceptGlobals(
runtime: Runtime,
testPath: string,
- jazzerConfig: Options,
+ jazzerConfig: OptionsManager,
{
currentTestState,
currentTestTimeout,
diff --git a/packages/jest-runner/index.ts b/packages/jest-runner/index.ts
index ccc1cd666..af3fc0f76 100644
--- a/packages/jest-runner/index.ts
+++ b/packages/jest-runner/index.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,19 +45,19 @@ export default async function jazzerTestRunner(
const vmContext = environment.getVmContext();
if (vmContext === null) throw new Error("vmContext is undefined");
- const jazzerConfig = loadConfig({
+ const options = loadConfig({
coverage: globalConfig.collectCoverage,
coverageReporters: globalConfig.coverageReporters as reports.ReportType[],
});
const globalEnvironments = [environment.getVmContext(), globalThis];
- registerGlobals(jazzerConfig, globalEnvironments);
+ registerGlobals(options, globalEnvironments);
setJazzerJsGlobal("vmContext", vmContext);
- const instrumentor = await initFuzzing(jazzerConfig);
+ const instrumentor = await initFuzzing(options);
interceptScriptTransformerCalls(runtime, instrumentor);
- const testState = interceptTestState(environment, jazzerConfig);
- interceptGlobals(runtime, testPath, jazzerConfig, testState);
+ const testState = interceptTestState(environment, options);
+ interceptGlobals(runtime, testPath, options, testState);
const circusRunner =
await runtime["_scriptTransformer"].requireAndTranspileModule(
diff --git a/packages/jest-runner/package.json b/packages/jest-runner/package.json
index c234aa7a8..a0da93ac7 100644
--- a/packages/jest-runner/package.json
+++ b/packages/jest-runner/package.json
@@ -1,6 +1,6 @@
{
"name": "@jazzer.js/jest-runner",
- "version": "2.1.0",
+ "version": "3.1.0",
"description": "Jazzer.js Jest runner",
"homepage": "https://github.com/CodeIntelligenceTesting/jazzer.js#readme",
"author": "Code Intelligence",
@@ -16,9 +16,9 @@
"main": "dist/index.js",
"types": "dist/index.d.ts",
"dependencies": {
- "@jazzer.js/core": "2.1.0",
- "cosmiconfig": "^8.3.6",
- "istanbul-reports": "^3.1.6"
+ "@jazzer.js/core": "3.1.0",
+ "cosmiconfig": "^9.0.0",
+ "istanbul-reports": "^3.1.7"
},
"peerDependencies": {
"@types/jest": "29.*",
@@ -26,7 +26,7 @@
},
"devDependencies": {
"@types/tmp": "^0.2.6",
- "tmp": "^0.2.1"
+ "tmp": "^0.2.3"
},
"engines": {
"node": ">= 14.0.0",
diff --git a/packages/jest-runner/readme.md b/packages/jest-runner/readme.md
index 45b06afb5..73811c4eb 100644
--- a/packages/jest-runner/readme.md
+++ b/packages/jest-runner/readme.md
@@ -2,7 +2,7 @@
Custom Jest runner to executes fuzz tests via Jazzer.js, detailed documentation
can be found at the
-[Jazzer.js GitHub page](https://github.com/CodeIntelligenceTesting/jazzer.js).
+[Jazzer.js GitHub page](https://github.com/CodeIntelligenceTesting/jazzer.js-commercial).
A fuzz test in Jest, in this case written in TypeScript, would look similar to
the following example:
diff --git a/packages/jest-runner/testStateInterceptor.test.ts b/packages/jest-runner/testStateInterceptor.test.ts
index ca305e6ff..0f7214a44 100644
--- a/packages/jest-runner/testStateInterceptor.test.ts
+++ b/packages/jest-runner/testStateInterceptor.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { defaultOptions, Options } from "@jazzer.js/core";
+import { Options, OptionsManager, OptionSource } from "@jazzer.js/core";
import { interceptTestState } from "./testStateInterceptor";
@@ -107,9 +107,10 @@ function mockEnvironment(options: Partial = {}) {
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any;
- const config = {
- ...defaultOptions,
- ...options,
- };
+ const config = new OptionsManager(OptionSource.DefaultJestOptions).merge(
+ options,
+ OptionSource.ConfigurationFile,
+ );
+
return { env, config, originalHandleTestEvent };
}
diff --git a/packages/jest-runner/testStateInterceptor.ts b/packages/jest-runner/testStateInterceptor.ts
index 2c292b8f4..5bac8cdea 100644
--- a/packages/jest-runner/testStateInterceptor.ts
+++ b/packages/jest-runner/testStateInterceptor.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
import { JestEnvironment } from "@jest/environment";
import { Circus } from "@jest/types";
-import { Options } from "@jazzer.js/core";
+import { OptionsManager } from "@jazzer.js/core";
// Arbitrary high value to disable Jest timeout.
const JEST_TIMEOUT_DISABLED = 1000 * 60 * 24 * 365;
@@ -30,7 +30,7 @@ export type InterceptedTestState = {
export function interceptTestState(
environment: JestEnvironment,
- jazzerConfig: Options,
+ jazzerConfig: OptionsManager,
): InterceptedTestState {
const originalHandleTestEvent =
environment.handleTestEvent?.bind(environment);
@@ -47,7 +47,7 @@ export function interceptTestState(
// test inside. This breaks test name pattern matching, so remove "$" from the end of the pattern,
// and skip tests not matching the original pattern in the fuzz function.
if (
- jazzerConfig.mode == "regression" &&
+ jazzerConfig.get("mode") == "regression" &&
state.testNamePattern?.source?.endsWith("$")
) {
originalTestNamePattern = state.testNamePattern;
@@ -59,7 +59,10 @@ export function interceptTestState(
} else if (event.name === "test_start") {
// In fuzzing mode, only execute the first encountered (not skipped) fuzz test
// and mark all others as skipped.
- if (jazzerConfig.mode === "fuzzing" && event.test.mode !== "skip") {
+ if (
+ jazzerConfig.get("mode") === "fuzzing" &&
+ event.test.mode !== "skip"
+ ) {
if (
!firstFuzzTestEncountered &&
(!state.testNamePattern ||
@@ -75,7 +78,7 @@ export function interceptTestState(
} else if (event.name === "test_fn_start") {
// Disable Jest timeout in fuzzing mode by setting it to a high value,
// otherwise Jest will kill the fuzz test after it's timeout (default 5 seconds).
- if (jazzerConfig.mode === "fuzzing") {
+ if (jazzerConfig.get("mode") === "fuzzing") {
state.testTimeout = JEST_TIMEOUT_DISABLED;
}
// Use configured timeout as fuzzing timeout as well. Every invocation
diff --git a/packages/jest-runner/transformerInterceptor.test.ts b/packages/jest-runner/transformerInterceptor.test.ts
index e7cbdb8ee..750cc6a28 100644
--- a/packages/jest-runner/transformerInterceptor.test.ts
+++ b/packages/jest-runner/transformerInterceptor.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/jest-runner/transformerInterceptor.ts b/packages/jest-runner/transformerInterceptor.ts
index f4faf277b..be4c1b644 100644
--- a/packages/jest-runner/transformerInterceptor.ts
+++ b/packages/jest-runner/transformerInterceptor.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/packages/jest-runner/tsconfig.json b/packages/jest-runner/tsconfig.json
index e258f91fe..b3da45e9d 100644
--- a/packages/jest-runner/tsconfig.json
+++ b/packages/jest-runner/tsconfig.json
@@ -7,9 +7,6 @@
"references": [
{
"path": "../core"
- },
- {
- "path": "../fuzzer"
}
]
}
diff --git a/scripts/build-fuzzer.js b/scripts/build-fuzzer.js
new file mode 100644
index 000000000..d009722f9
--- /dev/null
+++ b/scripts/build-fuzzer.js
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2026 Code Intelligence GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+const fs = require("fs");
+const path = require("path");
+
+const strip = require("./strip");
+
+fs.mkdirSync("prebuilds", { recursive: true });
+
+// Copy napi release into prebuilds/fuzzer--.node
+const targetName = path.join(
+ "prebuilds",
+ `fuzzer-${process.platform}-${getArchitecture()}.node`,
+);
+fs.copyFileSync("build/Release/jazzerjs.node", targetName);
+
+// Strip debugging symbols from the release binary.
+// TODO: maybe only strip when releasing?
+strip(targetName, function (err) {
+ if (err) {
+ console.error(err);
+ process.exit(1);
+ }
+});
+
+function getArchitecture() {
+ if (process.argv[3] && process.argv[3] === "x86_64") return "x64";
+
+ return process.argv[3] ?? process.arch;
+}
diff --git a/scripts/set-version.js b/scripts/set-version.js
new file mode 100644
index 000000000..bfd3c14e7
--- /dev/null
+++ b/scripts/set-version.js
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2026 Code Intelligence GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+const { execSync } = require("child_process");
+const fs = require("fs");
+const path = require("path");
+
+const newVersion = process.argv[2];
+validateVersion(newVersion);
+
+const packagesDir = path.join(__dirname, "..", "packages");
+const packages = fs.readdirSync(packagesDir);
+
+// read package.json of each package
+packages.forEach((packageName) => {
+ const packageJson = require(
+ path.join(packagesDir, packageName, "package.json"),
+ );
+
+ // update the version of the package
+ packageJson.version = newVersion;
+
+ // update the version of the dependencies
+ for (const dependencyName in packageJson.dependencies) {
+ // for all packages, check if the dependencyName name includes any of them
+ if (
+ packages.some(
+ (packageName) => dependencyName === "@jazzer.js/" + packageName,
+ )
+ ) {
+ packageJson.dependencies[dependencyName] = newVersion;
+ }
+ }
+
+ // write the updated package.json
+ writePackageJson(
+ path.join(packagesDir, packageName, "package.json"),
+ packageJson,
+ );
+});
+
+// update the jazzer.js version in the /package.json
+updateVersion(path.join(__dirname, "..", "package.json"), newVersion);
+
+// run npm install to update the package-lock.json files
+execSync("npm install", { cwd: packagesDir, stdio: "inherit" });
+
+function updateVersion(filename, newVersion) {
+ const pkg = require(filename);
+ pkg.version = newVersion;
+ writePackageJson(filename, pkg);
+}
+
+function writePackageJson(filename, pkg) {
+ fs.writeFileSync(filename, JSON.stringify(pkg, null, "\t") + "\n");
+}
+
+// make sure the new version has the format v*.*.*
+function validateVersion(version) {
+ if (!version?.match(/^\d+\.\d+\.\d+$/)) {
+ console.error("Invalid version format. Expected *.*.*");
+ process.exit(1);
+ }
+}
diff --git a/scripts/strip.js b/scripts/strip.js
new file mode 100644
index 000000000..1ac9b6d1a
--- /dev/null
+++ b/scripts/strip.js
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2026 Code Intelligence GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Original file has MIT Licence
+// This file is copied from prebuild/strip.js from https://github.com/prebuild/prebuild
+
+const child_process = require("child_process");
+
+function strip(files, cb) {
+ // TODO no support on windows, noop
+ const platform = process.platform;
+ if (platform === "win32") return process.nextTick(cb);
+ stripFiles(files, platform, cb);
+}
+
+function stripFiles(file, platform, cb) {
+ spawn(
+ process.env.STRIP || "strip",
+ stripArgs(platform, file),
+ function (err) {
+ if (err) {
+ cb(err);
+ return;
+ }
+ },
+ );
+}
+
+function stripArgs(platform, file) {
+ if (platform === "darwin") return [file, "-Sx"];
+ if (["freebsd", "linux"].includes(platform)) return [file, "--strip-all"];
+ // TODO find out what args to use for other platforms, e.g. 'sunos'
+ return [];
+}
+
+function spawn(cmd, args, cb) {
+ return child_process.spawn(cmd, args).on("exit", function (code) {
+ if (code === 0) return cb();
+ cb(new Error("could not spawn strip"));
+ });
+}
+
+module.exports = strip;
diff --git a/tests/bug-detectors/command-injection.test.js b/tests/bug-detectors/command-injection.test.js
index 6e2ad78fe..64b3cb29b 100644
--- a/tests/bug-detectors/command-injection.test.js
+++ b/tests/bug-detectors/command-injection.test.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/bug-detectors/command-injection/fuzz.js b/tests/bug-detectors/command-injection/fuzz.js
index b97f61ab5..7c37dfefe 100644
--- a/tests/bug-detectors/command-injection/fuzz.js
+++ b/tests/bug-detectors/command-injection/fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/bug-detectors/command-injection/makeFRIENDLY.js b/tests/bug-detectors/command-injection/makeFRIENDLY.js
index 1873081e9..56844d6fd 100644
--- a/tests/bug-detectors/command-injection/makeFRIENDLY.js
+++ b/tests/bug-detectors/command-injection/makeFRIENDLY.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/bug-detectors/general.test.js b/tests/bug-detectors/general.test.js
index c2367aac6..f94d5c79c 100644
--- a/tests/bug-detectors/general.test.js
+++ b/tests/bug-detectors/general.test.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,7 +30,7 @@ describe("General tests", () => {
const friendlyFilePath = path.join(bugDetectorDirectory, "FRIENDLY");
const evilFilePath = path.join(bugDetectorDirectory, "jaz_zer");
const errorPattern =
- /Command Injection in execSync\(\): called with 'jaz_zer'/g;
+ /Command Injection\n {4}in execSync\(\): called with 'jaz_zer'/g;
function expectErrorToBePrintedOnce(fuzzTest) {
const matches = fuzzTest.stderr.match(errorPattern);
diff --git a/tests/bug-detectors/general/fuzz.js b/tests/bug-detectors/general/fuzz.js
index ee92eb794..aa6031944 100644
--- a/tests/bug-detectors/general/fuzz.js
+++ b/tests/bug-detectors/general/fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -100,22 +100,22 @@ module.exports.CallOriginalFriendlyAsyncCallingSync = async function (data) {
};
module.exports.ForkModeCallOriginalEvil = makeFuzzFunctionWithInput(
- 100,
+ 1,
evilCommand,
);
module.exports.ForkModeCallOriginalFriendly = makeFuzzFunctionWithInput(
- 100,
+ 1,
friendlyCommand,
);
module.exports.ForkModeCallOriginalEvilAsync = makeAsyncFuzzFunctionWithInput(
- 100,
+ 1,
evilCommand,
);
module.exports.ForkModeCallOriginalFriendlyAsync =
- makeAsyncFuzzFunctionWithInput(100, friendlyCommand);
+ makeAsyncFuzzFunctionWithInput(1, friendlyCommand);
module.exports.DisableAllBugDetectors = makeFnCalledOnce(async (data) => {
// Command Injection : try to make an empty file named "jaz_zer" (our evil string)
diff --git a/tests/bug-detectors/general/tests.fuzz.js b/tests/bug-detectors/general/tests.fuzz.js
index 9782736c1..13b945d4e 100644
--- a/tests/bug-detectors/general/tests.fuzz.js
+++ b/tests/bug-detectors/general/tests.fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/bug-detectors/path-traversal.test.js b/tests/bug-detectors/path-traversal.test.js
index 3b690c2a8..a45cd501c 100644
--- a/tests/bug-detectors/path-traversal.test.js
+++ b/tests/bug-detectors/path-traversal.test.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/bug-detectors/path-traversal/fuzz.js b/tests/bug-detectors/path-traversal/fuzz.js
index f32c85447..791cf9f10 100644
--- a/tests/bug-detectors/path-traversal/fuzz.js
+++ b/tests/bug-detectors/path-traversal/fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -101,10 +101,10 @@ module.exports.PathTraversalJoinSafeAsync = makeFnCalledOnce(async (data) => {
path.join(safe_path, "SAFE");
});
-module.exports.invalidArgsToOpen = makeFnCalledOnce((data) => {
+module.exports.invalidArgsToOpen = (data) => {
fs.openSync(0);
-});
+};
-module.exports.invalidArgsToCp = makeFnCalledOnce((data) => {
+module.exports.invalidArgsToCp = (data) => {
fs.cp(0, 0, () => {});
-});
+};
diff --git a/tests/bug-detectors/prototype-pollution.test.js b/tests/bug-detectors/prototype-pollution.test.js
index 5d00d8dee..f3d5f203f 100644
--- a/tests/bug-detectors/prototype-pollution.test.js
+++ b/tests/bug-detectors/prototype-pollution.test.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -75,7 +75,7 @@ describe("Prototype Pollution", () => {
fuzzTest.execute();
}).toThrowError(FuzzingExitCode);
expect(fuzzTest.stderr).toContain(
- "Prototype Pollution: Prototype of Function changed",
+ "Prototype Pollution\n Prototype of Function changed",
);
});
@@ -90,7 +90,7 @@ describe("Prototype Pollution", () => {
fuzzTest.execute();
}).toThrowError(FuzzingExitCode);
expect(fuzzTest.stderr).toContain(
- "Prototype Pollution: Prototype of String changed",
+ "Prototype Pollution\n Prototype of String changed",
);
});
@@ -105,7 +105,7 @@ describe("Prototype Pollution", () => {
fuzzTest.execute();
}).toThrowError(FuzzingExitCode);
expect(fuzzTest.stderr).toContain(
- "Prototype Pollution: Prototype of Number changed",
+ "Prototype Pollution\n Prototype of Number changed",
);
});
@@ -120,7 +120,7 @@ describe("Prototype Pollution", () => {
fuzzTest.execute();
}).toThrowError(FuzzingExitCode);
expect(fuzzTest.stderr).toContain(
- "Prototype Pollution: Prototype of Boolean changed",
+ "Prototype Pollution\n Prototype of Boolean changed",
);
});
@@ -138,7 +138,7 @@ describe("Prototype Pollution", () => {
fuzzTest.execute();
}).toThrowError(FuzzingExitCode);
expect(fuzzTest.stderr).toContain(
- "Prototype Pollution: a.__proto__ value is ",
+ "Prototype Pollution\n a.__proto__ value is ",
);
});
@@ -155,7 +155,7 @@ describe("Prototype Pollution", () => {
expect(() => {
fuzzTest.execute();
}).toThrowError(FuzzingExitCode);
- expect(fuzzTest.stderr).toContain("Prototype Pollution: a.__proto__");
+ expect(fuzzTest.stderr).toContain("Prototype Pollution\n a.__proto__");
});
it("Test no instrumentation and polluting __proto__ of a class", () => {
@@ -334,7 +334,7 @@ describe("Prototype Pollution Jest tests", () => {
fuzzTest.execute();
}).toThrowError(JestRegressionExitCode);
expect(fuzzTest.stderr).toContain(
- "Prototype Pollution: Prototype of Object changed",
+ "Prototype Pollution\n Prototype of Object changed",
);
});
@@ -353,7 +353,7 @@ describe("Prototype Pollution Jest tests", () => {
fuzzTest.execute();
}).toThrowError(JestRegressionExitCode);
expect(fuzzTest.stderr).toContain(
- "Prototype Pollution: a.__proto__ value is",
+ "Prototype Pollution\n a.__proto__ value is",
);
});
@@ -372,7 +372,7 @@ describe("Prototype Pollution Jest tests", () => {
fuzzTest.execute();
}).toThrowError(JestRegressionExitCode);
expect(fuzzTest.stderr).toContain(
- "Prototype Pollution: a.__proto__ value is",
+ "Prototype Pollution\n a.__proto__ value is",
);
});
@@ -389,7 +389,7 @@ describe("Prototype Pollution Jest tests", () => {
fuzzTest.execute();
}).toThrowError(JestRegressionExitCode);
expect(fuzzTest.stderr).toContain(
- "Prototype Pollution: Prototype of Object changed",
+ "Prototype Pollution\n Prototype of Object changed",
);
});
diff --git a/tests/bug-detectors/prototype-pollution/fuzz.js b/tests/bug-detectors/prototype-pollution/fuzz.js
index 45dc9feeb..520e389ac 100644
--- a/tests/bug-detectors/prototype-pollution/fuzz.js
+++ b/tests/bug-detectors/prototype-pollution/fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/bug-detectors/prototype-pollution/instrument-all-exclude-one.config.js b/tests/bug-detectors/prototype-pollution/instrument-all-exclude-one.config.js
index 2dc32b77b..5f87c2299 100644
--- a/tests/bug-detectors/prototype-pollution/instrument-all-exclude-one.config.js
+++ b/tests/bug-detectors/prototype-pollution/instrument-all-exclude-one.config.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/bug-detectors/prototype-pollution/instrument-all.config.js b/tests/bug-detectors/prototype-pollution/instrument-all.config.js
index b9c7e3f39..e068efa04 100644
--- a/tests/bug-detectors/prototype-pollution/instrument-all.config.js
+++ b/tests/bug-detectors/prototype-pollution/instrument-all.config.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/bug-detectors/prototype-pollution/instrumentation-correctness-tests.js b/tests/bug-detectors/prototype-pollution/instrumentation-correctness-tests.js
index ceb46e3f4..77901ccd8 100644
--- a/tests/bug-detectors/prototype-pollution/instrumentation-correctness-tests.js
+++ b/tests/bug-detectors/prototype-pollution/instrumentation-correctness-tests.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/bug-detectors/prototype-pollution/tests.fuzz.js b/tests/bug-detectors/prototype-pollution/tests.fuzz.js
index 679154c0c..6b0e49b17 100644
--- a/tests/bug-detectors/prototype-pollution/tests.fuzz.js
+++ b/tests/bug-detectors/prototype-pollution/tests.fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/bug-detectors/remote-code-execution.test.js b/tests/bug-detectors/remote-code-execution.test.js
new file mode 100644
index 000000000..dc4c6d582
--- /dev/null
+++ b/tests/bug-detectors/remote-code-execution.test.js
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2026 Code Intelligence GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const path = require("path");
+
+const {
+ FuzzTestBuilder,
+ FuzzingExitCode,
+ JestRegressionExitCode,
+} = require("../helpers.js");
+
+const bugDetectorDirectory = path.join(__dirname, "remote-code-execution");
+
+const findingMessage = "Remote Code Execution";
+const okMessage = "can be called just fine";
+let fuzzTestBuilder;
+
+beforeEach(() => {
+ fuzzTestBuilder = new FuzzTestBuilder()
+ .runs(0)
+ .dir(bugDetectorDirectory)
+ .sync(true);
+});
+
+describe("CLI", () => {
+ describe("eval ()", () => {
+ it("Invocation without error", () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("invocationWithoutError")
+ .build()
+ .execute();
+ expect(fuzzTest.stdout).toContain(okMessage);
+ });
+
+ it("Direct invocation", () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("directInvocation")
+ .sync(true)
+ .build();
+ expect(() => {
+ fuzzTest.execute();
+ }).toThrowError(FuzzingExitCode);
+ expect(fuzzTest.stderr).toContain(findingMessage);
+ });
+
+ it("Indirect invocation", () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("indirectInvocation")
+ .sync(true)
+ .build();
+ expect(() => {
+ fuzzTest.execute();
+ }).toThrowError(FuzzingExitCode);
+ expect(fuzzTest.stderr).toContain(findingMessage);
+ });
+
+ it("Indirect invocation using comma operator", () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("indirectInvocationUsingCommaOperator")
+ .sync(true)
+ .build();
+ expect(() => {
+ fuzzTest.execute();
+ }).toThrowError(FuzzingExitCode);
+ expect(fuzzTest.stderr).toContain(findingMessage);
+ });
+
+ it("Indirect invocation through optional chaining", () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("indirectInvocationThroughOptionalChaining")
+ .sync(true)
+ .build();
+ expect(() => {
+ fuzzTest.execute();
+ }).toThrowError(FuzzingExitCode);
+ expect(fuzzTest.stderr).toContain(findingMessage);
+ });
+ });
+
+ describe("Function constructor", () => {
+ it("Invocation without error, without explicit constructor", () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("functionNoErrorNoConstructor")
+ .sync(true)
+ .build()
+ .execute();
+ expect(fuzzTest.stdout).toContain(okMessage);
+ });
+
+ it("Invocation without error", () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("functionNoErrorWithConstructor")
+ .sync(true)
+ .build()
+ .execute();
+ expect(fuzzTest.stdout).toContain(okMessage);
+ });
+
+ it("Direct invocation", () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("functionError")
+ .sync(true)
+ .build();
+ expect(() => {
+ fuzzTest.execute();
+ }).toThrowError(FuzzingExitCode);
+ expect(fuzzTest.stderr).toContain(findingMessage);
+ });
+
+ it("Direct invocation using new", () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("functionErrorNew")
+ .sync(true)
+ .build();
+ expect(() => {
+ fuzzTest.execute();
+ }).toThrowError(FuzzingExitCode);
+ expect(fuzzTest.stderr).toContain(findingMessage);
+ });
+
+ it("Target string in variable name - no error", () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("functionWithArgNoError")
+ .sync(true)
+ .build()
+ .execute();
+ expect(fuzzTest.stdout).toContain(okMessage);
+ });
+
+ it("With error - target string in last arg", () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("functionWithArgError")
+ .sync(true)
+ .build();
+ expect(() => {
+ fuzzTest.execute();
+ }).toThrowError(FuzzingExitCode);
+ expect(fuzzTest.stderr).toContain(findingMessage);
+ });
+
+ it("Function.prototype should still exist", () => {
+ const fuzzTest = fuzzTestBuilder
+ .dryRun(false)
+ .fuzzEntryPoint("functionPrototypeExists")
+ .sync(true)
+ .build();
+ fuzzTest.execute();
+ });
+ });
+});
+
+describe("Jest", () => {
+ describe("eval", () => {
+ it("Direct invocation", () => {
+ const fuzzTest = fuzzTestBuilder
+ .dryRun(false)
+ .jestTestFile("tests.fuzz.js")
+ .jestTestName("eval Direct invocation$")
+ .build();
+ expect(() => {
+ fuzzTest.execute();
+ }).toThrowError(JestRegressionExitCode);
+ expect(fuzzTest.stderr).toContain(findingMessage);
+ });
+
+ it("Indirect invocation", () => {
+ const fuzzTest = fuzzTestBuilder
+ .dryRun(false)
+ .jestTestFile("tests.fuzz.js")
+ .jestTestName("eval Indirect invocation$")
+ .build();
+ expect(() => {
+ fuzzTest.execute();
+ }).toThrowError(JestRegressionExitCode);
+ expect(fuzzTest.stderr).toContain(findingMessage);
+ });
+
+ it("Indirect invocation using comma operator", () => {
+ const fuzzTest = fuzzTestBuilder
+ .dryRun(false)
+ .jestTestFile("tests.fuzz.js")
+ .jestTestName("eval Indirect invocation using comma operator$")
+ .build();
+ expect(() => {
+ fuzzTest.execute();
+ }).toThrowError(JestRegressionExitCode);
+ expect(fuzzTest.stderr).toContain(findingMessage);
+ });
+
+ it("Indirect invocation using optional chaining", () => {
+ const fuzzTest = fuzzTestBuilder
+ .dryRun(false)
+ .verbose(true)
+ .jestTestFile("tests.fuzz.js")
+ .jestTestName("eval Indirect invocation through optional chaining$")
+ .build();
+ expect(() => {
+ fuzzTest.execute();
+ }).toThrowError(JestRegressionExitCode);
+ expect(fuzzTest.stderr).toContain(findingMessage);
+ });
+
+ it("No error with absence of the target string", () => {
+ const fuzzTest = fuzzTestBuilder
+ .dryRun(false)
+ .jestTestFile("tests.fuzz.js")
+ .jestTestName("eval No error$")
+ .build()
+ .execute();
+ expect(fuzzTest.stdout).toContain(okMessage);
+ });
+ });
+
+ describe("Function constructor", () => {
+ it("No error", () => {
+ const fuzzTest = fuzzTestBuilder
+ .dryRun(false)
+ .jestTestFile("tests.fuzz.js")
+ .jestTestName("Function No error$")
+ .build();
+ fuzzTest.execute();
+ expect(fuzzTest.stdout).toContain(okMessage);
+ });
+
+ it("No error with constructor", () => {
+ const fuzzTest = fuzzTestBuilder
+ .dryRun(false)
+ .jestTestFile("tests.fuzz.js")
+ .jestTestName("Function No error with constructor$")
+ .build();
+ fuzzTest.execute();
+ expect(fuzzTest.stdout).toContain(okMessage);
+ });
+
+ it("With error", () => {
+ const fuzzTest = fuzzTestBuilder
+ .dryRun(false)
+ .jestTestFile("tests.fuzz.js")
+ .jestTestName("Function With error$")
+ .build();
+ expect(() => {
+ fuzzTest.execute();
+ }).toThrowError(JestRegressionExitCode);
+ expect(fuzzTest.stderr).toContain(findingMessage);
+ });
+
+ it("With error with constructor", () => {
+ const fuzzTest = fuzzTestBuilder
+ .dryRun(false)
+ .jestTestFile("tests.fuzz.js")
+ .jestTestName("Function With error with constructor$")
+ .build();
+ expect(() => {
+ fuzzTest.execute();
+ }).toThrowError(JestRegressionExitCode);
+ expect(fuzzTest.stderr).toContain(findingMessage);
+ });
+
+ it("Variable name containing target string should not throw", () => {
+ const fuzzTest = fuzzTestBuilder
+ .dryRun(false)
+ .jestTestFile("tests.fuzz.js")
+ .jestTestName("Function Target string in variable name - no error$")
+ .build()
+ .execute();
+ expect(fuzzTest.stdout).toContain(okMessage);
+ });
+
+ it("With variable, body contains target string - should throw", () => {
+ const fuzzTest = fuzzTestBuilder
+ .dryRun(false)
+ .jestTestFile("tests.fuzz.js")
+ .jestTestName("Function With error - target string in last arg$")
+ .build();
+ expect(() => {
+ fuzzTest.execute();
+ }).toThrowError(JestRegressionExitCode);
+ expect(fuzzTest.stderr).toContain(findingMessage);
+ });
+
+ it("Function.prototype should still exist", () => {
+ const fuzzTest = fuzzTestBuilder
+ .dryRun(false)
+ .jestTestFile("tests.fuzz.js")
+ .jestTestName("Function.prototype still exists$")
+ .build();
+ fuzzTest.execute();
+ });
+ });
+});
diff --git a/tests/bug-detectors/remote-code-execution/fuzz.js b/tests/bug-detectors/remote-code-execution/fuzz.js
new file mode 100644
index 000000000..daab6b959
--- /dev/null
+++ b/tests/bug-detectors/remote-code-execution/fuzz.js
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2026 Code Intelligence GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const printOkMessage = "console.log('can be called just fine')";
+
+// eval
+module.exports.invocationWithoutError = function (data) {
+ eval("const a = 10; const b = 20;" + printOkMessage);
+};
+
+module.exports.directInvocation = function (data) {
+ eval("const jaz_zer = 10;");
+};
+
+module.exports.indirectInvocation = function (data) {
+ const a = eval;
+ a("const jaz_zer = 10;");
+};
+
+module.exports.indirectInvocationUsingCommaOperator = function (data) {
+ (0, eval)("const jaz_zer = 10;");
+};
+
+module.exports.indirectInvocationThroughOptionalChaining = function (data) {
+ eval?.("const jaz_zer = 10;");
+};
+
+// Function
+module.exports.functionNoErrorNoConstructor = function (data) {
+ Function("const a = 10; const b = 20;" + printOkMessage)();
+};
+
+module.exports.functionNoErrorWithConstructor = function (data) {
+ const fn = new Function("const a = 10; const b = 20;" + printOkMessage);
+ fn();
+};
+
+module.exports.functionError = function (data) {
+ Function("const jaz_zer = 10;");
+};
+
+module.exports.functionErrorNew = function (data) {
+ new Function("const jaz_zer = 10;")();
+};
+
+module.exports.functionWithArgNoError = function (data) {
+ new Function(
+ "jaz_zer",
+ "const foo = 10; console.log('Function can be called just fine')",
+ )("_");
+};
+
+module.exports.functionWithArgError = function (data) {
+ new Function("foo", "const jaz_zer = 10;")("_");
+};
+
+module.exports.functionPrototypeExists = function (data) {
+ console.log(Function.prototype.call.bind);
+};
diff --git a/tests/bug-detectors/remote-code-execution/package.json b/tests/bug-detectors/remote-code-execution/package.json
new file mode 100644
index 000000000..fcb22af75
--- /dev/null
+++ b/tests/bug-detectors/remote-code-execution/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "jazzerjs-remote-code-execution-tests",
+ "version": "1.0.0",
+ "description": "Tests for the Remote Code Execution bug detector",
+ "scripts": {
+ "test": "jest",
+ "fuzz": "JAZZER_FUZZ=1 jest"
+ },
+ "devDependencies": {
+ "@jazzer.js/jest-runner": "file:../../packages/jest-runner",
+ "eslint-plugin-jest": "^27.1.3"
+ },
+ "jest": {
+ "projects": [
+ {
+ "testRunner": "@jazzer.js/jest-runner",
+ "displayName": {
+ "name": "Jazzer.js",
+ "color": "cyan"
+ },
+ "testMatch": [
+ "/**/*.fuzz.js"
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/bug-detectors/remote-code-execution/tests.fuzz.js b/tests/bug-detectors/remote-code-execution/tests.fuzz.js
new file mode 100644
index 000000000..a7a7a3a88
--- /dev/null
+++ b/tests/bug-detectors/remote-code-execution/tests.fuzz.js
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2026 Code Intelligence GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const tests = require("./fuzz");
+
+describe("eval", () => {
+ it.fuzz("No error", (data) => {
+ tests.invocationWithoutError(data);
+ });
+
+ it.fuzz("Direct invocation", (data) => {
+ tests.directInvocation(data);
+ });
+
+ it.fuzz("Indirect invocation", (data) => {
+ tests.indirectInvocation(data);
+ });
+
+ it.fuzz("Indirect invocation using comma operator", (data) => {
+ tests.indirectInvocationUsingCommaOperator(data);
+ });
+
+ it.fuzz("Indirect invocation through optional chaining", (data) => {
+ tests.indirectInvocationThroughOptionalChaining(data);
+ });
+});
+
+describe("Function", () => {
+ it.fuzz("No error", (data) => {
+ tests.functionNoErrorNoConstructor();
+ });
+ it.fuzz("No error with constructor", (data) => {
+ tests.functionNoErrorWithConstructor(data);
+ });
+
+ it.fuzz("With error", (data) => {
+ tests.functionError(data);
+ });
+
+ it.fuzz("With error with constructor", (data) => {
+ tests.functionErrorNew(data);
+ });
+
+ it.fuzz("Target string in variable name - no error", (data) => {
+ tests.functionWithArgNoError(data);
+ });
+
+ it.fuzz("With error - target string in last arg", (data) => {
+ tests.functionWithArgError(data);
+ });
+
+ it.fuzz("Function.prototype still exists", (data) => {
+ tests.functionPrototypeExists(data);
+ });
+});
diff --git a/tests/bug-detectors/ssrf.test.js b/tests/bug-detectors/ssrf.test.js
new file mode 100644
index 000000000..1c208f53c
--- /dev/null
+++ b/tests/bug-detectors/ssrf.test.js
@@ -0,0 +1,416 @@
+/*
+ * Copyright 2026 Code Intelligence GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const dgram = require("dgram");
+const fs = require("fs");
+const http = require("http");
+const https = require("https");
+const path = require("path");
+
+const {
+ FuzzTestBuilder,
+ FuzzingExitCode,
+ JestRegressionExitCode,
+} = require("../helpers.js");
+
+const {
+ host,
+ hostIPv6,
+ okPort,
+ okPortHttps,
+ okPortIPv6,
+ notOkPort,
+ notOkPortHttps,
+ okMessage,
+ notOkMessage,
+ ssrfFindingMessage,
+} = require("./ssrf/connection-settings.js");
+
+describe("SSRF", () => {
+ let endpoints;
+
+ beforeAll(async () => {
+ endpoints = [
+ [http.createServer, host, okPort, okMessage],
+ [http.createServer, host, notOkPort, notOkMessage],
+ [https.createServer, host, okPortHttps, okMessage],
+ [https.createServer, host, notOkPortHttps, notOkMessage],
+ [dgram.createSocket, host, okPort, okMessage, false],
+ [dgram.createSocket, host, notOkPort, notOkMessage, false],
+ [dgram.createSocket, hostIPv6, okPortIPv6, okMessage, false, true],
+ ].map(
+ async ([createServerFn, host, port, message, isTCP, udpType]) =>
+ await createServer(createServerFn, host, port, message, isTCP, udpType),
+ );
+ });
+
+ afterAll((done) => {
+ Promise.all(endpoints).then((servers) => {
+ servers.forEach((server) => {
+ server.close();
+ server.unref();
+ });
+ done();
+ });
+ });
+
+ const bugDetectorDirectory = path.join(__dirname, "ssrf");
+ let fuzzTestBuilder;
+
+ describe("Not permitted connections", () => {
+ beforeEach(() => {
+ fuzzTestBuilder = new FuzzTestBuilder()
+ .dir(bugDetectorDirectory)
+ .fuzzFile("fuzz-http.js")
+ .runs(0)
+ .sync(false);
+ });
+
+ it("http.get(options, callback)", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("HttpGetOptionsCallback")
+ .build();
+ await expect(fuzzTest.executeWithPromise()).rejects.toThrowError(
+ FuzzingExitCode,
+ );
+ expect(fuzzTest.stderr).toContain(ssrfFindingMessage);
+ });
+
+ it("http.get(url, callback)", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("HttpGetUrlCallback")
+ .build();
+ await expect(fuzzTest.executeWithPromise()).rejects.toThrowError(
+ FuzzingExitCode,
+ );
+ expect(fuzzTest.stderr).toContain(ssrfFindingMessage);
+ });
+
+ it("http.get(url with no port, callback)", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("HttpGetUrlNoPort")
+ .build();
+ await expect(fuzzTest.executeWithPromise()).rejects.toThrowError(
+ FuzzingExitCode,
+ );
+ expect(fuzzTest.stderr).toContain(ssrfFindingMessage);
+ });
+
+ it("http.get(nothing, callback)", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("HttpGetUrlNoAnything")
+ .build();
+ await expect(fuzzTest.executeWithPromise()).rejects.toThrowError(
+ FuzzingExitCode,
+ );
+ expect(fuzzTest.stderr).toContain(ssrfFindingMessage);
+ });
+
+ it("http.request(options, callback)", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("HttpRequestOptionsCallback")
+ .build();
+ await expect(fuzzTest.executeWithPromise()).rejects.toThrowError(
+ FuzzingExitCode,
+ );
+ expect(fuzzTest.stderr).toContain(ssrfFindingMessage);
+ });
+
+ it("http.request(url, callback)", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("HttpRequestUrlCallback")
+ .build();
+ await expect(fuzzTest.executeWithPromise()).rejects.toThrowError(
+ FuzzingExitCode,
+ );
+ expect(fuzzTest.stderr).toContain(ssrfFindingMessage);
+ });
+
+ it("http.request(url with no port, callback)", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("HttpRequestUrlNoPort")
+ .build();
+ await expect(fuzzTest.executeWithPromise()).rejects.toThrowError(
+ FuzzingExitCode,
+ );
+ expect(fuzzTest.stderr).toContain(ssrfFindingMessage);
+ });
+
+ it("net.connect(port, host, callback)", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("netConnectPortHost")
+ .build();
+ await expect(fuzzTest.executeWithPromise()).rejects.toThrowError(
+ FuzzingExitCode,
+ );
+ expect(fuzzTest.stderr).toContain(ssrfFindingMessage);
+ });
+
+ it("net.connect(options, callback)", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("netConnectOptions")
+ .build();
+ await expect(fuzzTest.executeWithPromise()).rejects.toThrowError(
+ FuzzingExitCode,
+ );
+ expect(fuzzTest.stderr).toContain(ssrfFindingMessage);
+ });
+
+ it("net Socket.connect(port, host, callback)", async () => {
+ const fuzzTest = fuzzTestBuilder.fuzzEntryPoint("socketConnect").build();
+ await expect(fuzzTest.executeWithPromise()).rejects.toThrowError(
+ FuzzingExitCode,
+ );
+ expect(fuzzTest.stderr).toContain(ssrfFindingMessage);
+ });
+
+ it("net Socket.connect(options, callback)", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("socketConnectWithOptions")
+ .build();
+ await expect(fuzzTest.executeWithPromise()).rejects.toThrowError(
+ FuzzingExitCode,
+ );
+ expect(fuzzTest.stderr).toContain(ssrfFindingMessage);
+ });
+
+ it("tls.connect(options, callback)", async () => {
+ const fuzzTest = fuzzTestBuilder.fuzzEntryPoint("TlsConnect").build();
+ await expect(fuzzTest.executeWithPromise()).rejects.toThrowError(
+ FuzzingExitCode,
+ );
+ expect(fuzzTest.stderr).toContain(ssrfFindingMessage);
+ });
+
+ it("https.get(options, callback)", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("HttpsGetOptions")
+ .build();
+ await expect(fuzzTest.executeWithPromise()).rejects.toThrowError(
+ FuzzingExitCode,
+ );
+ expect(fuzzTest.stderr).toContain(ssrfFindingMessage);
+ });
+
+ it("http2.connect(options, callback)", async () => {
+ const fuzzTest = fuzzTestBuilder.fuzzEntryPoint("Http2Connect").build();
+ await expect(fuzzTest.executeWithPromise()).rejects.toThrowError(
+ FuzzingExitCode,
+ );
+ expect(fuzzTest.stderr).toContain(ssrfFindingMessage);
+ });
+
+ it("udp.connect(port, host, callback)", async () => {
+ const fuzzTest = fuzzTestBuilder.fuzzEntryPoint("udpConnect").build();
+ await expect(fuzzTest.executeWithPromise()).rejects.toThrowError(
+ FuzzingExitCode,
+ );
+ expect(fuzzTest.stderr).toContain(ssrfFindingMessage);
+ });
+
+ describe("Jest tests", () => {
+ beforeEach(() => {
+ fuzzTestBuilder = new FuzzTestBuilder()
+ .dir(bugDetectorDirectory)
+ .jestTestFile("tests.fuzz.js")
+ .sync(false);
+ });
+
+ it("net.connect(options, callback)", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .jestTestName("net.connect\\(options, callback\\)")
+ .build();
+ await expect(fuzzTest.executeWithPromise()).rejects.toThrowError(
+ JestRegressionExitCode,
+ );
+ expect(fuzzTest.stderr).toContain(ssrfFindingMessage);
+ });
+
+ it("udp.connect(port, host, callback)", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .jestTestName("udp.connect\\(port, host, callback\\)")
+ .build();
+ await expect(fuzzTest.executeWithPromise()).rejects.toThrowError(
+ JestRegressionExitCode,
+ );
+ expect(fuzzTest.stderr).toContain(ssrfFindingMessage);
+ });
+ });
+ });
+
+ describe("Permitted connections", () => {
+ beforeEach(() => {
+ fuzzTestBuilder = new FuzzTestBuilder()
+ .dir(bugDetectorDirectory)
+ .fuzzFile("fuzz-http.js")
+ .runs(1)
+ .customHooks([
+ path.join(bugDetectorDirectory, "allow-ok-ports.config.js"),
+ ])
+ .sync(false);
+ });
+
+ it("http.request", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("HttpRequestAllowed")
+ .build();
+ await fuzzTest.executeWithPromise();
+ expect(fuzzTest.stdout).toContain(okMessage);
+ });
+
+ it("http.get", async () => {
+ const fuzzTest = fuzzTestBuilder.fuzzEntryPoint("HttpGetAllowed").build();
+ await fuzzTest.executeWithPromise();
+ expect(fuzzTest.stdout).toContain(okMessage);
+ });
+
+ it("https.get", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("HttpsGetAllowed")
+ .build();
+ await fuzzTest.executeWithPromise();
+ expect(fuzzTest.stdout).toContain(okMessage);
+ });
+
+ it("http2.connect", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("Http2ConnectAllowed")
+ .build();
+ await fuzzTest.executeWithPromise();
+ expect(fuzzTest.stdout).toContain(okMessage);
+ });
+
+ it("net.connect", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("netConnectAllowed")
+ .build();
+ await fuzzTest.executeWithPromise();
+ expect(fuzzTest.stdout).toContain(okMessage);
+ });
+
+ it("udp.connect", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("udpConnectAllowed")
+ .build();
+ await fuzzTest.executeWithPromise();
+ expect(fuzzTest.stdout).toContain(okMessage);
+ });
+
+ it("udp.send connectionless", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("udpSendConnectionlessAllowed")
+ .build();
+ await fuzzTest.executeWithPromise();
+ expect(fuzzTest.stdout).toContain(okMessage);
+ });
+
+ it("udp.connect IPv6", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .fuzzEntryPoint("udpIPv6ConnectAllowed")
+ .build();
+ await fuzzTest.executeWithPromise();
+ expect(fuzzTest.stdout).toContain(okMessage);
+ });
+
+ describe("Jest tests", () => {
+ beforeEach(() => {
+ fuzzTestBuilder = new FuzzTestBuilder()
+ .dir(bugDetectorDirectory)
+ .jestTestFile("tests.fuzz.js")
+ .customHooks([
+ path.join(bugDetectorDirectory, "allow-ok-ports.config.js"),
+ ])
+ .sync(false);
+ });
+
+ it("http.request", async () => {
+ const fuzzTest = fuzzTestBuilder.jestTestName("http.request").build();
+ await expect(fuzzTest.executeWithPromise()).rejects.toThrowError(
+ JestRegressionExitCode,
+ );
+ expect(fuzzTest.stderr).toContain(okMessage);
+ });
+
+ it("udp.connect IPv6", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .jestTestName("udp.connect IPv6")
+ .build();
+ await expect(fuzzTest.executeWithPromise()).rejects.toThrowError(
+ JestRegressionExitCode,
+ );
+ expect(fuzzTest.stderr).toContain(okMessage);
+ });
+ });
+ });
+});
+async function createServer(
+ createServerFn,
+ host,
+ port,
+ message,
+ isTCP = true,
+ useIPv6 = false,
+) {
+ const options = {
+ key: fs.readFileSync(path.join(__dirname, "ssrf", "key.pem")),
+ cert: fs.readFileSync(path.join(__dirname, "ssrf", "cert.pem")),
+ port: port,
+ host: host,
+ };
+ let startedListening = false;
+ let server;
+
+ if (isTCP) {
+ server = createServerFn(options, (req, res) => {
+ res.writeHead(200, { "Content-Type": "text/plain" });
+ res.write(message);
+ res.end();
+ });
+
+ server.listen(port, host, () => {
+ startedListening = true;
+ });
+
+ server.on("connect", (req, socket, head) => {
+ console.log("connect");
+ });
+
+ process.on("uncaughtException", function (err) {
+ console.log(err);
+ });
+
+ server.on("close", () => {});
+
+ // wait for the server to start listening
+ while (!startedListening) {
+ // give away control to the event loop to prevent blocking
+ await new Promise((resolve) => setTimeout(resolve, 1));
+ }
+ } else {
+ // UDP
+ const udpType = useIPv6 ? "udp6" : "udp4";
+ server = createServerFn(udpType, (msg, rinfo) => {
+ server.send(message, rinfo.port, rinfo.address, (err) => {
+ if (err) {
+ console.log(err);
+ }
+ });
+ });
+ server.bind(options);
+ }
+
+ return server;
+}
diff --git a/tests/bug-detectors/ssrf/allow-ok-ports.config.js b/tests/bug-detectors/ssrf/allow-ok-ports.config.js
new file mode 100644
index 000000000..4217898e4
--- /dev/null
+++ b/tests/bug-detectors/ssrf/allow-ok-ports.config.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2026 Code Intelligence GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const {
+ getBugDetectorConfiguration,
+} = require("../../../packages/bug-detectors");
+
+const {
+ host,
+ hostIPv6,
+ okPort,
+ okPortHttps,
+ okPortIPv6,
+} = require("./connection-settings.js");
+
+getBugDetectorConfiguration("ssrf")
+ ?.addPermittedTCPConnection(host, okPort)
+ ?.addPermittedTCPConnection(host, okPortHttps)
+ ?.addPermittedUDPConnection(host, okPort)
+ ?.addPermittedUDPConnection(hostIPv6, okPortIPv6);
diff --git a/tests/bug-detectors/ssrf/cert.pem b/tests/bug-detectors/ssrf/cert.pem
new file mode 100644
index 000000000..4f2f81eb5
--- /dev/null
+++ b/tests/bug-detectors/ssrf/cert.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEGzCCAwOgAwIBAgIUbZz6FeUIaEKrRDlYAaiVain0i/kwDQYJKoZIhvcNAQEL
+BQAwgZwxCzAJBgNVBAYTAkRFMQwwCgYDVQQIDANOUlcxDTALBgNVBAcMBEJvbm4x
+GjAYBgNVBAoMEUNvZGUgSW50ZWxsaWdlbmNlMQwwCgYDVQQLDANkZXYxEjAQBgNV
+BAMMCWxvY2FsaG9zdDEyMDAGCSqGSIb3DQEJARYjcGV0ZXIuc2FtYXJpbkBjb2Rl
+LWludGVsbGlnZW5jZS5jb20wHhcNMjMwOTIxMTAxODAxWhcNMzMwOTE4MTAxODAx
+WjCBnDELMAkGA1UEBhMCREUxDDAKBgNVBAgMA05SVzENMAsGA1UEBwwEQm9ubjEa
+MBgGA1UECgwRQ29kZSBJbnRlbGxpZ2VuY2UxDDAKBgNVBAsMA2RldjESMBAGA1UE
+AwwJbG9jYWxob3N0MTIwMAYJKoZIhvcNAQkBFiNwZXRlci5zYW1hcmluQGNvZGUt
+aW50ZWxsaWdlbmNlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ALpnkI3RrdavEl7HS6Bt6c0GjbZxJHvNlYOk046xNBfDUZ1ndTOEZ7ymBJ0hOTj4
+Vlo7+KaX49ozZetKBf/qa39l++/GCeYsRgkvhoXv9i8CL6x8ZxCE6tATaSpKTadP
+zz8DzLdi1vFfpFqChrgvj27RKG9bvBAaVAIy2CueHDU3TkuFD6gz1TKKvfN09ENk
+2CfMWvmb1dEqurtmtfMHECOW24oIhD3LrZKWn2bw2dIj5HZ+GJV77IL2FYf7Gy/S
+2oWwKw4cS5D9MvJclc9nYcM1oJk7EyB0V3LEOGz71T0G3cXXD9FeWJ3QP0EciHJB
+AOIVw9VJbbTHv9kOnoreBJ8CAwEAAaNTMFEwHQYDVR0OBBYEFHacoIUOO+n6fhiG
+V06pQR/QIfwhMB8GA1UdIwQYMBaAFHacoIUOO+n6fhiGV06pQR/QIfwhMA8GA1Ud
+EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFeSN39NCD4yVx1ng7C6tIBl
+0urMoVny0rQjBzlVcxI1nMvmDeW5GslJ4OY9Dhl+SP2kp5XoR7s4bwhikP0NjgPv
+Z3HM5PPpcSsCt/8al9P1Rr0j8VFDby5IIKV1lR7Z7OfHe5MOFPF5JXmgypuU4TVx
+OF4wlwx0N8TG/iXsmC8LkW5EkgT56GDkLkbe/gp2BvjK3MgXMKC18lk/z/GnQQHp
+mXdwQCSx8+bJLWu2/X1lwP3XT8K73hYi58C1p0JRdS2Ryd7LDzxEIoAB1Ji1osBg
+RvYeCYv1yWjSN+YJp5NGxGRM9FRPNsIe0xv0r1s0o4uLPXs6CLir4gi8nn2F6xE=
+-----END CERTIFICATE-----
diff --git a/tests/bug-detectors/ssrf/connection-settings.js b/tests/bug-detectors/ssrf/connection-settings.js
new file mode 100644
index 000000000..983679b69
--- /dev/null
+++ b/tests/bug-detectors/ssrf/connection-settings.js
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2026 Code Intelligence GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+const host = "localhost";
+const hostIPv6 = "::1";
+
+const okPort = 8080;
+const okPortHttps = 8181;
+const notOkPort = 9090;
+const notOkPortHttps = 9191;
+
+const okPortIPv6 = 6060;
+
+const okMessage = "Connection allowed.";
+const notOkMessage = "SSRF sanitizer does not work!";
+const ssrfFindingMessage = "Server Side Request Forgery (SSRF)";
+
+module.exports = {
+ host,
+ hostIPv6,
+ okPort,
+ okPortHttps,
+ notOkPort,
+ notOkPortHttps,
+ okPortIPv6,
+ okMessage,
+ notOkMessage,
+ ssrfFindingMessage,
+};
diff --git a/tests/bug-detectors/ssrf/fuzz-http.js b/tests/bug-detectors/ssrf/fuzz-http.js
new file mode 100644
index 000000000..e6b09817e
--- /dev/null
+++ b/tests/bug-detectors/ssrf/fuzz-http.js
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2026 Code Intelligence GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+const dgram = require("dgram");
+const fs = require("fs");
+const http = require("http");
+const http2 = require("http2");
+const https = require("https");
+const net = require("net");
+const tls = require("tls");
+
+const {
+ host,
+ hostIPv6,
+ okPort,
+ okPortHttps,
+ okPortIPv6,
+ notOkPort,
+ notOkPortHttps,
+ okMessage,
+ notOkMessage,
+} = require("./connection-settings.js");
+
+const url = "http://" + host;
+const allowedUrlWithPort = url + ":" + okPort.toString();
+const allowedHttpsUrlWithPort =
+ "https://" + host + ":" + okPortHttps.toString();
+
+const notAllowedUrlWithPort = url + ":" + notOkPort.toString();
+
+module.exports.HttpGetOptionsCallback = async function (data) {
+ const options = {
+ host: host,
+ port: notOkPort,
+ path: "/HttpGetOptionsCallback",
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ };
+
+ let done = false;
+ http
+ .get(options, function (res) {
+ console.log(notOkMessage);
+ done = true;
+ })
+ .end();
+};
+
+module.exports.HttpGetUrlCallback = async function (data) {
+ http
+ .get(notAllowedUrlWithPort + "/HttpGetUrlCallback", function (res) {
+ console.log(notOkMessage);
+ })
+ .end();
+};
+
+module.exports.HttpGetUrlNoPort = function (data) {
+ http
+ .get(url + "/HttpGetUrlNoPort", function (res) {
+ console.log(notOkMessage);
+ })
+ .end();
+};
+
+module.exports.HttpGetUrlNoAnything = function (data) {
+ http
+ .get({}, function (res) {
+ console.log(notOkMessage);
+ })
+ .end();
+};
+
+module.exports.HttpRequestOptionsCallback = function (data) {
+ const options = {
+ host: host,
+ port: notOkPort,
+ path: "/HttpRequestOptionsCallback",
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ };
+
+ http
+ .request(options, function (res) {
+ console.log(notOkMessage);
+ })
+ .end();
+};
+
+module.exports.HttpRequestUrlCallback = function (data) {
+ http
+ .request(notAllowedUrlWithPort + "/HttpRequestUrlCallback", function (res) {
+ console.log(notOkMessage);
+ })
+ .end();
+};
+
+module.exports.HttpRequestUrlNoPort = function (data) {
+ http
+ .request(url + "/HttpRequestUrlNoPort", function (res) {
+ console.log(notOkMessage);
+ })
+ .end();
+};
+
+module.exports.netConnectPortHost = async function (data) {
+ net.connect(notOkPort, host, function () {
+ console.log(notOkMessage);
+ });
+};
+
+module.exports.netConnectOptions = async function (data) {
+ const options = {
+ host: host,
+ port: notOkPort,
+ };
+ net.connect(options, function () {
+ console.log(notOkMessage);
+ });
+};
+
+module.exports.socketConnect = async function (data) {
+ const socket = new net.Socket();
+ socket.connect(notOkPort, host, function () {
+ console.log(notOkMessage);
+ });
+};
+
+module.exports.socketConnectWithOptions = async function (data) {
+ const options = {
+ host: host,
+ port: notOkPort,
+ };
+ const socket = new net.Socket();
+ socket.connect(options, function () {
+ console.log(notOkMessage);
+ });
+};
+
+module.exports.TlsConnect = async function (data) {
+ const options = {
+ ca: [fs.readFileSync("cert.pem")],
+ host: host,
+ port: notOkPortHttps,
+ };
+ try {
+ tls
+ .connect(options, function (res) {
+ console.log(notOkMessage);
+ })
+ .end();
+ } catch (e) {
+ console.log(e);
+ }
+};
+
+module.exports.HttpsGetOptions = async function (data) {
+ let output = "";
+ let done = false;
+ const options = {
+ ca: [fs.readFileSync("cert.pem")],
+ host: host,
+ port: notOkPortHttps,
+ path: "/" + "HttpsGetOptions",
+ };
+ https
+ .get(options, function (res) {
+ res.on("data", function (d) {
+ output += d;
+ });
+ res.on("end", function () {
+ console.log(output);
+ done = true;
+ });
+ })
+ .end();
+};
+
+module.exports.Http2Connect = async function (data) {
+ const options = {};
+ let output = "";
+ let done = false;
+ http2.connect(notAllowedUrlWithPort, options, function (res) {
+ res.on("data", function (d) {
+ output += d;
+ });
+ res.on("end", function () {
+ console.log(output);
+ done = true;
+ });
+ });
+};
+
+module.exports.udpConnect = async function (data) {
+ const client = dgram.createSocket("udp4");
+ client.connect(notOkPort, host, function (err) {
+ client.send("hello!", (err) => {
+ // receive a message from the server
+ client.on("message", function (msg, info) {
+ console.log("Data received from server : " + msg.toString());
+ console.log(
+ "Received %d bytes from %s:%d\n",
+ msg.length,
+ info.address,
+ info.port,
+ );
+ client.close();
+ });
+ });
+ });
+};
+
+module.exports.HttpRequestAllowed = async function (data) {
+ // Options to be used by request
+ const options = {
+ host: "",
+ port: okPort,
+ path: "/HttpRequestAllowed",
+ };
+ let output = "";
+ let done = false;
+ http
+ .request(options, function (res) {
+ res.on("data", function (d) {
+ output += d;
+ });
+ res.on("end", function () {
+ console.log(output);
+ done = true;
+ });
+ })
+ .end();
+};
+
+module.exports.HttpGetAllowed = async function (data) {
+ let output = "";
+ let done = false;
+ http
+ .get(allowedUrlWithPort + "/HttpGetAllowed", function (res) {
+ res.on("data", function (d) {
+ output += d;
+ });
+ res.on("end", function () {
+ console.log(output);
+ done = true;
+ });
+ })
+ .end();
+};
+
+module.exports.HttpsGetAllowed = async function (data) {
+ let output = "";
+ let done = false;
+ const options = {
+ ca: [fs.readFileSync("cert.pem")],
+ host: host,
+ port: okPortHttps,
+ path: "/HttpsGetAllowed",
+ };
+ https
+ .get(options, function (res) {
+ res.on("data", function (d) {
+ output += d;
+ });
+ res.on("end", function () {
+ console.log(output);
+ done = true;
+ });
+ })
+ .end();
+};
+
+module.exports.Http2ConnectAllowed = async function (data) {
+ // Not sure why this particular protocol wants http:// instead of https://
+ http2.connect(url + ":" + okPortHttps, {}, function (res) {
+ console.log(okMessage);
+ });
+};
+
+module.exports.netConnectAllowed = async function (data) {
+ net
+ .connect(okPort, host, function (res) {
+ console.log(okMessage);
+ })
+ .end();
+};
+
+module.exports.udpConnectAllowed = async function (data) {
+ const client = dgram.createSocket("udp4");
+ client.connect(okPort, host, function (err) {
+ client.send("hello!", (err) => {
+ // receive a message from the server
+ client.on("message", function (msg, info) {
+ console.log("Data received from server : " + msg.toString());
+ console.log(
+ "Received %d bytes from %s:%d\n",
+ msg.length,
+ info.address,
+ info.port,
+ );
+ client.close();
+ });
+ });
+ });
+};
+
+module.exports.udpSendConnectionlessAllowed = async function (data) {
+ const client = dgram.createSocket("udp4");
+ client.send("hello!", okPort, host, (err) => {
+ // receive a message from the server
+ client.on("message", function (msg, info) {
+ console.log("Data received from server : " + msg.toString());
+ console.log(
+ "Received %d bytes from %s:%d\n",
+ msg.length,
+ info.address,
+ info.port,
+ );
+ client.close();
+ });
+ });
+};
+
+module.exports.udpIPv6ConnectAllowed = async function (data) {
+ const client = dgram.createSocket("udp6");
+ client.connect(6060, hostIPv6, function (err) {
+ client.send("hello!", (err) => {
+ // receive a message from the server
+ client.on("message", function (msg, info) {
+ console.log("Data received from server : " + msg.toString());
+ console.log(
+ "Received %d bytes from %s:%d\n",
+ msg.length,
+ info.address,
+ info.port,
+ );
+ client.close();
+ });
+ });
+ });
+};
diff --git a/tests/bug-detectors/ssrf/key.pem b/tests/bug-detectors/ssrf/key.pem
new file mode 100644
index 000000000..a6b27d350
--- /dev/null
+++ b/tests/bug-detectors/ssrf/key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC6Z5CN0a3WrxJe
+x0ugbenNBo22cSR7zZWDpNOOsTQXw1GdZ3UzhGe8pgSdITk4+FZaO/iml+PaM2Xr
+SgX/6mt/ZfvvxgnmLEYJL4aF7/YvAi+sfGcQhOrQE2kqSk2nT88/A8y3YtbxX6Ra
+goa4L49u0ShvW7wQGlQCMtgrnhw1N05LhQ+oM9Uyir3zdPRDZNgnzFr5m9XRKrq7
+ZrXzBxAjltuKCIQ9y62Slp9m8NnSI+R2fhiVe+yC9hWH+xsv0tqFsCsOHEuQ/TLy
+XJXPZ2HDNaCZOxMgdFdyxDhs+9U9Bt3F1w/RXlid0D9BHIhyQQDiFcPVSW20x7/Z
+Dp6K3gSfAgMBAAECggEAXSfEphtTtSZpF9ShhttnLH9J8xM4GGb1gYSt9XG5hual
+svQxLj3NWgnd5GjmIAJ7pTyzVw4xYKqvFJc5yFtuvYxKC9n8uHsHxS9rGySA8500
+Fg9Vsnu6naIVvHzFsgfAms1bUYqjwJz7lgAFM6cRF2CPxJcjtShzM2YVgjbSAgV3
+HGjrFDLsv5U9DtKI3uEzV1ArTzhVjirSDh0IcBVZCwFewrOfaMP3Vf8T2LcdIpGK
+gnpzPi75AXraZSBR3HheEKg/4vs7I73uiC3lQKzIITEdQxwARCgOLD8gW0aFFikt
+TnycO8qudWNx8YmdfRsAHsKhiee+iwT+LihYn8p6gQKBgQDkaQDt7pu4nTAdoJZX
+dM2lEcf1s2Q4O5N4WdU0CjIhD61Q36KRA86Zbpc741m7zSu/VmUn+8Y+FZPL3/S2
+KbbJ5QmXbNGCqN0yge/EVPY1vw3lfNYoI3QkSS9izUhc/bS6BIzDZrkFUw5pDH03
+eJrMKKZwLIR+yzwSkMWew57NPQKBgQDQ66U24gEn0b4zfSS2Lu8Zoc7ZVfJLXk+Y
++oZzbMnbcMBR+ytHq8SM3yn1JjWGHp3/s2FuOCUN+GvzHT+eM61NtjylTQoEkaMM
+Ra6e1virWB+9NDVeSxlRpMmjBJJTYVndyTd0nt4F4PDNaY7Q3DGLsMi+PQTmAufG
+ZR+NCKEvCwKBgESUFlhZ5N1YLKMonRsjEb93CD+IHhYYJR3kcvQN/6EXkOUQUEIU
+D4rXvoaXq1CMuI7ZRMPtf0cSuW5kDphHC/+wSeHyJTGCu+83PiMHk2jttSFrCu3A
+P1XJt3WFxy1Ma1/Sj+T3SaQEnPYDbvEhv/B+YAKcCyf6o027s+oIN/zNAoGAejO7
+2dRslJwMwxVKKf5eAQIyedHZ/dfWe0be6hkSIXdcJxfhgvSn7TaD1k9ZM3ApPu3v
+6YaRthA/JF9RXPohPrl/07iySWXel0kTEPnxTlgniIZHSTZoQuc+wknkRT1GUYJn
+G6HpgErIz34U+XoyyODJKu2KNfgxFk0EHXyUu20CgYArWPDCxhMcgXdcgocFeC88
+UcDEsxKlAhYazP4BIN29FfGFKeR+DPKUsfoxSM4dvSd86NJFeSoLoLoIk+Tpe3TD
+hPFl33RSs2W1Z8kGsT7vsr02s/TdOO4SctU5SpRW8jBvbCGpn+1m1jSWQSr2nhOV
+LfgfOMEdHdpisk7wuLt2JA==
+-----END PRIVATE KEY-----
diff --git a/tests/bug-detectors/ssrf/package.json b/tests/bug-detectors/ssrf/package.json
new file mode 100644
index 000000000..590d48f14
--- /dev/null
+++ b/tests/bug-detectors/ssrf/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "jazzerjs-ssrf-tests",
+ "version": "1.0.0",
+ "description": "Tests for the SSRF bug detector",
+ "scripts": {
+ "test": "jest",
+ "fuzz": "JAZZER_FUZZ=1 jest"
+ },
+ "devDependencies": {
+ "@jazzer.js/jest-runner": "file:../../packages/jest-runner",
+ "eslint-plugin-jest": "^27.1.3"
+ },
+ "jest": {
+ "projects": [
+ {
+ "testRunner": "@jazzer.js/jest-runner",
+ "displayName": {
+ "name": "Jazzer.js",
+ "color": "cyan"
+ },
+ "testMatch": [
+ "/**/*.fuzz.js"
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/bug-detectors/ssrf/tests.fuzz.js b/tests/bug-detectors/ssrf/tests.fuzz.js
new file mode 100644
index 000000000..6060f5fa0
--- /dev/null
+++ b/tests/bug-detectors/ssrf/tests.fuzz.js
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2026 Code Intelligence GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+const targets = require("./fuzz-http");
+
+it.fuzz("http.request", async (data) => {
+ return targets.HttpRequestAllowed(data);
+});
+
+it.fuzz("udp.connect IPv6", async (data) => {
+ return targets.udpIPv6ConnectAllowed(data);
+});
+
+it.fuzz("net.connect(options, callback)", async (data) => {
+ return targets.netConnectOptions(data);
+});
+
+it.fuzz("udp.connect(port, host, callback)", async (data) => {
+ return targets.udpConnect(data);
+});
diff --git a/tests/code_coverage/coverage.test.js b/tests/code_coverage/coverage.test.js
index 2487f7bac..0d18f1dba 100644
--- a/tests/code_coverage/coverage.test.js
+++ b/tests/code_coverage/coverage.test.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -194,6 +194,7 @@ function executeJestRunner(
if (useCustomHooks) {
config.customHooks = useCustomHooks;
}
+ config.disableBugDetectors = [".*"];
// write the config file, overwriting any existing one
fs.writeFileSync(
path.join(testDirectory, ".jazzerjsrc.json"),
@@ -248,6 +249,8 @@ function executeFuzzTest(
options.push("--cov_dir");
options.push(coverageOutputDir);
}
+
+ options.push("--disableBugDetectors='.*'");
options.push("--");
options.push("-runs=0");
const process = spawnSync("npx", options, {
diff --git a/tests/code_coverage/sample_fuzz_test/codeCoverage.fuzz.js b/tests/code_coverage/sample_fuzz_test/codeCoverage.fuzz.js
index 191d5439c..23ceaf350 100644
--- a/tests/code_coverage/sample_fuzz_test/codeCoverage.fuzz.js
+++ b/tests/code_coverage/sample_fuzz_test/codeCoverage.fuzz.js
@@ -1,18 +1,4 @@
-/*
- * Copyright 2023 Code Intelligence GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+/* eslint-disable header/header */
const target = require("./fuzz.js");
diff --git a/tests/code_coverage/sample_fuzz_test/custom-hooks.js b/tests/code_coverage/sample_fuzz_test/custom-hooks.js
index 5b88def16..e6b86518a 100644
--- a/tests/code_coverage/sample_fuzz_test/custom-hooks.js
+++ b/tests/code_coverage/sample_fuzz_test/custom-hooks.js
@@ -1,18 +1,4 @@
-/*
- * Copyright 2023 Code Intelligence GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+/* eslint-disable header/header */
const { registerReplaceHook } = require("@jazzer.js/hooking");
diff --git a/tests/code_coverage/sample_fuzz_test/expected_coverage/fuzz+lib+codeCoverage-fuzz.json b/tests/code_coverage/sample_fuzz_test/expected_coverage/fuzz+lib+codeCoverage-fuzz.json
index 1d66342b0..a83bb493f 100644
--- a/tests/code_coverage/sample_fuzz_test/expected_coverage/fuzz+lib+codeCoverage-fuzz.json
+++ b/tests/code_coverage/sample_fuzz_test/expected_coverage/fuzz+lib+codeCoverage-fuzz.json
@@ -1,47 +1,48 @@
{
"codeCoverage.fuzz.js": {
+ "path": "/home/peter/Documents/Programming/jazzer.js/tests/code_coverage/sample_fuzz_test/codeCoverage.fuzz.js",
"statementMap": {
"0": {
- "start": { "line": 17, "column": 15 },
- "end": { "line": 17, "column": 35 }
+ "start": { "line": 3, "column": 15 },
+ "end": { "line": 3, "column": 35 }
},
"1": {
- "start": { "line": 19, "column": 0 },
- "end": { "line": 23, "column": 3 }
+ "start": { "line": 5, "column": 0 },
+ "end": { "line": 9, "column": 3 }
},
"2": {
- "start": { "line": 20, "column": 1 },
- "end": { "line": 22, "column": 4 }
+ "start": { "line": 6, "column": 1 },
+ "end": { "line": 8, "column": 4 }
},
"3": {
- "start": { "line": 21, "column": 2 },
- "end": { "line": 21, "column": 20 }
+ "start": { "line": 7, "column": 2 },
+ "end": { "line": 7, "column": 20 }
}
},
"fnMap": {
"0": {
"name": "(anonymous_0)",
"decl": {
- "start": { "line": 19, "column": 24 },
- "end": { "line": 19, "column": 25 }
+ "start": { "line": 5, "column": 24 },
+ "end": { "line": 5, "column": 25 }
},
"loc": {
- "start": { "line": 19, "column": 30 },
- "end": { "line": 23, "column": 1 }
+ "start": { "line": 5, "column": 30 },
+ "end": { "line": 9, "column": 1 }
},
- "line": 19
+ "line": 5
},
"1": {
"name": "(anonymous_1)",
"decl": {
- "start": { "line": 20, "column": 25 },
- "end": { "line": 20, "column": 26 }
+ "start": { "line": 6, "column": 25 },
+ "end": { "line": 6, "column": 26 }
},
"loc": {
- "start": { "line": 20, "column": 35 },
- "end": { "line": 22, "column": 2 }
+ "start": { "line": 6, "column": 35 },
+ "end": { "line": 8, "column": 2 }
},
- "line": 20
+ "line": 6
}
},
"branchMap": {},
@@ -49,136 +50,140 @@
"f": { "0": 1, "1": 3 },
"b": {},
"_coverageSchema": "1a1c01bbd47fc00a2c39e90264f33305004495a9",
- "hash": "25c01ffa3552de53ae353b8e557c73461d766e51"
+ "hash": "cb38b1e488af765571e6967998c49d18aff66c76"
},
"fuzz.js": {
+ "path": "/home/peter/Documents/Programming/jazzer.js/tests/code_coverage/sample_fuzz_test/fuzz.js",
"statementMap": {
"0": {
- "start": { "line": 17, "column": 12 },
- "end": { "line": 17, "column": 28 }
+ "start": { "line": 3, "column": 12 },
+ "end": { "line": 3, "column": 28 }
},
"1": {
- "start": { "line": 22, "column": 0 },
- "end": { "line": 28, "column": 2 }
+ "start": { "line": 8, "column": 0 },
+ "end": { "line": 14, "column": 2 }
},
"2": {
- "start": { "line": 23, "column": 1 },
- "end": { "line": 23, "column": 41 }
+ "start": { "line": 9, "column": 1 },
+ "end": { "line": 9, "column": 41 }
},
"3": {
- "start": { "line": 24, "column": 1 },
- "end": { "line": 26, "column": 2 }
+ "start": { "line": 10, "column": 1 },
+ "end": { "line": 12, "column": 2 }
},
"4": {
- "start": { "line": 25, "column": 2 },
- "end": { "line": 25, "column": 9 }
+ "start": { "line": 11, "column": 2 },
+ "end": { "line": 11, "column": 9 }
},
"5": {
- "start": { "line": 27, "column": 1 },
- "end": { "line": 27, "column": 18 }
+ "start": { "line": 13, "column": 1 },
+ "end": { "line": 13, "column": 18 }
}
},
"fnMap": {
"0": {
"name": "(anonymous_0)",
"decl": {
- "start": { "line": 22, "column": 22 },
- "end": { "line": 22, "column": 23 }
+ "start": { "line": 8, "column": 22 },
+ "end": { "line": 8, "column": 23 }
},
"loc": {
- "start": { "line": 22, "column": 38 },
- "end": { "line": 28, "column": 1 }
+ "start": { "line": 8, "column": 38 },
+ "end": { "line": 14, "column": 1 }
},
- "line": 22
+ "line": 8
}
},
"branchMap": {
"0": {
"loc": {
- "start": { "line": 24, "column": 1 },
- "end": { "line": 26, "column": 2 }
+ "start": { "line": 10, "column": 1 },
+ "end": { "line": 12, "column": 2 }
},
"type": "if",
"locations": [
{
- "start": { "line": 24, "column": 1 },
- "end": { "line": 26, "column": 2 }
+ "start": { "line": 10, "column": 1 },
+ "end": { "line": 12, "column": 2 }
},
{
- "start": { "line": 24, "column": 1 },
- "end": { "line": 26, "column": 2 }
+ "start": { "line": 10, "column": 1 },
+ "end": { "line": 12, "column": 2 }
}
],
- "line": 24
+ "line": 10
}
},
"s": { "0": 1, "1": 1, "2": 3, "3": 3, "4": 2, "5": 1 },
"f": { "0": 3 },
"b": { "0": [2, 1] },
+ "inputSourceMap": null,
"_coverageSchema": "1a1c01bbd47fc00a2c39e90264f33305004495a9",
- "hash": "d5b411e8de7efcd2798a7cd78efd7bd8347f647a"
+ "hash": "919965dfc96b474e5bb4bd686708056c565cd2df"
},
"lib.js": {
+ "path": "/home/peter/Documents/Programming/jazzer.js/tests/code_coverage/sample_fuzz_test/lib.js",
"statementMap": {
"0": {
- "start": { "line": 18, "column": 1 },
- "end": { "line": 18, "column": 29 }
+ "start": { "line": 4, "column": 1 },
+ "end": { "line": 4, "column": 29 }
},
"1": {
- "start": { "line": 19, "column": 1 },
- "end": { "line": 21, "column": 2 }
+ "start": { "line": 5, "column": 1 },
+ "end": { "line": 7, "column": 2 }
},
"2": {
- "start": { "line": 20, "column": 2 },
- "end": { "line": 20, "column": 11 }
+ "start": { "line": 6, "column": 2 },
+ "end": { "line": 6, "column": 11 }
},
"3": {
- "start": { "line": 22, "column": 1 },
- "end": { "line": 22, "column": 11 }
+ "start": { "line": 8, "column": 1 },
+ "end": { "line": 8, "column": 11 }
},
"4": {
- "start": { "line": 25, "column": 0 },
- "end": { "line": 27, "column": 2 }
+ "start": { "line": 11, "column": 0 },
+ "end": { "line": 13, "column": 2 }
}
},
"fnMap": {
"0": {
"name": "foo",
"decl": {
- "start": { "line": 17, "column": 9 },
- "end": { "line": 17, "column": 12 }
+ "start": { "line": 3, "column": 9 },
+ "end": { "line": 3, "column": 12 }
},
"loc": {
- "start": { "line": 17, "column": 16 },
- "end": { "line": 23, "column": 1 }
+ "start": { "line": 3, "column": 16 },
+ "end": { "line": 9, "column": 1 }
},
- "line": 17
+ "line": 3
}
},
"branchMap": {
"0": {
"loc": {
- "start": { "line": 19, "column": 1 },
- "end": { "line": 21, "column": 2 }
+ "start": { "line": 5, "column": 1 },
+ "end": { "line": 7, "column": 2 }
},
"type": "if",
"locations": [
{
- "start": { "line": 19, "column": 1 },
- "end": { "line": 21, "column": 2 }
+ "start": { "line": 5, "column": 1 },
+ "end": { "line": 7, "column": 2 }
},
{
- "start": { "line": 19, "column": 1 },
- "end": { "line": 21, "column": 2 }
+ "start": { "line": 5, "column": 1 },
+ "end": { "line": 7, "column": 2 }
}
],
- "line": 19
+ "line": 5
}
},
"s": { "0": 1, "1": 1, "2": 1, "3": 0, "4": 1 },
"f": { "0": 1 },
"b": { "0": [1, 0] },
+ "inputSourceMap": null,
"_coverageSchema": "1a1c01bbd47fc00a2c39e90264f33305004495a9",
- "hash": "9606a42b6e4a5e9a5c23554dda63403d86a4a9a2"
+ "hash": "fcd40034890333ddc0be68a932be368882a3d10b"
}
}
diff --git a/tests/code_coverage/sample_fuzz_test/expected_coverage/fuzz+lib+customHooks.json b/tests/code_coverage/sample_fuzz_test/expected_coverage/fuzz+lib+customHooks.json
index 92b89d35c..430e12f35 100644
--- a/tests/code_coverage/sample_fuzz_test/expected_coverage/fuzz+lib+customHooks.json
+++ b/tests/code_coverage/sample_fuzz_test/expected_coverage/fuzz+lib+customHooks.json
@@ -1,31 +1,32 @@
{
"custom-hooks.js": {
+ "path": "/home/peter/Documents/Programming/jazzer.js/tests/code_coverage/sample_fuzz_test/custom-hooks.js",
"statementMap": {
"0": {
- "start": { "line": 17, "column": 32 },
- "end": { "line": 17, "column": 61 }
+ "start": { "line": 3, "column": 32 },
+ "end": { "line": 3, "column": 61 }
},
"1": {
- "start": { "line": 19, "column": 0 },
- "end": { "line": 21, "column": 3 }
+ "start": { "line": 5, "column": 0 },
+ "end": { "line": 7, "column": 3 }
},
"2": {
- "start": { "line": 20, "column": 1 },
- "end": { "line": 20, "column": 37 }
+ "start": { "line": 6, "column": 1 },
+ "end": { "line": 6, "column": 37 }
}
},
"fnMap": {
"0": {
"name": "(anonymous_0)",
"decl": {
- "start": { "line": 19, "column": 41 },
- "end": { "line": 19, "column": 42 }
+ "start": { "line": 5, "column": 41 },
+ "end": { "line": 5, "column": 42 }
},
"loc": {
- "start": { "line": 19, "column": 47 },
- "end": { "line": 21, "column": 1 }
+ "start": { "line": 5, "column": 47 },
+ "end": { "line": 7, "column": 1 }
},
- "line": 19
+ "line": 5
}
},
"branchMap": {},
@@ -33,130 +34,132 @@
"f": { "0": 1 },
"b": {},
"_coverageSchema": "1a1c01bbd47fc00a2c39e90264f33305004495a9",
- "hash": "7ee4d96bd07f3609d51855142c39faa2adf6ab0a"
+ "hash": "0050adbd727053788c80c09d103e1ce556304b88"
},
"fuzz.js": {
+ "path": "/home/peter/Documents/Programming/jazzer.js/tests/code_coverage/sample_fuzz_test/fuzz.js",
"statementMap": {
"0": {
- "start": { "line": 17, "column": 12 },
- "end": { "line": 17, "column": 28 }
+ "start": { "line": 3, "column": 12 },
+ "end": { "line": 3, "column": 28 }
},
"1": {
- "start": { "line": 22, "column": 0 },
- "end": { "line": 28, "column": 2 }
+ "start": { "line": 8, "column": 0 },
+ "end": { "line": 14, "column": 2 }
},
"2": {
- "start": { "line": 23, "column": 1 },
- "end": { "line": 23, "column": 41 }
+ "start": { "line": 9, "column": 1 },
+ "end": { "line": 9, "column": 41 }
},
"3": {
- "start": { "line": 24, "column": 1 },
- "end": { "line": 26, "column": 2 }
+ "start": { "line": 10, "column": 1 },
+ "end": { "line": 12, "column": 2 }
},
"4": {
- "start": { "line": 25, "column": 2 },
- "end": { "line": 25, "column": 9 }
+ "start": { "line": 11, "column": 2 },
+ "end": { "line": 11, "column": 9 }
},
"5": {
- "start": { "line": 27, "column": 1 },
- "end": { "line": 27, "column": 18 }
+ "start": { "line": 13, "column": 1 },
+ "end": { "line": 13, "column": 18 }
}
},
"fnMap": {
"0": {
"name": "(anonymous_0)",
"decl": {
- "start": { "line": 22, "column": 22 },
- "end": { "line": 22, "column": 23 }
+ "start": { "line": 8, "column": 22 },
+ "end": { "line": 8, "column": 23 }
},
"loc": {
- "start": { "line": 22, "column": 38 },
- "end": { "line": 28, "column": 1 }
+ "start": { "line": 8, "column": 38 },
+ "end": { "line": 14, "column": 1 }
},
- "line": 22
+ "line": 8
}
},
"branchMap": {
"0": {
"loc": {
- "start": { "line": 24, "column": 1 },
- "end": { "line": 26, "column": 2 }
+ "start": { "line": 10, "column": 1 },
+ "end": { "line": 12, "column": 2 }
},
"type": "if",
"locations": [
{
- "start": { "line": 24, "column": 1 },
- "end": { "line": 26, "column": 2 }
+ "start": { "line": 10, "column": 1 },
+ "end": { "line": 12, "column": 2 }
},
{ "start": {}, "end": {} }
],
- "line": 24
+ "line": 10
}
},
"s": { "0": 1, "1": 1, "2": 3, "3": 3, "4": 2, "5": 1 },
"f": { "0": 3 },
"b": { "0": [2, 1] },
"_coverageSchema": "1a1c01bbd47fc00a2c39e90264f33305004495a9",
- "hash": "d5b411e8de7efcd2798a7cd78efd7bd8347f647a"
+ "hash": "5d5860b26158df2154cfe4eb4255dc6534ccfff1"
},
"lib.js": {
+ "path": "/home/peter/Documents/Programming/jazzer.js/tests/code_coverage/sample_fuzz_test/lib.js",
"statementMap": {
"0": {
- "start": { "line": 18, "column": 1 },
- "end": { "line": 18, "column": 29 }
+ "start": { "line": 4, "column": 1 },
+ "end": { "line": 4, "column": 29 }
},
"1": {
- "start": { "line": 19, "column": 1 },
- "end": { "line": 21, "column": 2 }
+ "start": { "line": 5, "column": 1 },
+ "end": { "line": 7, "column": 2 }
},
"2": {
- "start": { "line": 20, "column": 2 },
- "end": { "line": 20, "column": 11 }
+ "start": { "line": 6, "column": 2 },
+ "end": { "line": 6, "column": 11 }
},
"3": {
- "start": { "line": 22, "column": 1 },
- "end": { "line": 22, "column": 11 }
+ "start": { "line": 8, "column": 1 },
+ "end": { "line": 8, "column": 11 }
},
"4": {
- "start": { "line": 25, "column": 0 },
- "end": { "line": 27, "column": 2 }
+ "start": { "line": 11, "column": 0 },
+ "end": { "line": 13, "column": 2 }
}
},
"fnMap": {
"0": {
"name": "foo",
"decl": {
- "start": { "line": 17, "column": 9 },
- "end": { "line": 17, "column": 12 }
+ "start": { "line": 3, "column": 9 },
+ "end": { "line": 3, "column": 12 }
},
"loc": {
- "start": { "line": 17, "column": 16 },
- "end": { "line": 23, "column": 1 }
+ "start": { "line": 3, "column": 16 },
+ "end": { "line": 9, "column": 1 }
},
- "line": 17
+ "line": 3
}
},
"branchMap": {
"0": {
"loc": {
- "start": { "line": 19, "column": 1 },
- "end": { "line": 21, "column": 2 }
+ "start": { "line": 5, "column": 1 },
+ "end": { "line": 7, "column": 2 }
},
"type": "if",
"locations": [
{
- "start": { "line": 19, "column": 1 },
- "end": { "line": 21, "column": 2 }
+ "start": { "line": 5, "column": 1 },
+ "end": { "line": 7, "column": 2 }
},
{ "start": {}, "end": {} }
],
- "line": 19
+ "line": 5
}
},
"s": { "0": 0, "1": 0, "2": 0, "3": 0, "4": 1 },
"f": { "0": 0 },
"b": { "0": [0, 0] },
"_coverageSchema": "1a1c01bbd47fc00a2c39e90264f33305004495a9",
- "hash": "9606a42b6e4a5e9a5c23554dda63403d86a4a9a2"
+ "hash": "2c8e6fbf7fbf1d3facf8b6f7aeed0de7b31a4877"
}
}
diff --git a/tests/code_coverage/sample_fuzz_test/expected_coverage/fuzz+lib+otherCodeCoverage-fuzz.json b/tests/code_coverage/sample_fuzz_test/expected_coverage/fuzz+lib+otherCodeCoverage-fuzz.json
index b4283dd16..b22b28390 100644
--- a/tests/code_coverage/sample_fuzz_test/expected_coverage/fuzz+lib+otherCodeCoverage-fuzz.json
+++ b/tests/code_coverage/sample_fuzz_test/expected_coverage/fuzz+lib+otherCodeCoverage-fuzz.json
@@ -1,193 +1,1501 @@
{
- "otherCodeCoverage.fuzz.ts": {
+ "fuzz.ts": {
+ "path": "/home/peter/Documents/Programming/jazzer.js/packages/jest-runner/fuzz.ts",
"statementMap": {
"0": {
- "start": { "line": 17, "column": 0 },
- "end": { "line": 17, "column": 32 }
+ "start": { "line": 9, "column": 0 },
+ "end": { "line": 9, "column": null }
},
"1": {
- "start": { "line": 18, "column": 0 },
- "end": { "line": 18, "column": 33 }
+ "start": { "line": 13, "column": 0 },
+ "end": { "line": 13, "column": null }
},
"2": {
- "start": { "line": 20, "column": 0 },
- "end": { "line": 24, "column": 3 }
+ "start": { "line": 27, "column": 0 },
+ "end": { "line": 27, "column": null }
},
"3": {
- "start": { "line": 21, "column": 1 },
- "end": { "line": 23, "column": 4 }
+ "start": { "line": 28, "column": 0 },
+ "end": { "line": 28, "column": null }
},
"4": {
- "start": { "line": 22, "column": 2 },
- "end": { "line": 22, "column": 13 }
+ "start": { "line": 31, "column": 0 },
+ "end": { "line": 31, "column": 13 }
+ },
+ "5": {
+ "start": { "line": 40, "column": 2 },
+ "end": { "line": 44, "column": 2 }
+ },
+ "6": {
+ "start": { "line": 40, "column": 30 },
+ "end": { "line": 44, "column": 2 }
+ },
+ "7": {
+ "start": { "line": 41, "column": 2 },
+ "end": { "line": 43, "column": null }
+ },
+ "8": {
+ "start": { "line": 42, "column": 3 },
+ "end": { "line": 42, "column": null }
+ },
+ "9": {
+ "start": { "line": 39, "column": 13 },
+ "end": { "line": 39, "column": null }
+ },
+ "10": {
+ "start": { "line": 49, "column": 27 },
+ "end": { "line": 49, "column": 50 }
+ },
+ "11": {
+ "start": { "line": 50, "column": 1 },
+ "end": { "line": 65, "column": null }
+ },
+ "12": {
+ "start": { "line": 51, "column": 2 },
+ "end": { "line": 64, "column": null }
+ },
+ "13": {
+ "start": { "line": 55, "column": 3 },
+ "end": { "line": 63, "column": null }
+ },
+ "14": {
+ "start": { "line": 56, "column": 31 },
+ "end": { "line": 56, "column": 56 }
+ },
+ "15": {
+ "start": { "line": 57, "column": 4 },
+ "end": { "line": 57, "column": null }
+ },
+ "16": {
+ "start": { "line": 58, "column": 10 },
+ "end": { "line": 63, "column": null }
+ },
+ "17": {
+ "start": { "line": 59, "column": 31 },
+ "end": { "line": 59, "column": 56 }
+ },
+ "18": {
+ "start": { "line": 60, "column": 4 },
+ "end": { "line": 60, "column": null }
+ },
+ "19": {
+ "start": { "line": 62, "column": 4 },
+ "end": { "line": 62, "column": null }
+ },
+ "20": {
+ "start": { "line": 77, "column": 1 },
+ "end": { "line": 144, "column": null }
+ },
+ "21": {
+ "start": { "line": 80, "column": 22 },
+ "end": { "line": 80, "column": 43 }
+ },
+ "22": {
+ "start": { "line": 82, "column": 2 },
+ "end": { "line": 87, "column": null }
+ },
+ "23": {
+ "start": { "line": 83, "column": 3 },
+ "end": { "line": 86, "column": null }
+ },
+ "24": {
+ "start": { "line": 89, "column": 40 },
+ "end": { "line": 89, "column": 42 }
+ },
+ "25": {
+ "start": { "line": 91, "column": 2 },
+ "end": { "line": 99, "column": null }
+ },
+ "26": {
+ "start": { "line": 92, "column": 3 },
+ "end": { "line": 92, "column": null }
+ },
+ "27": {
+ "start": { "line": 93, "column": 9 },
+ "end": { "line": 99, "column": null }
+ },
+ "28": {
+ "start": { "line": 94, "column": 3 },
+ "end": { "line": 94, "column": null }
+ },
+ "29": {
+ "start": { "line": 95, "column": 9 },
+ "end": { "line": 99, "column": null }
+ },
+ "30": {
+ "start": { "line": 96, "column": 3 },
+ "end": { "line": 98, "column": null }
+ },
+ "31": {
+ "start": { "line": 101, "column": 2 },
+ "end": { "line": 101, "column": null }
+ },
+ "32": {
+ "start": { "line": 103, "column": 16 },
+ "end": { "line": 103, "column": 34 }
+ },
+ "33": {
+ "start": { "line": 104, "column": 2 },
+ "end": { "line": 106, "column": null }
+ },
+ "34": {
+ "start": { "line": 105, "column": 3 },
+ "end": { "line": 105, "column": null }
+ },
+ "35": {
+ "start": { "line": 110, "column": 24 },
+ "end": { "line": 110, "column": 69 }
+ },
+ "36": {
+ "start": { "line": 111, "column": 26 },
+ "end": { "line": 111, "column": 51 }
+ },
+ "37": {
+ "start": { "line": 113, "column": 2 },
+ "end": { "line": 113, "column": null }
+ },
+ "38": {
+ "start": { "line": 116, "column": 3 },
+ "end": { "line": 118, "column": 49 }
+ },
+ "39": {
+ "start": { "line": 119, "column": 2 },
+ "end": { "line": 124, "column": null }
+ },
+ "40": {
+ "start": { "line": 120, "column": 3 },
+ "end": { "line": 122, "column": null }
+ },
+ "41": {
+ "start": { "line": 123, "column": 3 },
+ "end": { "line": 123, "column": null }
+ },
+ "42": {
+ "start": { "line": 126, "column": 17 },
+ "end": { "line": 129, "column": null }
+ },
+ "43": {
+ "start": { "line": 132, "column": 20 },
+ "end": { "line": 134, "column": null }
+ },
+ "44": {
+ "start": { "line": 137, "column": 2 },
+ "end": { "line": 143, "column": null }
+ },
+ "45": {
+ "start": { "line": 138, "column": 3 },
+ "end": { "line": 138, "column": null }
+ },
+ "46": {
+ "start": { "line": 139, "column": 9 },
+ "end": { "line": 143, "column": null }
+ },
+ "47": {
+ "start": { "line": 140, "column": 3 },
+ "end": { "line": 140, "column": null }
+ },
+ "48": {
+ "start": { "line": 142, "column": 3 },
+ "end": { "line": 142, "column": null }
+ },
+ "49": {
+ "start": { "line": 68, "column": 0 },
+ "end": { "line": 68, "column": 16 }
+ },
+ "50": {
+ "start": { "line": 147, "column": 32 },
+ "end": { "line": 166, "column": 1 }
+ },
+ "51": {
+ "start": { "line": 155, "column": 1 },
+ "end": { "line": 165, "column": null }
+ },
+ "52": {
+ "start": { "line": 156, "column": 21 },
+ "end": { "line": 156, "column": 36 }
+ },
+ "53": {
+ "start": { "line": 157, "column": 24 },
+ "end": { "line": 157, "column": 55 }
+ },
+ "54": {
+ "start": { "line": 158, "column": 2 },
+ "end": { "line": 158, "column": null }
+ },
+ "55": {
+ "start": { "line": 159, "column": 2 },
+ "end": { "line": 159, "column": null }
+ },
+ "56": {
+ "start": { "line": 160, "column": 2 },
+ "end": { "line": 160, "column": null }
+ },
+ "57": {
+ "start": { "line": 161, "column": 2 },
+ "end": { "line": 164, "column": null }
+ },
+ "58": {
+ "start": { "line": 163, "column": 3 },
+ "end": { "line": 163, "column": null }
+ },
+ "59": {
+ "start": { "line": 163, "column": 14 },
+ "end": { "line": 163, "column": null }
+ },
+ "60": {
+ "start": { "line": 147, "column": 13 },
+ "end": { "line": 147, "column": 32 }
+ },
+ "61": {
+ "start": { "line": 168, "column": 35 },
+ "end": { "line": 209, "column": 1 }
+ },
+ "62": {
+ "start": { "line": 176, "column": 1 },
+ "end": { "line": 176, "column": null }
+ },
+ "63": {
+ "start": { "line": 178, "column": 1 },
+ "end": { "line": 208, "column": null }
+ },
+ "64": {
+ "start": { "line": 180, "column": 3 },
+ "end": { "line": 190, "column": null }
+ },
+ "65": {
+ "start": { "line": 182, "column": 4 },
+ "end": { "line": 189, "column": null }
+ },
+ "66": {
+ "start": { "line": 183, "column": 5 },
+ "end": { "line": 183, "column": null }
+ },
+ "67": {
+ "start": { "line": 186, "column": 5 },
+ "end": { "line": 188, "column": null }
+ },
+ "68": {
+ "start": { "line": 187, "column": 19 },
+ "end": { "line": 187, "column": 57 }
+ },
+ "69": {
+ "start": { "line": 194, "column": 2 },
+ "end": { "line": 198, "column": null }
+ },
+ "70": {
+ "start": { "line": 196, "column": 15 },
+ "end": { "line": 196, "column": 45 }
+ },
+ "71": {
+ "start": { "line": 201, "column": 2 },
+ "end": { "line": 207, "column": null }
+ },
+ "72": {
+ "start": { "line": 202, "column": 3 },
+ "end": { "line": 206, "column": null }
+ },
+ "73": {
+ "start": { "line": 204, "column": 16 },
+ "end": { "line": 204, "column": 63 }
+ },
+ "74": {
+ "start": { "line": 168, "column": 13 },
+ "end": { "line": 168, "column": 35 }
+ },
+ "75": {
+ "start": { "line": 211, "column": 28 },
+ "end": { "line": 253, "column": 1 }
+ },
+ "76": {
+ "start": { "line": 217, "column": 1 },
+ "end": { "line": 252, "column": null }
+ },
+ "77": {
+ "start": { "line": 218, "column": 19 },
+ "end": { "line": 218, "column": 24 }
+ },
+ "78": {
+ "start": { "line": 219, "column": 24 },
+ "end": { "line": 236, "column": 3 }
+ },
+ "79": {
+ "start": { "line": 220, "column": 3 },
+ "end": { "line": 227, "column": null }
+ },
+ "80": {
+ "start": { "line": 224, "column": 4 },
+ "end": { "line": 226, "column": null }
+ },
+ "81": {
+ "start": { "line": 228, "column": 3 },
+ "end": { "line": 228, "column": null }
+ },
+ "82": {
+ "start": { "line": 230, "column": 3 },
+ "end": { "line": 234, "column": null }
+ },
+ "83": {
+ "start": { "line": 231, "column": 4 },
+ "end": { "line": 231, "column": null }
+ },
+ "84": {
+ "start": { "line": 233, "column": 4 },
+ "end": { "line": 233, "column": null }
+ },
+ "85": {
+ "start": { "line": 235, "column": 3 },
+ "end": { "line": 235, "column": null }
+ },
+ "86": {
+ "start": { "line": 237, "column": 17 },
+ "end": { "line": 237, "column": 42 }
+ },
+ "87": {
+ "start": { "line": 243, "column": 2 },
+ "end": { "line": 249, "column": null }
+ },
+ "88": {
+ "start": { "line": 244, "column": 3 },
+ "end": { "line": 248, "column": null }
+ },
+ "89": {
+ "start": { "line": 251, "column": 2 },
+ "end": { "line": 251, "column": null }
+ },
+ "90": {
+ "start": { "line": 259, "column": 1 },
+ "end": { "line": 264, "column": null }
+ },
+ "91": {
+ "start": { "line": 261, "column": 3 },
+ "end": { "line": 261, "column": null }
+ },
+ "92": {
+ "start": { "line": 263, "column": 3 },
+ "end": { "line": 263, "column": null }
+ },
+ "93": {
+ "start": { "line": 265, "column": 1 },
+ "end": { "line": 265, "column": null }
+ },
+ "94": {
+ "start": { "line": 268, "column": 20 },
+ "end": { "line": 280, "column": 1 }
+ },
+ "95": {
+ "start": { "line": 269, "column": 1 },
+ "end": { "line": 278, "column": null }
+ },
+ "96": {
+ "start": { "line": 271, "column": 3 },
+ "end": { "line": 271, "column": null }
+ },
+ "97": {
+ "start": { "line": 273, "column": 3 },
+ "end": { "line": 273, "column": null }
+ },
+ "98": {
+ "start": { "line": 275, "column": 3 },
+ "end": { "line": 277, "column": null }
+ },
+ "99": {
+ "start": { "line": 276, "column": 4 },
+ "end": { "line": 276, "column": null }
+ },
+ "100": {
+ "start": { "line": 279, "column": 1 },
+ "end": { "line": 279, "column": null }
+ },
+ "101": {
+ "start": { "line": 282, "column": 29 },
+ "end": { "line": 295, "column": 1 }
+ },
+ "102": {
+ "start": { "line": 286, "column": 18 },
+ "end": { "line": 286, "column": 24 }
+ },
+ "103": {
+ "start": { "line": 287, "column": 21 },
+ "end": { "line": 287, "column": 26 }
+ },
+ "104": {
+ "start": { "line": 288, "column": 1 },
+ "end": { "line": 293, "column": null }
+ },
+ "105": {
+ "start": { "line": 289, "column": 2 },
+ "end": { "line": 289, "column": null }
+ },
+ "106": {
+ "start": { "line": 290, "column": 2 },
+ "end": { "line": 292, "column": null }
+ },
+ "107": {
+ "start": { "line": 291, "column": 3 },
+ "end": { "line": 291, "column": null }
+ },
+ "108": {
+ "start": { "line": 294, "column": 1 },
+ "end": { "line": 294, "column": null }
}
},
"fnMap": {
"0": {
- "name": "(anonymous_0)",
+ "name": "(anonymous_6)",
"decl": {
- "start": { "line": 20, "column": 24 },
- "end": { "line": 20, "column": 27 }
+ "start": { "line": 40, "column": 2 },
+ "end": { "line": 40, "column": 24 }
},
"loc": {
- "start": { "line": 20, "column": 29 },
- "end": { "line": 24, "column": 1 }
+ "start": { "line": 40, "column": 30 },
+ "end": { "line": 44, "column": 2 }
}
},
"1": {
- "name": "(anonymous_1)",
+ "name": "(anonymous_7)",
+ "decl": {
+ "start": { "line": 40, "column": 30 },
+ "end": { "line": 40, "column": 34 }
+ },
+ "loc": {
+ "start": { "line": 40, "column": 38 },
+ "end": { "line": 44, "column": 2 }
+ }
+ },
+ "2": {
+ "name": "(anonymous_8)",
+ "decl": {
+ "start": { "line": 41, "column": 38 },
+ "end": { "line": 41, "column": 43 }
+ },
+ "loc": {
+ "start": { "line": 41, "column": 43 },
+ "end": { "line": 43, "column": 3 }
+ }
+ },
+ "3": {
+ "name": "printTestNameIfRequested",
+ "decl": {
+ "start": { "line": 48, "column": 9 },
+ "end": { "line": 48, "column": 33 }
+ },
+ "loc": {
+ "start": { "line": 48, "column": 57 },
+ "end": { "line": 66, "column": null }
+ }
+ },
+ "4": {
+ "name": "fuzz",
+ "decl": {
+ "start": { "line": 68, "column": 16 },
+ "end": { "line": 68, "column": 20 }
+ },
+ "loc": {
+ "start": { "line": 75, "column": 19 },
+ "end": { "line": 145, "column": null }
+ }
+ },
+ "5": {
+ "name": "(anonymous_11)",
+ "decl": {
+ "start": { "line": 77, "column": 8 },
+ "end": { "line": 77, "column": 9 }
+ },
+ "loc": {
+ "start": { "line": 77, "column": 39 },
+ "end": { "line": 144, "column": 2 }
+ }
+ },
+ "6": {
+ "name": "(anonymous_12)",
+ "decl": {
+ "start": { "line": 120, "column": 27 },
+ "end": { "line": 120, "column": 32 }
+ },
+ "loc": {
+ "start": { "line": 120, "column": 32 },
+ "end": { "line": 121, "column": null }
+ }
+ },
+ "7": {
+ "name": "(anonymous_13)",
+ "decl": {
+ "start": { "line": 147, "column": 32 },
+ "end": { "line": 147, "column": null }
+ },
+ "loc": {
+ "start": { "line": 154, "column": 4 },
+ "end": { "line": 166, "column": 1 }
+ }
+ },
+ "8": {
+ "name": "(anonymous_14)",
+ "decl": {
+ "start": { "line": 155, "column": 38 },
+ "end": { "line": 155, "column": 49 }
+ },
+ "loc": {
+ "start": { "line": 155, "column": 49 },
+ "end": { "line": 165, "column": 2 }
+ }
+ },
+ "9": {
+ "name": "(anonymous_15)",
+ "decl": {
+ "start": { "line": 161, "column": 49 },
+ "end": { "line": 161, "column": 50 }
+ },
+ "loc": {
+ "start": { "line": 161, "column": 63 },
+ "end": { "line": 164, "column": 3 }
+ }
+ },
+ "10": {
+ "name": "(anonymous_16)",
+ "decl": {
+ "start": { "line": 168, "column": 35 },
+ "end": { "line": 168, "column": null }
+ },
+ "loc": {
+ "start": { "line": 175, "column": 4 },
+ "end": { "line": 209, "column": 1 }
+ }
+ },
+ "11": {
+ "name": "(anonymous_17)",
"decl": {
- "start": { "line": 21, "column": 27 },
- "end": { "line": 21, "column": 28 }
+ "start": { "line": 178, "column": 42 },
+ "end": { "line": 178, "column": 47 }
},
"loc": {
- "start": { "line": 21, "column": 44 },
- "end": { "line": 23, "column": 2 }
+ "start": { "line": 178, "column": 47 },
+ "end": { "line": 208, "column": 2 }
+ }
+ },
+ "12": {
+ "name": "executeTarget",
+ "decl": {
+ "start": { "line": 179, "column": 11 },
+ "end": { "line": 179, "column": 24 }
+ },
+ "loc": {
+ "start": { "line": 179, "column": 40 },
+ "end": { "line": 191, "column": null }
+ }
+ },
+ "13": {
+ "name": "(anonymous_19)",
+ "decl": {
+ "start": { "line": 180, "column": 22 },
+ "end": { "line": 180, "column": 23 }
+ },
+ "loc": {
+ "start": { "line": 180, "column": 42 },
+ "end": { "line": 190, "column": 4 }
+ }
+ },
+ "14": {
+ "name": "(anonymous_20)",
+ "decl": {
+ "start": { "line": 187, "column": 12 },
+ "end": { "line": 187, "column": 19 }
+ },
+ "loc": {
+ "start": { "line": 187, "column": 19 },
+ "end": { "line": 187, "column": 57 }
+ }
+ },
+ "15": {
+ "name": "(anonymous_21)",
+ "decl": {
+ "start": { "line": 196, "column": 3 },
+ "end": { "line": 196, "column": 15 }
+ },
+ "loc": {
+ "start": { "line": 196, "column": 15 },
+ "end": { "line": 196, "column": 45 }
+ }
+ },
+ "16": {
+ "name": "(anonymous_22)",
+ "decl": {
+ "start": { "line": 201, "column": 31 },
+ "end": { "line": 201, "column": 32 }
+ },
+ "loc": {
+ "start": { "line": 201, "column": 48 },
+ "end": { "line": 207, "column": 3 }
+ }
+ },
+ "17": {
+ "name": "(anonymous_23)",
+ "decl": {
+ "start": { "line": 204, "column": 4 },
+ "end": { "line": 204, "column": 16 }
+ },
+ "loc": {
+ "start": { "line": 204, "column": 16 },
+ "end": { "line": 204, "column": 63 }
+ }
+ },
+ "18": {
+ "name": "(anonymous_24)",
+ "decl": {
+ "start": { "line": 211, "column": 28 },
+ "end": { "line": 211, "column": null }
+ },
+ "loc": {
+ "start": { "line": 216, "column": 4 },
+ "end": { "line": 253, "column": 1 }
+ }
+ },
+ "19": {
+ "name": "(anonymous_25)",
+ "decl": {
+ "start": { "line": 219, "column": 24 },
+ "end": { "line": 219, "column": 35 }
+ },
+ "loc": {
+ "start": { "line": 219, "column": 39 },
+ "end": { "line": 236, "column": 3 }
+ }
+ },
+ "20": {
+ "name": "handleMode",
+ "decl": {
+ "start": { "line": 255, "column": 9 },
+ "end": { "line": 255, "column": 19 }
+ },
+ "loc": {
+ "start": { "line": 257, "column": 44 },
+ "end": { "line": 266, "column": null }
+ }
+ },
+ "21": {
+ "name": "(anonymous_27)",
+ "decl": {
+ "start": { "line": 268, "column": 20 },
+ "end": { "line": 268, "column": 45 }
+ },
+ "loc": {
+ "start": { "line": 268, "column": 57 },
+ "end": { "line": 280, "column": 1 }
+ }
+ },
+ "22": {
+ "name": "(anonymous_28)",
+ "decl": {
+ "start": { "line": 282, "column": 29 },
+ "end": { "line": 282, "column": null }
+ },
+ "loc": {
+ "start": { "line": 285, "column": 14 },
+ "end": { "line": 295, "column": 1 }
}
}
},
- "branchMap": {},
+ "branchMap": {
+ "0": {
+ "loc": {
+ "start": { "line": 50, "column": 1 },
+ "end": { "line": 65, "column": null }
+ },
+ "type": "if",
+ "locations": [
+ {
+ "start": { "line": 50, "column": 1 },
+ "end": { "line": 65, "column": null }
+ },
+ {
+ "start": { "line": 50, "column": 1 },
+ "end": { "line": 65, "column": null }
+ }
+ ]
+ },
+ "1": {
+ "loc": {
+ "start": { "line": 51, "column": 2 },
+ "end": { "line": 64, "column": null }
+ },
+ "type": "if",
+ "locations": [
+ {
+ "start": { "line": 51, "column": 2 },
+ "end": { "line": 64, "column": null }
+ },
+ {
+ "start": { "line": 51, "column": 2 },
+ "end": { "line": 64, "column": null }
+ }
+ ]
+ },
+ "2": {
+ "loc": {
+ "start": { "line": 52, "column": 3 },
+ "end": { "line": 53, "column": 66 }
+ },
+ "type": "binary-expr",
+ "locations": [
+ {
+ "start": { "line": 52, "column": 3 },
+ "end": { "line": 52, "column": 62 }
+ },
+ {
+ "start": { "line": 53, "column": 3 },
+ "end": { "line": 53, "column": 66 }
+ }
+ ]
+ },
+ "3": {
+ "loc": {
+ "start": { "line": 55, "column": 3 },
+ "end": { "line": 63, "column": null }
+ },
+ "type": "if",
+ "locations": [
+ {
+ "start": { "line": 55, "column": 3 },
+ "end": { "line": 63, "column": null }
+ },
+ {
+ "start": { "line": 58, "column": 10 },
+ "end": { "line": 63, "column": null }
+ }
+ ]
+ },
+ "4": {
+ "loc": {
+ "start": { "line": 56, "column": 31 },
+ "end": { "line": 56, "column": 56 }
+ },
+ "type": "binary-expr",
+ "locations": [
+ {
+ "start": { "line": 56, "column": 31 },
+ "end": { "line": 56, "column": 50 }
+ },
+ {
+ "start": { "line": 56, "column": 54 },
+ "end": { "line": 56, "column": 56 }
+ }
+ ]
+ },
+ "5": {
+ "loc": {
+ "start": { "line": 58, "column": 10 },
+ "end": { "line": 63, "column": null }
+ },
+ "type": "if",
+ "locations": [
+ {
+ "start": { "line": 58, "column": 10 },
+ "end": { "line": 63, "column": null }
+ },
+ {
+ "start": { "line": 61, "column": 10 },
+ "end": { "line": 63, "column": null }
+ }
+ ]
+ },
+ "6": {
+ "loc": {
+ "start": { "line": 82, "column": 2 },
+ "end": { "line": 87, "column": null }
+ },
+ "type": "if",
+ "locations": [
+ {
+ "start": { "line": 82, "column": 2 },
+ "end": { "line": 87, "column": null }
+ },
+ {
+ "start": { "line": 82, "column": 2 },
+ "end": { "line": 87, "column": null }
+ }
+ ]
+ },
+ "7": {
+ "loc": {
+ "start": { "line": 91, "column": 2 },
+ "end": { "line": 99, "column": null }
+ },
+ "type": "if",
+ "locations": [
+ {
+ "start": { "line": 91, "column": 2 },
+ "end": { "line": 99, "column": null }
+ },
+ {
+ "start": { "line": 93, "column": 9 },
+ "end": { "line": 99, "column": null }
+ }
+ ]
+ },
+ "8": {
+ "loc": {
+ "start": { "line": 93, "column": 9 },
+ "end": { "line": 99, "column": null }
+ },
+ "type": "if",
+ "locations": [
+ {
+ "start": { "line": 93, "column": 9 },
+ "end": { "line": 99, "column": null }
+ },
+ {
+ "start": { "line": 95, "column": 9 },
+ "end": { "line": 99, "column": null }
+ }
+ ]
+ },
+ "9": {
+ "loc": {
+ "start": { "line": 95, "column": 9 },
+ "end": { "line": 99, "column": null }
+ },
+ "type": "if",
+ "locations": [
+ {
+ "start": { "line": 95, "column": 9 },
+ "end": { "line": 99, "column": null }
+ },
+ {
+ "start": { "line": 95, "column": 9 },
+ "end": { "line": 99, "column": null }
+ }
+ ]
+ },
+ "10": {
+ "loc": {
+ "start": { "line": 104, "column": 2 },
+ "end": { "line": 106, "column": null }
+ },
+ "type": "if",
+ "locations": [
+ {
+ "start": { "line": 104, "column": 2 },
+ "end": { "line": 106, "column": null }
+ },
+ {
+ "start": { "line": 104, "column": 2 },
+ "end": { "line": 106, "column": null }
+ }
+ ]
+ },
+ "11": {
+ "loc": {
+ "start": { "line": 116, "column": 3 },
+ "end": { "line": 118, "column": 49 }
+ },
+ "type": "binary-expr",
+ "locations": [
+ {
+ "start": { "line": 116, "column": 3 },
+ "end": { "line": 116, "column": 30 }
+ },
+ {
+ "start": { "line": 117, "column": 3 },
+ "end": { "line": 117, "column": 32 }
+ },
+ {
+ "start": { "line": 118, "column": 3 },
+ "end": { "line": 118, "column": 49 }
+ }
+ ]
+ },
+ "12": {
+ "loc": {
+ "start": { "line": 119, "column": 2 },
+ "end": { "line": 124, "column": null }
+ },
+ "type": "if",
+ "locations": [
+ {
+ "start": { "line": 119, "column": 2 },
+ "end": { "line": 124, "column": null }
+ },
+ {
+ "start": { "line": 119, "column": 2 },
+ "end": { "line": 124, "column": null }
+ }
+ ]
+ },
+ "13": {
+ "loc": {
+ "start": { "line": 137, "column": 2 },
+ "end": { "line": 143, "column": null }
+ },
+ "type": "if",
+ "locations": [
+ {
+ "start": { "line": 137, "column": 2 },
+ "end": { "line": 143, "column": null }
+ },
+ {
+ "start": { "line": 139, "column": 9 },
+ "end": { "line": 143, "column": null }
+ }
+ ]
+ },
+ "14": {
+ "loc": {
+ "start": { "line": 139, "column": 9 },
+ "end": { "line": 143, "column": null }
+ },
+ "type": "if",
+ "locations": [
+ {
+ "start": { "line": 139, "column": 9 },
+ "end": { "line": 143, "column": null }
+ },
+ {
+ "start": { "line": 141, "column": 9 },
+ "end": { "line": 143, "column": null }
+ }
+ ]
+ },
+ "15": {
+ "loc": {
+ "start": { "line": 163, "column": 3 },
+ "end": { "line": 163, "column": null }
+ },
+ "type": "if",
+ "locations": [
+ {
+ "start": { "line": 163, "column": 3 },
+ "end": { "line": 163, "column": null }
+ },
+ {
+ "start": { "line": 163, "column": 3 },
+ "end": { "line": 163, "column": null }
+ }
+ ]
+ },
+ "16": {
+ "loc": {
+ "start": { "line": 182, "column": 4 },
+ "end": { "line": 189, "column": null }
+ },
+ "type": "if",
+ "locations": [
+ {
+ "start": { "line": 182, "column": 4 },
+ "end": { "line": 189, "column": null }
+ },
+ {
+ "start": { "line": 184, "column": 11 },
+ "end": { "line": 189, "column": null }
+ }
+ ]
+ },
+ "17": {
+ "loc": {
+ "start": { "line": 220, "column": 3 },
+ "end": { "line": 227, "column": null }
+ },
+ "type": "if",
+ "locations": [
+ {
+ "start": { "line": 220, "column": 3 },
+ "end": { "line": 227, "column": null }
+ },
+ {
+ "start": { "line": 220, "column": 3 },
+ "end": { "line": 227, "column": null }
+ }
+ ]
+ },
+ "18": {
+ "loc": {
+ "start": { "line": 230, "column": 3 },
+ "end": { "line": 234, "column": null }
+ },
+ "type": "if",
+ "locations": [
+ {
+ "start": { "line": 230, "column": 3 },
+ "end": { "line": 234, "column": null }
+ },
+ {
+ "start": { "line": 232, "column": 10 },
+ "end": { "line": 234, "column": null }
+ }
+ ]
+ },
+ "19": {
+ "loc": {
+ "start": { "line": 235, "column": 3 },
+ "end": { "line": 235, "column": 45 }
+ },
+ "type": "cond-expr",
+ "locations": [
+ {
+ "start": { "line": 235, "column": 11 },
+ "end": { "line": 235, "column": 24 }
+ },
+ {
+ "start": { "line": 235, "column": 27 },
+ "end": { "line": 235, "column": 45 }
+ }
+ ]
+ },
+ "20": {
+ "loc": {
+ "start": { "line": 243, "column": 2 },
+ "end": { "line": 249, "column": null }
+ },
+ "type": "if",
+ "locations": [
+ {
+ "start": { "line": 243, "column": 2 },
+ "end": { "line": 249, "column": null }
+ },
+ {
+ "start": { "line": 243, "column": 2 },
+ "end": { "line": 249, "column": null }
+ }
+ ]
+ },
+ "21": {
+ "loc": {
+ "start": { "line": 243, "column": 6 },
+ "end": { "line": 243, "column": 49 }
+ },
+ "type": "binary-expr",
+ "locations": [
+ {
+ "start": { "line": 243, "column": 6 },
+ "end": { "line": 243, "column": 12 }
+ },
+ {
+ "start": { "line": 243, "column": 16 },
+ "end": { "line": 243, "column": 49 }
+ }
+ ]
+ },
+ "22": {
+ "loc": {
+ "start": { "line": 259, "column": 1 },
+ "end": { "line": 264, "column": null }
+ },
+ "type": "switch",
+ "locations": [
+ {
+ "start": { "line": 260, "column": 2 },
+ "end": { "line": 261, "column": null }
+ },
+ {
+ "start": { "line": 262, "column": 2 },
+ "end": { "line": 263, "column": null }
+ }
+ ]
+ },
+ "23": {
+ "loc": {
+ "start": { "line": 269, "column": 1 },
+ "end": { "line": 278, "column": null }
+ },
+ "type": "switch",
+ "locations": [
+ {
+ "start": { "line": 270, "column": 2 },
+ "end": { "line": 271, "column": null }
+ },
+ {
+ "start": { "line": 272, "column": 2 },
+ "end": { "line": 273, "column": null }
+ },
+ {
+ "start": { "line": 274, "column": 2 },
+ "end": { "line": 277, "column": null }
+ }
+ ]
+ },
+ "24": {
+ "loc": {
+ "start": { "line": 275, "column": 3 },
+ "end": { "line": 277, "column": null }
+ },
+ "type": "if",
+ "locations": [
+ {
+ "start": { "line": 275, "column": 3 },
+ "end": { "line": 277, "column": null }
+ },
+ {
+ "start": { "line": 275, "column": 3 },
+ "end": { "line": 277, "column": null }
+ }
+ ]
+ },
+ "25": {
+ "loc": {
+ "start": { "line": 290, "column": 2 },
+ "end": { "line": 292, "column": null }
+ },
+ "type": "if",
+ "locations": [
+ {
+ "start": { "line": 290, "column": 2 },
+ "end": { "line": 292, "column": null }
+ },
+ {
+ "start": { "line": 290, "column": 2 },
+ "end": { "line": 292, "column": null }
+ }
+ ]
+ }
+ },
"s": {
"0": 1,
"1": 1,
"2": 1,
"3": 1,
- "4": 3
+ "4": 1,
+ "5": 1,
+ "6": 0,
+ "7": 0,
+ "8": 0,
+ "9": 1,
+ "10": 0,
+ "11": 0,
+ "12": 0,
+ "13": 0,
+ "14": 0,
+ "15": 0,
+ "16": 0,
+ "17": 0,
+ "18": 0,
+ "19": 0,
+ "20": 0,
+ "21": 0,
+ "22": 0,
+ "23": 0,
+ "24": 0,
+ "25": 0,
+ "26": 0,
+ "27": 0,
+ "28": 0,
+ "29": 0,
+ "30": 0,
+ "31": 0,
+ "32": 0,
+ "33": 0,
+ "34": 0,
+ "35": 0,
+ "36": 0,
+ "37": 0,
+ "38": 0,
+ "39": 0,
+ "40": 0,
+ "41": 0,
+ "42": 0,
+ "43": 0,
+ "44": 0,
+ "45": 0,
+ "46": 0,
+ "47": 0,
+ "48": 0,
+ "49": 1,
+ "50": 1,
+ "51": 0,
+ "52": 0,
+ "53": 0,
+ "54": 0,
+ "55": 0,
+ "56": 0,
+ "57": 0,
+ "58": 0,
+ "59": 0,
+ "60": 1,
+ "61": 1,
+ "62": 0,
+ "63": 0,
+ "64": 0,
+ "65": 0,
+ "66": 0,
+ "67": 0,
+ "68": 0,
+ "69": 0,
+ "70": 0,
+ "71": 0,
+ "72": 0,
+ "73": 0,
+ "74": 1,
+ "75": 1,
+ "76": 0,
+ "77": 0,
+ "78": 0,
+ "79": 0,
+ "80": 0,
+ "81": 0,
+ "82": 0,
+ "83": 0,
+ "84": 0,
+ "85": 0,
+ "86": 0,
+ "87": 0,
+ "88": 0,
+ "89": 0,
+ "90": 0,
+ "91": 0,
+ "92": 0,
+ "93": 0,
+ "94": 1,
+ "95": 0,
+ "96": 0,
+ "97": 0,
+ "98": 0,
+ "99": 0,
+ "100": 0,
+ "101": 1,
+ "102": 0,
+ "103": 0,
+ "104": 0,
+ "105": 0,
+ "106": 0,
+ "107": 0,
+ "108": 0
},
"f": {
- "0": 1,
- "1": 3
+ "0": 0,
+ "1": 0,
+ "2": 0,
+ "3": 0,
+ "4": 0,
+ "5": 0,
+ "6": 0,
+ "7": 0,
+ "8": 0,
+ "9": 0,
+ "10": 0,
+ "11": 0,
+ "12": 0,
+ "13": 0,
+ "14": 0,
+ "15": 0,
+ "16": 0,
+ "17": 0,
+ "18": 0,
+ "19": 0,
+ "20": 0,
+ "21": 0,
+ "22": 0
},
- "b": {}
+ "b": {
+ "0": [0, 0],
+ "1": [0, 0],
+ "2": [0, 0],
+ "3": [0, 0],
+ "4": [0, 0],
+ "5": [0, 0],
+ "6": [0, 0],
+ "7": [0, 0],
+ "8": [0, 0],
+ "9": [0, 0],
+ "10": [0, 0],
+ "11": [0, 0, 0],
+ "12": [0, 0],
+ "13": [0, 0],
+ "14": [0, 0],
+ "15": [0, 0],
+ "16": [0, 0],
+ "17": [0, 0],
+ "18": [0, 0],
+ "19": [0, 0],
+ "20": [0, 0],
+ "21": [0, 0],
+ "22": [0, 0],
+ "23": [0, 0, 0],
+ "24": [0, 0],
+ "25": [0, 0]
+ }
},
"fuzz.js": {
+ "path": "/home/peter/Documents/Programming/jazzer.js/tests/code_coverage/sample_fuzz_test/fuzz.js",
"statementMap": {
"0": {
- "start": { "line": 17, "column": 12 },
- "end": { "line": 17, "column": 28 }
+ "start": { "line": 3, "column": 12 },
+ "end": { "line": 3, "column": 28 }
},
"1": {
- "start": { "line": 22, "column": 0 },
- "end": { "line": 28, "column": 2 }
+ "start": { "line": 8, "column": 0 },
+ "end": { "line": 14, "column": 2 }
},
"2": {
- "start": { "line": 23, "column": 1 },
- "end": { "line": 23, "column": 41 }
+ "start": { "line": 9, "column": 1 },
+ "end": { "line": 9, "column": 41 }
},
"3": {
- "start": { "line": 24, "column": 1 },
- "end": { "line": 26, "column": 2 }
+ "start": { "line": 10, "column": 1 },
+ "end": { "line": 12, "column": 2 }
},
"4": {
- "start": { "line": 25, "column": 2 },
- "end": { "line": 25, "column": 9 }
+ "start": { "line": 11, "column": 2 },
+ "end": { "line": 11, "column": 9 }
},
"5": {
- "start": { "line": 27, "column": 1 },
- "end": { "line": 27, "column": 18 }
+ "start": { "line": 13, "column": 1 },
+ "end": { "line": 13, "column": 18 }
}
},
"fnMap": {
"0": {
"name": "(anonymous_0)",
"decl": {
- "start": { "line": 22, "column": 22 },
- "end": { "line": 22, "column": 23 }
+ "start": { "line": 8, "column": 22 },
+ "end": { "line": 8, "column": 23 }
},
"loc": {
- "start": { "line": 22, "column": 38 },
- "end": { "line": 28, "column": 1 }
+ "start": { "line": 8, "column": 38 },
+ "end": { "line": 14, "column": 1 }
},
- "line": 22
+ "line": 8
}
},
"branchMap": {
"0": {
"loc": {
- "start": { "line": 24, "column": 1 },
- "end": { "line": 26, "column": 2 }
+ "start": { "line": 10, "column": 1 },
+ "end": { "line": 12, "column": 2 }
},
"type": "if",
"locations": [
{
- "start": { "line": 24, "column": 1 },
- "end": { "line": 26, "column": 2 }
+ "start": { "line": 10, "column": 1 },
+ "end": { "line": 12, "column": 2 }
},
{
- "start": { "line": 24, "column": 1 },
- "end": { "line": 26, "column": 2 }
+ "start": { "line": 10, "column": 1 },
+ "end": { "line": 12, "column": 2 }
}
],
- "line": 24
+ "line": 10
}
},
"s": { "0": 1, "1": 1, "2": 3, "3": 3, "4": 2, "5": 1 },
"f": { "0": 3 },
"b": { "0": [2, 1] },
+ "inputSourceMap": null,
"_coverageSchema": "1a1c01bbd47fc00a2c39e90264f33305004495a9",
- "hash": "d5b411e8de7efcd2798a7cd78efd7bd8347f647a"
+ "hash": "919965dfc96b474e5bb4bd686708056c565cd2df"
},
"lib.js": {
+ "path": "/home/peter/Documents/Programming/jazzer.js/tests/code_coverage/sample_fuzz_test/lib.js",
"statementMap": {
"0": {
- "start": { "line": 18, "column": 1 },
- "end": { "line": 18, "column": 29 }
+ "start": { "line": 4, "column": 1 },
+ "end": { "line": 4, "column": 29 }
},
"1": {
- "start": { "line": 19, "column": 1 },
- "end": { "line": 21, "column": 2 }
+ "start": { "line": 5, "column": 1 },
+ "end": { "line": 7, "column": 2 }
},
"2": {
- "start": { "line": 20, "column": 2 },
- "end": { "line": 20, "column": 11 }
+ "start": { "line": 6, "column": 2 },
+ "end": { "line": 6, "column": 11 }
},
"3": {
- "start": { "line": 22, "column": 1 },
- "end": { "line": 22, "column": 11 }
+ "start": { "line": 8, "column": 1 },
+ "end": { "line": 8, "column": 11 }
},
"4": {
- "start": { "line": 25, "column": 0 },
- "end": { "line": 27, "column": 2 }
+ "start": { "line": 11, "column": 0 },
+ "end": { "line": 13, "column": 2 }
}
},
"fnMap": {
"0": {
"name": "foo",
"decl": {
- "start": { "line": 17, "column": 9 },
- "end": { "line": 17, "column": 12 }
+ "start": { "line": 3, "column": 9 },
+ "end": { "line": 3, "column": 12 }
},
"loc": {
- "start": { "line": 17, "column": 16 },
- "end": { "line": 23, "column": 1 }
+ "start": { "line": 3, "column": 16 },
+ "end": { "line": 9, "column": 1 }
},
- "line": 17
+ "line": 3
}
},
"branchMap": {
"0": {
"loc": {
- "start": { "line": 19, "column": 1 },
- "end": { "line": 21, "column": 2 }
+ "start": { "line": 5, "column": 1 },
+ "end": { "line": 7, "column": 2 }
},
"type": "if",
"locations": [
{
- "start": { "line": 19, "column": 1 },
- "end": { "line": 21, "column": 2 }
+ "start": { "line": 5, "column": 1 },
+ "end": { "line": 7, "column": 2 }
},
{
- "start": { "line": 19, "column": 1 },
- "end": { "line": 21, "column": 2 }
+ "start": { "line": 5, "column": 1 },
+ "end": { "line": 7, "column": 2 }
}
],
- "line": 19
+ "line": 5
}
},
"s": { "0": 1, "1": 1, "2": 1, "3": 0, "4": 1 },
"f": { "0": 1 },
"b": { "0": [1, 0] },
+ "inputSourceMap": null,
"_coverageSchema": "1a1c01bbd47fc00a2c39e90264f33305004495a9",
- "hash": "9606a42b6e4a5e9a5c23554dda63403d86a4a9a2"
+ "hash": "fcd40034890333ddc0be68a932be368882a3d10b"
+ },
+ "otherCodeCoverage.fuzz.ts": {
+ "path": "/home/peter/Documents/Programming/jazzer.js/tests/code_coverage/sample_fuzz_test/otherCodeCoverage.fuzz.ts",
+ "statementMap": {
+ "0": {
+ "start": { "line": 3, "column": 0 },
+ "end": { "line": 3, "column": 32 }
+ },
+ "1": {
+ "start": { "line": 4, "column": 0 },
+ "end": { "line": 4, "column": 33 }
+ },
+ "2": {
+ "start": { "line": 6, "column": 0 },
+ "end": { "line": 10, "column": 3 }
+ },
+ "3": {
+ "start": { "line": 7, "column": 1 },
+ "end": { "line": 9, "column": 4 }
+ },
+ "4": {
+ "start": { "line": 8, "column": 2 },
+ "end": { "line": 8, "column": 13 }
+ }
+ },
+ "fnMap": {
+ "0": {
+ "name": "(anonymous_0)",
+ "decl": {
+ "start": { "line": 6, "column": 24 },
+ "end": { "line": 6, "column": 27 }
+ },
+ "loc": {
+ "start": { "line": 6, "column": 29 },
+ "end": { "line": 10, "column": 1 }
+ }
+ },
+ "1": {
+ "name": "(anonymous_1)",
+ "decl": {
+ "start": { "line": 7, "column": 27 },
+ "end": { "line": 7, "column": 28 }
+ },
+ "loc": {
+ "start": { "line": 7, "column": 44 },
+ "end": { "line": 9, "column": 2 }
+ }
+ }
+ },
+ "branchMap": {},
+ "s": { "0": 1, "1": 1, "2": 1, "3": 1, "4": 3 },
+ "f": { "0": 1, "1": 3 },
+ "b": {}
}
}
diff --git a/tests/code_coverage/sample_fuzz_test/expected_coverage/fuzz+lib.json b/tests/code_coverage/sample_fuzz_test/expected_coverage/fuzz+lib.json
index 888a25782..b5b4c5f41 100644
--- a/tests/code_coverage/sample_fuzz_test/expected_coverage/fuzz+lib.json
+++ b/tests/code_coverage/sample_fuzz_test/expected_coverage/fuzz+lib.json
@@ -1,126 +1,128 @@
{
"fuzz.js": {
+ "path": "/home/peter/Documents/Programming/jazzer.js/tests/code_coverage/sample_fuzz_test/fuzz.js",
"statementMap": {
"0": {
- "start": { "line": 17, "column": 12 },
- "end": { "line": 17, "column": 28 }
+ "start": { "line": 3, "column": 12 },
+ "end": { "line": 3, "column": 28 }
},
"1": {
- "start": { "line": 22, "column": 0 },
- "end": { "line": 28, "column": 2 }
+ "start": { "line": 8, "column": 0 },
+ "end": { "line": 14, "column": 2 }
},
"2": {
- "start": { "line": 23, "column": 1 },
- "end": { "line": 23, "column": 41 }
+ "start": { "line": 9, "column": 1 },
+ "end": { "line": 9, "column": 41 }
},
"3": {
- "start": { "line": 24, "column": 1 },
- "end": { "line": 26, "column": 2 }
+ "start": { "line": 10, "column": 1 },
+ "end": { "line": 12, "column": 2 }
},
"4": {
- "start": { "line": 25, "column": 2 },
- "end": { "line": 25, "column": 9 }
+ "start": { "line": 11, "column": 2 },
+ "end": { "line": 11, "column": 9 }
},
"5": {
- "start": { "line": 27, "column": 1 },
- "end": { "line": 27, "column": 18 }
+ "start": { "line": 13, "column": 1 },
+ "end": { "line": 13, "column": 18 }
}
},
"fnMap": {
"0": {
"name": "(anonymous_0)",
"decl": {
- "start": { "line": 22, "column": 22 },
- "end": { "line": 22, "column": 23 }
+ "start": { "line": 8, "column": 22 },
+ "end": { "line": 8, "column": 23 }
},
"loc": {
- "start": { "line": 22, "column": 38 },
- "end": { "line": 28, "column": 1 }
+ "start": { "line": 8, "column": 38 },
+ "end": { "line": 14, "column": 1 }
},
- "line": 22
+ "line": 8
}
},
"branchMap": {
"0": {
"loc": {
- "start": { "line": 24, "column": 1 },
- "end": { "line": 26, "column": 2 }
+ "start": { "line": 10, "column": 1 },
+ "end": { "line": 12, "column": 2 }
},
"type": "if",
"locations": [
{
- "start": { "line": 24, "column": 1 },
- "end": { "line": 26, "column": 2 }
+ "start": { "line": 10, "column": 1 },
+ "end": { "line": 12, "column": 2 }
},
{ "start": {}, "end": {} }
],
- "line": 24
+ "line": 10
}
},
"s": { "0": 1, "1": 1, "2": 3, "3": 3, "4": 2, "5": 1 },
"f": { "0": 3 },
"b": { "0": [2, 1] },
"_coverageSchema": "1a1c01bbd47fc00a2c39e90264f33305004495a9",
- "hash": "d5b411e8de7efcd2798a7cd78efd7bd8347f647a"
+ "hash": "5d5860b26158df2154cfe4eb4255dc6534ccfff1"
},
"lib.js": {
+ "path": "/home/peter/Documents/Programming/jazzer.js/tests/code_coverage/sample_fuzz_test/lib.js",
"statementMap": {
"0": {
- "start": { "line": 18, "column": 1 },
- "end": { "line": 18, "column": 29 }
+ "start": { "line": 4, "column": 1 },
+ "end": { "line": 4, "column": 29 }
},
"1": {
- "start": { "line": 19, "column": 1 },
- "end": { "line": 21, "column": 2 }
+ "start": { "line": 5, "column": 1 },
+ "end": { "line": 7, "column": 2 }
},
"2": {
- "start": { "line": 20, "column": 2 },
- "end": { "line": 20, "column": 11 }
+ "start": { "line": 6, "column": 2 },
+ "end": { "line": 6, "column": 11 }
},
"3": {
- "start": { "line": 22, "column": 1 },
- "end": { "line": 22, "column": 11 }
+ "start": { "line": 8, "column": 1 },
+ "end": { "line": 8, "column": 11 }
},
"4": {
- "start": { "line": 25, "column": 0 },
- "end": { "line": 27, "column": 2 }
+ "start": { "line": 11, "column": 0 },
+ "end": { "line": 13, "column": 2 }
}
},
"fnMap": {
"0": {
"name": "foo",
"decl": {
- "start": { "line": 17, "column": 9 },
- "end": { "line": 17, "column": 12 }
+ "start": { "line": 3, "column": 9 },
+ "end": { "line": 3, "column": 12 }
},
"loc": {
- "start": { "line": 17, "column": 16 },
- "end": { "line": 23, "column": 1 }
+ "start": { "line": 3, "column": 16 },
+ "end": { "line": 9, "column": 1 }
},
- "line": 17
+ "line": 3
}
},
"branchMap": {
"0": {
"loc": {
- "start": { "line": 19, "column": 1 },
- "end": { "line": 21, "column": 2 }
+ "start": { "line": 5, "column": 1 },
+ "end": { "line": 7, "column": 2 }
},
"type": "if",
"locations": [
{
- "start": { "line": 19, "column": 1 },
- "end": { "line": 21, "column": 2 }
+ "start": { "line": 5, "column": 1 },
+ "end": { "line": 7, "column": 2 }
},
{ "start": {}, "end": {} }
],
- "line": 19
+ "line": 5
}
},
"s": { "0": 1, "1": 1, "2": 1, "3": 0, "4": 1 },
"f": { "0": 1 },
"b": { "0": [1, 0] },
"_coverageSchema": "1a1c01bbd47fc00a2c39e90264f33305004495a9",
- "hash": "9606a42b6e4a5e9a5c23554dda63403d86a4a9a2"
+ "hash": "2c8e6fbf7fbf1d3facf8b6f7aeed0de7b31a4877"
}
}
diff --git a/tests/code_coverage/sample_fuzz_test/fuzz.js b/tests/code_coverage/sample_fuzz_test/fuzz.js
index 3d2bed16b..496b34196 100644
--- a/tests/code_coverage/sample_fuzz_test/fuzz.js
+++ b/tests/code_coverage/sample_fuzz_test/fuzz.js
@@ -1,18 +1,4 @@
-/*
- * Copyright 2023 Code Intelligence GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+/* eslint-disable header/header */
const lib = require("./lib");
diff --git a/tests/code_coverage/sample_fuzz_test/lib.js b/tests/code_coverage/sample_fuzz_test/lib.js
index 6d460de6c..a044628a4 100644
--- a/tests/code_coverage/sample_fuzz_test/lib.js
+++ b/tests/code_coverage/sample_fuzz_test/lib.js
@@ -1,18 +1,4 @@
-/*
- * Copyright 2023 Code Intelligence GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+/* eslint-disable header/header */
function foo(a) {
console.log("original foo");
diff --git a/tests/code_coverage/sample_fuzz_test/otherCodeCoverage.fuzz.ts b/tests/code_coverage/sample_fuzz_test/otherCodeCoverage.fuzz.ts
index b66031d32..d91287db3 100644
--- a/tests/code_coverage/sample_fuzz_test/otherCodeCoverage.fuzz.ts
+++ b/tests/code_coverage/sample_fuzz_test/otherCodeCoverage.fuzz.ts
@@ -1,18 +1,4 @@
-/*
- * Copyright 2023 Code Intelligence GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+/* eslint-disable header/header */
import "@jazzer.js/jest-runner";
import { fuzz } from "./fuzz.js";
diff --git a/tests/done_callback/fuzz.js b/tests/done_callback/fuzz.js
index b18543fa6..5685c76d2 100644
--- a/tests/done_callback/fuzz.js
+++ b/tests/done_callback/fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/done_callback/package.json b/tests/done_callback/package.json
index ab270334d..0d54782fb 100644
--- a/tests/done_callback/package.json
+++ b/tests/done_callback/package.json
@@ -3,7 +3,7 @@
"version": "1.0.0",
"description": "An example showing how Jazzer.js handles callback based fuzz targets",
"scripts": {
- "fuzz": "jazzer fuzz -x Error -- -runs=5000 -seed=2386907168",
+ "fuzz": "jazzer fuzz --disableBugDetectors='.*' -x Error -- -runs=5000 -seed=2386907168",
"dryRun": "jazzer fuzz -- -runs=100 -seed=123456789"
},
"devDependencies": {
diff --git a/tests/fork_mode/fuzz.js b/tests/fork_mode/fuzz.js
index c093faeb6..939a5425c 100644
--- a/tests/fork_mode/fuzz.js
+++ b/tests/fork_mode/fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/fork_mode/package.json b/tests/fork_mode/package.json
index 7b6b2cd26..f04ed1d4b 100644
--- a/tests/fork_mode/package.json
+++ b/tests/fork_mode/package.json
@@ -3,7 +3,7 @@
"version": "1.0.0",
"description": "An example showing how to use libFuzzer's fork mode in Jazzer.js",
"scripts": {
- "fuzz": "jazzer fuzz --sync -- -fork=3",
+ "fuzz": "jazzer fuzz --sync --disableBugDetectors='.*' -- -fork=3",
"dryRun": "jazzer fuzz --sync -- -fork=3 -runs=100 -seed=123456789"
},
"devDependencies": {
diff --git a/tests/helpers.js b/tests/helpers.js
index 9a1b5b1f1..8ca16ac41 100644
--- a/tests/helpers.js
+++ b/tests/helpers.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
*/
const assert = require("assert");
-const { spawnSync } = require("child_process");
+const { spawnSync, spawn } = require("child_process");
const fs = require("fs");
const path = require("path");
@@ -76,16 +76,27 @@ class FuzzTest {
this.timeout = timeout;
}
+ // Runs the fuzz test in another process using `spawnSync`.
execute() {
if (this.jestTestFile) {
- this.executeWithJest();
+ this.#executeWithJest();
} else {
- this.executeWithCli();
+ this.#executeWithCli();
}
return this;
}
- executeWithCli() {
+ // Runs the fuzz test using `spawn`. This is useful when we want to do something while the fuzz test
+ // is running (e.g. process http requests).
+ executeWithPromise() {
+ if (this.jestTestFile) {
+ return this.#executeWithJest(false);
+ } else {
+ return this.#executeWithCli(false);
+ }
+ }
+
+ #executeWithCli(useSpawnSync = true) {
const options = ["jazzer", this.fuzzFile];
options.push("-f " + this.fuzzEntryPoint);
if (this.sync) options.push("--sync");
@@ -115,10 +126,14 @@ class FuzzTest {
for (const dictionary of this.dictionaries) {
options.push("-dict=" + dictionary);
}
- this.runTest("npx", options, { ...process.env });
+ if (useSpawnSync) {
+ this.#spawnTestSync("npx", options, { ...process.env });
+ } else {
+ return this.#spawnTest("npx", options, { ...process.env });
+ }
}
- executeWithJest() {
+ #executeWithJest(useSpawnSync = true) {
const fuzzerOptions = [];
if (this.runs) {
fuzzerOptions.push("-runs=" + this.runs);
@@ -186,10 +201,14 @@ class FuzzTest {
env.JAZZER_LIST_FUZZTEST_NAMES_PATTERN = this.listFuzzTestNamesPattern;
}
- this.runTest(cmd, options, env);
+ if (useSpawnSync) {
+ this.#spawnTestSync(cmd, options, env);
+ } else {
+ return this.#spawnTest(cmd, options, env);
+ }
}
- runTest(cmd, options, env) {
+ #spawnTestSync(cmd, options, env) {
if (this.logTestOutput) {
console.log("COMMAND: " + cmd + " " + options.join(" "));
}
@@ -212,6 +231,45 @@ class FuzzTest {
throw new Error(this.status.toString());
}
}
+
+ #spawnTest(cmd, options, env) {
+ return new Promise((resolve, reject) => {
+ if (this.logTestOutput) {
+ console.log("COMMAND: " + cmd + " " + options.join(" "));
+ }
+ const proc = spawn(cmd, options, {
+ stdio: "pipe",
+ cwd: this.dir,
+ shell: true,
+ windowsHide: true,
+ env: env,
+ });
+ this.stdout = "";
+ this.stderr = "";
+ proc.stdout.on("data", (data) => {
+ this.stdout += data;
+ });
+
+ proc.stderr.on("data", (data) => {
+ this.stderr += data;
+ });
+
+ // wait for process to finish
+ proc.on("exit", () => {
+ this.status = proc.exitCode.toString();
+ if (this.logTestOutput) {
+ console.log("STDOUT: " + this.stdout);
+ console.log("STDERR: " + this.stderr);
+ console.log("STATUS: " + this.status);
+ }
+ if (this.status !== "0") {
+ reject(new Error(this.status.toString()));
+ } else {
+ resolve(this.status.toString());
+ }
+ });
+ });
+ }
}
// noinspection JSUnusedGlobalSymbols
diff --git a/tests/jest_integration/integration.test.js b/tests/jest_integration/integration.test.js
index 8d5a26431..0564eb070 100644
--- a/tests/jest_integration/integration.test.js
+++ b/tests/jest_integration/integration.test.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@ describe("Jest integration", () => {
beforeEach(() => {
fuzzTestBuilder = new FuzzTestBuilder()
.dir(projectDir)
- .runs(1_000_000)
+ .disableBugDetectors([".*"])
.jestRunInFuzzingMode(true)
.jestTestFile(jestTestFile + ".js");
});
@@ -107,6 +107,17 @@ describe("Jest integration", () => {
});
describe("timeout", () => {
+ it("execute sync timeout test", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .jestTestName("execute sync timeout test plain")
+ .build();
+ expect(() => {
+ fuzzTest.execute();
+ }).toThrow(TimeoutExitCode);
+ assertTimeoutMessageLogged(fuzzTest, 5);
+ await expectCrashFileIn("execute_sync_timeout_test_plain");
+ });
+
it("execute async timeout test", async () => {
const fuzzTest = fuzzTestBuilder
.jestTestName("execute async timeout test plain")
@@ -221,11 +232,35 @@ describe("Jest integration", () => {
expect(fuzzTest.stdout).toContain("standard test called");
});
});
+
+ describe("Per-fuzztest dictionary entries", () => {
+ it("with dictionary", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .jestTestName("execute sync hashed fuzz test with dictionary")
+ .build();
+ expect(() => {
+ fuzzTest.execute();
+ }).toThrow(JestRegressionExitCode);
+ expect(fuzzTest.stderr).toContain("Welcome to Amazing Fuzzing!");
+ });
+
+ it("with uint8 dictionary", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .logTestOutput()
+ .jestTestName("execute sync hashed fuzz test with uint8 dictionary")
+ .build();
+ expect(() => {
+ fuzzTest.execute();
+ }).toThrow(JestRegressionExitCode);
+ expect(fuzzTest.stderr).toContain("Welcome to Amazing Fuzzing!");
+ });
+ });
});
describe("Regression mode", () => {
const regressionTestBuilder = new FuzzTestBuilder()
.dir(projectDir)
+ .disableBugDetectors([".*"])
.jestTestFile(jestTestFile + ".js");
describe("execute", () => {
@@ -335,7 +370,11 @@ describe("Jest integration", () => {
const stackFrames = firstFailureMessage(result)
.split("\n")
.filter((line) => line.startsWith(" at"));
- expect(stackFrames).toHaveLength(10);
+ // TODO: understand why the stack trace contains one more frame when all bug detectors are enabled.
+ // missing stack frame before last:
+ // ' at processTicksAndRejections (node:internal/process/task_queues:96:5)\n' +
+ expect(stackFrames.length).toBeLessThanOrEqual(11);
+ expect(stackFrames.length).toBeGreaterThanOrEqual(10);
});
it("prioritize finding over error", () => {
@@ -379,6 +418,7 @@ describe("Jest integration", () => {
const listFuzzTestNamesTestBuilder = new FuzzTestBuilder()
.dir(projectDir)
.listFuzzTestNames()
+ .disableBugDetectors([".*"])
.jestTestFile(jestTestFile + ".js");
it("lists fuzz tests", () => {
@@ -450,6 +490,7 @@ describe("Jest TS integration", () => {
fuzzTestBuilder = new FuzzTestBuilder()
.dir(projectDir)
.runs(1_000_000)
+ .disableBugDetectors([".*"])
.jestRunInFuzzingMode(true)
.jestTestFile(jestTsTestFile + ".ts");
});
@@ -495,10 +536,41 @@ describe("Jest TS integration", () => {
await expectCrashFileIn("execute_async_test_using_a_callback");
});
});
+
+ describe("Fuzz test options support", () => {
+ it("with dictionary", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .jestTestName("execute sync hashed fuzz test with dictionary")
+ .build();
+ expect(() => {
+ fuzzTest.execute();
+ }).toThrow(JestRegressionExitCode);
+ expect(fuzzTest.stderr).toContain("Welcome to Amazing Fuzzing!");
+ });
+
+ it("with sync and runs", () => {
+ const fuzzTest = fuzzTestBuilder
+ .verbose()
+ .runs(1) // will get changed to 101 by the fuzz test
+ .sync(false) // will get changed to true by the fuzz test
+ .jestTestName(
+ "Further options sync, number of runs, dictionary is Amazing",
+ )
+ .build();
+ fuzzTest.execute();
+ // The options are printed with colors. Here "sync: true," is matched.
+ expect(fuzzTest.stderr).toContain("sync: { value: true,");
+ expect(fuzzTest.stderr).toContain(
+ "dictionaryEntries: { value: [ 'Amazing' ]",
+ );
+ expect(fuzzTest.stdout).toContain("i = 100");
+ });
+ });
});
describe("Regression mode", () => {
const regressionTestBuilder = new FuzzTestBuilder()
+ .disableBugDetectors([".*"])
.dir(projectDir)
.jestTestFile(jestTsTestFile + ".ts");
diff --git a/tests/jest_integration/jest_project/integration.fuzz.js b/tests/jest_integration/jest_project/integration.fuzz.js
index eea7766f3..79bd17b71 100644
--- a/tests/jest_integration/jest_project/integration.fuzz.js
+++ b/tests/jest_integration/jest_project/integration.fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,6 +37,29 @@ describe("Jest Integration", () => {
target.fuzzMe(data);
});
+ it.fuzz(
+ "execute sync hashed fuzz test with dictionary",
+ (data) => {
+ target.fuzzMeHashed(data);
+ },
+ { dictionaryEntries: ["Amazing"] },
+ );
+
+ it.fuzz(
+ "execute sync hashed fuzz test with uint8 dictionary",
+ (data) => {
+ target.fuzzMeHashed(data);
+ },
+ {
+ dictionaryEntries: [
+ new Uint8Array([0x41, 0x6d, 0x61, 0x7a, 0x69, 0x6e, 0x67]),
+ // Adding an entry with all bytes to the dictionary should not affect the fuzzing.
+ // This tests if escaping all 256 characters works in a way that libFuzzer is happy with it.
+ new Uint8Array([...Array(256).keys()]),
+ ],
+ },
+ );
+
it.fuzz("execute async test", async (data) => {
await target.asyncFuzzMe(data);
});
@@ -53,6 +76,10 @@ describe("Jest Integration", () => {
await target.asyncTimeout(data);
});
+ it.fuzz("execute sync timeout test plain", (data) => {
+ target.syncTimeout(data);
+ });
+
it.fuzz(
"execute async timeout test with method timeout",
async (data) => {
diff --git a/tests/jest_integration/jest_project/run-mode-only.fuzz.js b/tests/jest_integration/jest_project/run-mode-only.fuzz.js
index af7ab7d21..9d7543593 100644
--- a/tests/jest_integration/jest_project/run-mode-only.fuzz.js
+++ b/tests/jest_integration/jest_project/run-mode-only.fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/jest_integration/jest_project/target.js b/tests/jest_integration/jest_project/target.js
index 00a4968ad..54557836d 100644
--- a/tests/jest_integration/jest_project/target.js
+++ b/tests/jest_integration/jest_project/target.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+const crypto = require("crypto");
+
const fuzzMe = (data) => {
if (data.toString() === "Awe") {
throw Error("Welcome to Awesome Fuzzing!");
@@ -21,6 +23,26 @@ const fuzzMe = (data) => {
};
module.exports.fuzzMe = fuzzMe;
+const fuzzMeHashed = function (data) {
+ const s = data.toString();
+ if (s.length !== 7) {
+ return;
+ }
+
+ const sha = crypto.createHash("sha512").update(s);
+ const result = sha.digest("hex");
+
+ // Hash of "Amazing"
+ if (
+ result ===
+ "79328e1e1272ff2890ff0c6e8181a52ce5960ae7703b00f9f094edd7dbd198210129b2bb307e8cd34d689d101e4d685f1259e42af7ce252944ca46aecca60752"
+ ) {
+ throw Error("Welcome to Amazing Fuzzing!");
+ }
+};
+
+module.exports.fuzzMeHashed = fuzzMeHashed;
+
module.exports.asyncFuzzMe = (data) =>
new Promise((resolve, reject) => {
try {
@@ -52,6 +74,13 @@ module.exports.asyncTimeout = (data) =>
// Never resolve this promise to provoke a timeout.
});
+module.exports.syncTimeout = (data) => {
+ // eslint-disable-next-line no-constant-condition
+ while (true) {
+ /* empty */
+ }
+};
+
// noinspection JSUnusedLocalSymbols
module.exports.callbackTimeout = (data, done) => {
// Never call done to provoke a timeout.
diff --git a/tests/jest_integration/jest_project_ts/integration.fuzz.ts b/tests/jest_integration/jest_project_ts/integration.fuzz.ts
index 20a437ac4..a5fd9fead 100644
--- a/tests/jest_integration/jest_project_ts/integration.fuzz.ts
+++ b/tests/jest_integration/jest_project_ts/integration.fuzz.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,4 +37,32 @@ describe("Jest TS Integration", () => {
target.callbackFuzzMe(data, done);
},
);
+
+ it.fuzz(
+ "execute sync hashed fuzz test with dictionary",
+ (data: Buffer) => {
+ target.fuzzMeHashed(data);
+ },
+ {
+ dictionaryEntries: ["Amazing"],
+ },
+ );
+
+ describe("Further options", () => {
+ let i = 0;
+ it.fuzz(
+ "sync, number of runs, dictionary is Amazing",
+ (data: Buffer) => {
+ if (i === 100) {
+ console.log("i = " + i);
+ }
+ i++;
+ },
+ {
+ sync: true,
+ fuzzerOptions: ["-runs=101"],
+ dictionaryEntries: ["Amazing"],
+ },
+ );
+ });
});
diff --git a/tests/jest_integration/jest_project_ts/jest.config.ts b/tests/jest_integration/jest_project_ts/jest.config.ts
index f27e0e8c0..74edadb12 100644
--- a/tests/jest_integration/jest_project_ts/jest.config.ts
+++ b/tests/jest_integration/jest_project_ts/jest.config.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/jest_integration/jest_project_ts/target.ts b/tests/jest_integration/jest_project_ts/target.ts
index c561148cb..a6f9bc622 100644
--- a/tests/jest_integration/jest_project_ts/target.ts
+++ b/tests/jest_integration/jest_project_ts/target.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+import * as crypto from "crypto";
+
export function fuzzMe(data: Buffer) {
if (typeof data === "object") {
if (data.toString() === "Awesome") {
@@ -54,3 +56,21 @@ export async function asyncFuzzMe(data: Buffer) {
});
});
}
+
+export function fuzzMeHashed(data: Buffer) {
+ const s = data.toString();
+ if (s.length !== 7) {
+ return;
+ }
+
+ const sha = crypto.createHash("sha512").update(s);
+ const result = sha.digest("hex");
+
+ // Hash of "Amazing"
+ if (
+ result ===
+ "79328e1e1272ff2890ff0c6e8181a52ce5960ae7703b00f9f094edd7dbd198210129b2bb307e8cd34d689d101e4d685f1259e42af7ce252944ca46aecca60752"
+ ) {
+ throw Error("Welcome to Amazing Fuzzing!");
+ }
+}
diff --git a/tests/promise/fuzz.js b/tests/promise/fuzz.js
index 015f4574d..62fb53f95 100644
--- a/tests/promise/fuzz.js
+++ b/tests/promise/fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/promise/package.json b/tests/promise/package.json
index 5fdb3f90e..0ec55ccc3 100644
--- a/tests/promise/package.json
+++ b/tests/promise/package.json
@@ -3,7 +3,7 @@
"version": "1.0.0",
"description": "An example showing how Jazzer.js handles promise based fuzz targets",
"scripts": {
- "fuzz": "jazzer fuzz --fuzz_function fuzz_promise -x Error -- -runs=5000 -seed=3088388356",
+ "fuzz": "jazzer fuzz --fuzz_function fuzz_promise --disableBugDetectors='.*' -x Error -- -runs=5000 -seed=3088388356",
"dryRun": "jazzer fuzz --fuzz_function fuzz_promise -- -runs=1 -seed=123456789"
},
"devDependencies": {
diff --git a/tests/return_values/asyncRunnerAsyncReturns/fuzz.js b/tests/return_values/asyncRunnerAsyncReturns/fuzz.js
index fc65797af..e0fd7da4f 100644
--- a/tests/return_values/asyncRunnerAsyncReturns/fuzz.js
+++ b/tests/return_values/asyncRunnerAsyncReturns/fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/return_values/asyncRunnerMixedReturns/fuzz.js b/tests/return_values/asyncRunnerMixedReturns/fuzz.js
index 5302c5f70..918bdbf09 100644
--- a/tests/return_values/asyncRunnerMixedReturns/fuzz.js
+++ b/tests/return_values/asyncRunnerMixedReturns/fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/return_values/asyncRunnerSyncReturns/fuzz.js b/tests/return_values/asyncRunnerSyncReturns/fuzz.js
index 9dec24391..911c140a6 100644
--- a/tests/return_values/asyncRunnerSyncReturns/fuzz.js
+++ b/tests/return_values/asyncRunnerSyncReturns/fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/return_values/exampleCode/code.js b/tests/return_values/exampleCode/code.js
index c9b2298de..5b6f2a9bb 100644
--- a/tests/return_values/exampleCode/code.js
+++ b/tests/return_values/exampleCode/code.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/return_values/package.json b/tests/return_values/package.json
index 10e621595..612bb4743 100644
--- a/tests/return_values/package.json
+++ b/tests/return_values/package.json
@@ -3,7 +3,8 @@
"version": "1.0.0",
"description": "Unit tests for detection of sync and async behavior.",
"scripts": {
- "fuzz": "jest"
+ "fuzz": "jest",
+ "test": "jest"
},
"devDependencies": {
"@jazzer.js/core": "file:../../packages/core/"
diff --git a/tests/return_values/return_values.test.js b/tests/return_values/return_values.test.js
index 91c0304a8..7476f1919 100644
--- a/tests/return_values/return_values.test.js
+++ b/tests/return_values/return_values.test.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -66,6 +66,7 @@ describe("Execute a async runner", () => {
function executeFuzzTest(sync, verbose, dir) {
const fuzzTest = new FuzzTestBuilder()
.fuzzEntryPoint("fuzz")
+ .disableBugDetectors([".*"])
.runs(5000)
.dir(dir)
.sync(sync)
diff --git a/tests/return_values/syncRunnerAsyncReturns/fuzz.js b/tests/return_values/syncRunnerAsyncReturns/fuzz.js
index fc65797af..e0fd7da4f 100644
--- a/tests/return_values/syncRunnerAsyncReturns/fuzz.js
+++ b/tests/return_values/syncRunnerAsyncReturns/fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/return_values/syncRunnerMixedReturns/fuzz.js b/tests/return_values/syncRunnerMixedReturns/fuzz.js
index 5302c5f70..918bdbf09 100644
--- a/tests/return_values/syncRunnerMixedReturns/fuzz.js
+++ b/tests/return_values/syncRunnerMixedReturns/fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/return_values/syncRunnerSyncReturns/fuzz.js b/tests/return_values/syncRunnerSyncReturns/fuzz.js
index 9dec24391..911c140a6 100644
--- a/tests/return_values/syncRunnerSyncReturns/fuzz.js
+++ b/tests/return_values/syncRunnerSyncReturns/fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/signal_handlers/SIGINT/fuzz.js b/tests/signal_handlers/SIGINT/fuzz.js
index d91ab76b2..e833d71cb 100644
--- a/tests/signal_handlers/SIGINT/fuzz.js
+++ b/tests/signal_handlers/SIGINT/fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,7 +27,20 @@ module.exports.SIGINT_SYNC = (data) => {
i++;
};
-module.exports.SIGINT_ASYNC = (data) => {
+module.exports.SIGINT_SYNC_endless_loop = (data) => {
+ // eslint-disable-next-line no-constant-condition
+ while (true) {
+ if (i === 1000 || i === 1001) {
+ process.kill(process.pid, "SIGINT");
+ }
+ if (i > 1001) {
+ console.error("Signal has not stopped the fuzzing process");
+ }
+ i++;
+ }
+};
+
+module.exports.SIGINT_ASYNC = async (data) => {
// Raising SIGINT in async mode does not stop the fuzzer directly,
// as the event is handled asynchronously in the event loop.
if (i === 1000) {
@@ -36,3 +49,16 @@ module.exports.SIGINT_ASYNC = (data) => {
}
i++;
};
+
+module.exports.SIGINT_ASYNC_endless_loop = async (data) => {
+ // eslint-disable-next-line no-constant-condition
+ while (true) {
+ if (i === 1000 || i === 1001) {
+ process.kill(process.pid, "SIGINT");
+ }
+ if (i > 1001) {
+ console.error("Signal has not stopped the fuzzing process");
+ }
+ i++;
+ }
+};
diff --git a/tests/signal_handlers/SIGINT/tests.fuzz.js b/tests/signal_handlers/SIGINT/tests.fuzz.js
index 51e7bad17..f9a51faad 100644
--- a/tests/signal_handlers/SIGINT/tests.fuzz.js
+++ b/tests/signal_handlers/SIGINT/tests.fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,9 +14,11 @@
* limitations under the License.
*/
-const { SIGINT_SYNC, SIGINT_ASYNC } = require("./fuzz.js");
+const fuzz = require("./fuzz.js");
describe("Jest", () => {
- it.fuzz("Sync", SIGINT_SYNC);
- it.fuzz("Async", SIGINT_ASYNC);
+ it.fuzz("Sync", fuzz.SIGINT_SYNC);
+ it.fuzz("Sync endless loop", fuzz.SIGINT_SYNC_endless_loop);
+ it.fuzz("Async", fuzz.SIGINT_ASYNC);
+ it.fuzz("Async endless loop", fuzz.SIGINT_ASYNC_endless_loop);
});
diff --git a/tests/signal_handlers/SIGSEGV/fuzz.js b/tests/signal_handlers/SIGSEGV/fuzz.js
index b85077aff..470aea3b9 100644
--- a/tests/signal_handlers/SIGSEGV/fuzz.js
+++ b/tests/signal_handlers/SIGSEGV/fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/signal_handlers/SIGSEGV/tests.fuzz.js b/tests/signal_handlers/SIGSEGV/tests.fuzz.js
index 8072c3bc8..65be81513 100644
--- a/tests/signal_handlers/SIGSEGV/tests.fuzz.js
+++ b/tests/signal_handlers/SIGSEGV/tests.fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/signal_handlers/native-signal/index.ts b/tests/signal_handlers/native-signal/index.ts
index 361343525..564d7b247 100644
--- a/tests/signal_handlers/native-signal/index.ts
+++ b/tests/signal_handlers/native-signal/index.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/signal_handlers/signal_handlers.test.js b/tests/signal_handlers/signal_handlers.test.js
index 2f780ff38..950d4cc7d 100644
--- a/tests/signal_handlers/signal_handlers.test.js
+++ b/tests/signal_handlers/signal_handlers.test.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@ describe("SIGINT handlers", () => {
const testProjectDir = path.join(__dirname, "SIGINT");
fuzzTestBuilder = new FuzzTestBuilder()
.runs(20000)
+ .disableBugDetectors([".*"])
.dir(testProjectDir)
.coverage(true)
.verbose(true);
@@ -58,6 +59,26 @@ describe("SIGINT handlers", () => {
fuzzTest.execute();
expectSigintOutput(fuzzTest);
});
+ it("stop sync fuzzing on SIGINT in endless loop", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .sync(true)
+ .timeout(5000)
+ .fuzzEntryPoint("SIGINT_SYNC_endless_loop")
+ .build();
+ fuzzTest.execute();
+ expectNoCrashFileLogged(fuzzTest);
+ expectFuzzingStopped(fuzzTest);
+ });
+ it("stop async fuzzing on SIGINT in endless loop", async () => {
+ const fuzzTest = fuzzTestBuilder
+ .sync(false)
+ .timeout(5000)
+ .fuzzEntryPoint("SIGINT_ASYNC_endless_loop")
+ .build();
+ fuzzTest.execute();
+ expectNoCrashFileLogged(fuzzTest);
+ expectFuzzingStopped(fuzzTest);
+ });
});
describe("in Jest fuzzing mode", () => {
@@ -79,6 +100,26 @@ describe("SIGINT handlers", () => {
fuzzTest.execute();
expectSigintOutput(fuzzTest);
});
+ it("stop sync endless loop fuzzing on SIGINT", () => {
+ const fuzzTest = fuzzTestBuilder
+ .jestTestFile("tests.fuzz.js")
+ .jestTestName("^Jest Sync endless loop$")
+ .jestRunInFuzzingMode(true)
+ .build();
+ fuzzTest.execute();
+ expectNoCrashFileLogged(fuzzTest);
+ expectFuzzingStopped(fuzzTest);
+ });
+ it("stop async endless loop fuzzing on SIGINT", () => {
+ const fuzzTest = fuzzTestBuilder
+ .jestTestFile("tests.fuzz.js")
+ .jestTestName("^Jest Async endless loop$")
+ .jestRunInFuzzingMode(true)
+ .build();
+ fuzzTest.execute();
+ expectNoCrashFileLogged(fuzzTest);
+ expectFuzzingStopped(fuzzTest);
+ });
});
});
@@ -90,6 +131,7 @@ describe("SIGSEGV handlers", () => {
const testProjectDir = path.join(__dirname, "SIGSEGV");
fuzzTestBuilder = new FuzzTestBuilder()
.runs(20000)
+ .disableBugDetectors([".*"])
.dir(testProjectDir)
.coverage(true);
await cleanCrashFilesIn(testProjectDir);
diff --git a/tests/string_compare/fuzz.js b/tests/string_compare/fuzz.js
index ef579cfaa..f92ec89ba 100644
--- a/tests/string_compare/fuzz.js
+++ b/tests/string_compare/fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/string_compare/package.json b/tests/string_compare/package.json
index 7053fe53c..76b5fbd16 100644
--- a/tests/string_compare/package.json
+++ b/tests/string_compare/package.json
@@ -3,7 +3,7 @@
"version": "1.0.0",
"description": "An example showing how Jazzer.js handles string comparisons in the code",
"scripts": {
- "fuzz": "jazzer fuzz --sync -x Error -- -runs=5000000 -seed=111994470",
+ "fuzz": "jazzer fuzz --sync --disableBugDetectors='.*' -x Error -- -runs=5000000 -seed=111994470",
"dryRun": "jazzer fuzz --sync -- -runs=100 -seed=123456789"
},
"devDependencies": {
diff --git a/tests/switch/package.json b/tests/switch/package.json
deleted file mode 100644
index 478208a45..000000000
--- a/tests/switch/package.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "name": "jazzerjs-switch-example",
- "version": "1.0.0",
- "description": "An example showing how Jazzer.js handles switch statements",
- "scripts": {
- "fuzz": "jazzer fuzz --sync -x Error -- -runs=2000000 -seed=1148448756",
- "dryRun": "jazzer fuzz --sync -- -runs=100 -seed=123456789"
- },
- "devDependencies": {
- "@jazzer.js/core": "file:../../packages/core"
- }
-}
diff --git a/tests/timeout/fuzz.js b/tests/timeout/fuzz.js
index 19a33fe80..8d63b52bd 100644
--- a/tests/timeout/fuzz.js
+++ b/tests/timeout/fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/timeout/package.json b/tests/timeout/package.json
index d17add0ab..f35a9da32 100644
--- a/tests/timeout/package.json
+++ b/tests/timeout/package.json
@@ -3,7 +3,7 @@
"version": "1.0.0",
"description": "Timeout test: checking that the handler for the SIGALRM signal does not return with error code.",
"scripts": {
- "timeout": "jazzer fuzz -f=timeout --timeout=1000 -- -runs=5000 -seed=1234",
+ "timeout": "jazzer fuzz -f=timeout --timeout=1000 --disableBugDetectors='.*' -- -runs=5000 -seed=1234",
"fuzz": "jazzer fuzz --timeout=1000 -- -runs=5000 -seed=1234",
"dryRun": "echo \"skipped\""
},
diff --git a/tests/value_profiling/fuzz.js b/tests/value_profiling/fuzz.js
index 1f430eb97..29ed21682 100644
--- a/tests/value_profiling/fuzz.js
+++ b/tests/value_profiling/fuzz.js
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Code Intelligence GmbH
+ * Copyright 2026 Code Intelligence GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tests/value_profiling/package.json b/tests/value_profiling/package.json
index 34f8290e1..38b5e9ca9 100644
--- a/tests/value_profiling/package.json
+++ b/tests/value_profiling/package.json
@@ -3,7 +3,7 @@
"version": "1.0.0",
"description": "An example showing how Jazzer.js handles integer comparisons in the code",
"scripts": {
- "fuzz": "jazzer fuzz --sync -x Error -- -runs=4000000 -seed=1428686921 -use_value_profile=1",
+ "fuzz": "jazzer fuzz --sync --disableBugDetectors='.*' -x Error -- -runs=4000000 -seed=1428686921 -use_value_profile=1",
"dryRun": "jazzer fuzz --sync -- -use_value_profile=1 -runs=100 -seed=123456789"
},
"devDependencies": {