### Install Swift Protobuf Compiler Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Sources/Fuzzilli/Protobuf/README.md Installs the necessary protoc compiler and Swift plugin via Homebrew. ```bash brew install swift-protobuf ``` -------------------------------- ### Install Parser Dependencies Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Sources/Fuzzilli/Compiler/Parser/README.md Install the necessary dependencies for the parser using npm. Ensure Node.js is installed and in your system's PATH. ```bash npm i ``` -------------------------------- ### Get Fuzzilli CLI Help Source: https://github.com/googleprojectzero/fuzzilli/blob/main/README.md Display help information for the Fuzzilli CLI, including available options and commands. ```bash swift run FuzzilliCli --help ``` -------------------------------- ### Define a FuzzIL program Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/HowFuzzilliWorks.md Example of a FuzzIL program structure using operations, variables, and block definitions. ```text v0 <- BeginPlainFunctionDefinition -> v1, v2, v3 v4 <- BinaryOperation v1 '+' v2 SetProperty v3, 'foo', v4 EndPlainFunctionDefinition v5 <- LoadString "Hello World" v6 <- CreateObject ['bar': v5] v7 <- LoadFloat 13.37 v8 <- CallFunction v0, [v7, v7, v6] ``` -------------------------------- ### FuzzIL Intermediate Language Example Source: https://github.com/googleprojectzero/fuzzilli/blob/main/README.md Illustrates the structure of FuzzIL's intermediate language, showing operations, variables, and parameters. ```plaintext v0 <− LoadInteger '0' v1 <− LoadInteger '10' v2 <− LoadInteger '1' v3 <− LoadInteger '0' BeginFor v0, '<', v1, '+', v2 −> v4 v6 <− BinaryOperation v3, '+', v4 Reassign v3, v6 EndFor v7 <− LoadString 'Result: ' v8 <− BinaryOperation v7, '+', v3 v9 <− LoadGlobal 'console' v10 <− CallMethod v9, 'log', [v8] ``` -------------------------------- ### Lift FuzzIL to JavaScript Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/HowFuzzilliWorks.md Examples of how FuzzIL code is translated into JavaScript using different lifting strategies. ```javascript function f0(a1, a2, a3) { a3.foo = a1 + a2; } const v6 = {bar: "Hello World"}; f0(13.37, 13.37, v6); ``` ```javascript function f0(a1, a2, a3) { const v4 = a1 + a2; a3.foo = v4; } const v5 = "Hello World"; const v6 = {bar: v5}; const v7 = 13.37; const v8 = f0(v7, v7, v6); ``` -------------------------------- ### Input Mutator Example Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/HowFuzzilliWorks.md Replaces an input to an instruction with another randomly chosen one. This mutation is simple due to FuzzIL's variable-based input design. ```fuzzil SetProperty v3, 'foo', v4 ``` ```fuzzil SetProperty v3, 'foo', v2 ``` -------------------------------- ### Example of Invalid FuzzIL Code Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/HowFuzzilliWorks.md Demonstrates a generated instruction sequence that triggers a TypeError because the variable is not a function. ```text v3 <- LoadString "foobar" v4 <- CallFunction v3, [] // TypeError: v3 is not a function ``` -------------------------------- ### Operation Mutator Example Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/HowFuzzilliWorks.md Mutates the parameters of an operation. This example shows changing the operator in a binary operation. ```fuzzil v4 <- BinaryOperation v1 '+' v2 ``` ```fuzzil v4 <- BinaryOperation v1 '/' v2 ``` -------------------------------- ### Inspect FuzzIL Type Representations Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/HowFuzzilliWorks.md Examples of how common JavaScript values are represented within the FuzzIL type system. ```javascript let v0 = "foobar"; // .string + .object(...) + .array // the object part contains all the standard string methods and properties let v0 = { valueOf() { ...; return 13.37; }}; // .object(...) + .float // The object can be used for numerical operations since it has a meaningful // conversion operator defined (a custom valueOf method with known signature). // Note: this is not yet implemented, currently the type would just be .object let v0 = [...]; // .array + .object(...) // the JavaScript array is clearly an array (can be iterated over) but also // exposes properties and methods and as such is also an object class v0 { ... foo() { ... }; bar() { ... } }; // .constructor([...] => .object(...)) // The variable v0 is a constructor with the parameters indicated by its // constructor and which returns an object of the v0 "group" with certain // properties and methods (e.g. foo and bar) ``` -------------------------------- ### Example of nested function structure Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/HowFuzzilliWorks.md This structure illustrates the type of code patterns that the inlining reducer attempts to simplify. ```javascript function v1(...) { function v2(...) { function v3(...) { } v3(...); } v2(...); } v1(...); ``` -------------------------------- ### JavaScript Function Definition with Typed Parameters Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/HowFuzzilliWorks.md Shows a pseudocode example of a JavaScript function with explicitly typed parameters (Number, JSArray) and a return type (JSArray), enabling meaningful use of arguments. ```javascript function foo(v4: Number, v5: JSArray) -> JSArray { // Can make meaningful use of v4 and v5 here ...; } ``` -------------------------------- ### Splicing: Simple Code Insertion Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/HowFuzzilliWorks.md Copies a self-contained part of one program into another. Variables are renamed to avoid collisions. This example shows inserting instructions related to loading a float and calling a Math method. ```fuzzil v0 <- LoadInt '42' v1 <- LoadFloat '13.37' v2 <- LoadBuiltin 'Math' v3 <- CallMethod v2, 'sin', [v1] v4 <- CreateArray [v3, v3] ``` ```fuzzil ... existing code v13 <- LoadFloat '13.37' v14 <- LoadBuiltin 'Math' v15 <- CallMethod v14, 'sin', [v13] ... existing code ``` -------------------------------- ### Define Simple Value Code Generator Source: https://context7.com/googleprojectzero/fuzzilli/llms.txt Create a basic CodeGenerator that produces integer values by loading a random integer. This is a starting point for more complex generators. ```swift let IntegerGenerator = CodeGenerator("IntegerGenerator", produces: [.integer]) { b in b.loadInt(b.randomInt()) } ``` -------------------------------- ### Example of Meaningless JavaScript Operation Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/HowFuzzilliWorks.md This JavaScript code demonstrates a semantically meaningless operation that results in NaN, highlighting a scenario Fuzzilli aims to avoid generating frequently. ```javascript let v0 = ...; let v1 = v0 / {}; ``` -------------------------------- ### Initialize Qt Submodules Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Targets/QTJS/README.md Navigate into the cloned Qt directory and initialize its submodules. This step is crucial for obtaining all necessary components. ```bash cd qt6 && perl init-repository ``` -------------------------------- ### Build QuickJS for Fuzzing Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Targets/QJS/README.md Commands to prepare the QuickJS environment for Fuzzilli. ```bash git clone https://github.com/bellard/quickjs ``` ```bash make qjs ``` -------------------------------- ### Execute and Evaluate FuzzIL Programs Source: https://context7.com/googleprojectzero/fuzzilli/llms.txt Demonstrates the lifecycle of a FuzzIL program including execution, outcome handling, coverage evaluation, and corpus import logic. ```swift // Execute a program let program = fuzzer.makeBuilder().finalize() let execution = fuzzer.execute(program, purpose: .fuzzing) // Check execution outcome switch execution.outcome { case .succeeded: print("Program executed successfully") print("Stdout: \(execution.stdout)") print("Execution time: \(execution.execTime)s") case .failed: print("Program failed (threw exception)") print("Stderr: \(execution.stderr)") case .crashed(let signal): print("Program crashed with signal \(signal)") print("Stderr: \(execution.stderr)") case .timedOut: print("Program timed out") case .differential: print("Differential behavior between optimized/unoptimized execution") } // Evaluate program for interestingness (coverage) if let aspects = fuzzer.evaluator.evaluate(execution) { print("Program is interesting! Triggered \(aspects.count) new aspects") // Process and potentially add to corpus fuzzer.processMaybeInteresting(program, havingAspects: aspects, origin: .local) } // Import an external program let importResult = fuzzer.importProgram(program, origin: .corpusImport(mode: .default)) switch importResult { case .imported: print("Program was imported into corpus") case .dropped: print("Program was dropped (not interesting)") case .failed(let outcome): print("Import failed: \(outcome)") case .needsWasm: print("Program requires WASM support") case .needsBundles: print("Program requires bundle support") } ``` -------------------------------- ### Build Fuzzing Harness Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Targets/QTJS/README.md Execute the fuzzbuild.sh script from the root directory of the Qt6 build. This script compiles the fuzzing harness. ```bash fuzzbuild.sh in the qt6 root directory ``` -------------------------------- ### Clone and Build Spidermonkey Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Targets/Spidermonkey/README.md Commands to prepare the Spidermonkey environment for fuzzing. ```bash git clone https://github.com/mozilla/gecko-dev cd gecko-dev ./fuzzbuild.sh ``` -------------------------------- ### Generate Swift Files Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Sources/Fuzzilli/Protobuf/README.md Generates Swift source files from the project's Protobuf definition files. ```bash protoc --swift_opt=Visibility=Public --swift_out=. program.proto operations.proto sync.proto ast.proto ``` -------------------------------- ### Define Program Templates Source: https://context7.com/googleprojectzero/fuzzilli/llms.txt Create custom templates for the HybridEngine to generate structured test cases, then register them with weights. ```swift // Basic code generation template let BasicTemplate = ProgramTemplate("BasicTemplate") { b in b.buildPrefix() // Generate initial variables b.build(n: 50) // Generate 50 random instructions } // JIT function template targeting JIT compiler bugs let JITFunctionTemplate = ProgramTemplate("JITFunction") { b in // Generate prefix with random initial values b.buildPrefix() b.build(n: 5) // Generate a function with random parameters let f = b.buildPlainFunction(with: b.randomParameters()) { args in b.build(n: 30) // Random function body b.doReturn(b.randomJsVariable()) } // Trigger JIT compilation by calling many times b.buildRepeatLoop(n: 100) { _ in b.callFunction(f, withArgs: b.randomArguments(forCalling: f)) } // Call again with different arguments (type confusion potential) b.build(n: 5) b.callFunction(f, withArgs: b.randomArguments(forCalling: f)) } // Prototype manipulation template let PrototypeTemplate = ProgramTemplate("PrototypeMutation") { b in b.buildPrefix() // Create an object and function let obj = b.createObject(with: ["a": b.loadInt(42)]) let proto = b.getProperty("__proto__", of: obj) // Generate a function that accesses object properties let f = b.buildPlainFunction(with: .parameters(n: 1)) { args in b.getProperty("a", of: args[0]) b.build(n: 10) } // JIT compile the function b.buildRepeatLoop(n: 100) { _ in b.callFunction(f, withArgs: [obj]) } // Mutate prototype (potential for deoptimization bugs) b.setProperty("b", of: proto, to: b.loadInt(1337)) // Call again after prototype mutation b.callFunction(f, withArgs: [obj]) } // Callback-triggering template let CallbackTemplate = ProgramTemplate("Callbacks") { b in b.buildPrefix() b.build(n: 10) // Create object with valueOf callback b.buildObjectLiteral { lit in lit.addMethod("valueOf", with: .parameters(n: 0)) { _ in b.build(n: 5) b.doReturn(b.loadInt(42)) } } b.build(n: 20) } // Register templates with weights let programTemplates = WeightedList([ (BasicTemplate, 10), (JITFunctionTemplate, 15), (PrototypeTemplate, 10), (CallbackTemplate, 5), ]) ``` -------------------------------- ### Clone Qt Repository Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Targets/QTJS/README.md Clone the Qt repository to obtain the necessary code for Qt5 and Qt6. The qt5 repository contains code for both versions. ```bash git clone git://code.qt.io/qt/qt5.git qt6 ``` -------------------------------- ### Initialize Fuzzer Instance Source: https://context7.com/googleprojectzero/fuzzilli/llms.txt Configure and instantiate a Fuzzer object with custom runners, engines, and environment settings in Swift. ```swift import Fuzzilli // Create configuration let config = Configuration( arguments: CommandLine.arguments, timeout: 250, logLevel: .info, startupTests: [("fuzzilli('FUZZILLI_PRINT', 'test')", .shouldSucceed)], minimizationLimit: 0.0, enableDiagnostics: false, enableInspection: true, staticCorpus: false, tag: "v8-fuzzing", isWasmEnabled: false, generateBundle: false, storagePath: "/tmp/fuzz_output", corpusGenerationIterations: 100, forDifferentialFuzzing: false, instanceId: 0, dumplingEnabled: false ) // Create script runner (REPRL) let runner = REPRL( executable: "/path/to/d8", processArguments: ["--allow-natives-syntax", "--reprl"], processEnvironment: [:], maxExecsBeforeRespawn: 1000 ) // Create mutation engine let engine = MutationEngine(numConsecutiveMutations: 5) // Create mutators let mutators = WeightedList([ (ExplorationMutator(), 3), (CodeGenMutator(), 2), (SpliceMutator(), 2), (InputMutator(typeAwareness: .loose), 2), (OperationMutator(), 1), (CombineMutator(), 1), ]) // Create environment and lifter let environment = JavaScriptEnvironment( additionalBuiltins: [:], additionalObjectGroups: [], additionalEnumerations: [] ) let lifter = JavaScriptLifter( prefix: "", suffix: "", ecmaVersion: .es6, environment: environment ) // Create corpus and evaluator let corpus = BasicCorpus(minSize: 1000, maxSize: Int.max, minMutationsPerSample: 25) let evaluator = ProgramCoverageEvaluator(runner: runner) let minimizer = Minimizer() // Construct the fuzzer let fuzzer = Fuzzer( configuration: config, scriptRunner: runner, referenceScriptRunner: nil, engine: engine, mutators: mutators, codeGenerators: codeGenerators, programTemplates: programTemplates, evaluator: evaluator, environment: environment, lifter: lifter, corpus: corpus, minimizer: minimizer ) // Initialize and start fuzzer.sync { fuzzer.addModule(Statistics()) fuzzer.addModule(Storage(for: fuzzer, storageDir: "/tmp/fuzz_output")) fuzzer.initialize() fuzzer.runStartupTests(with: .value(250)) fuzzer.start(runUntil: .iterationsPerformed(1000000)) } ``` -------------------------------- ### Define Engine Profiles Source: https://context7.com/googleprojectzero/fuzzilli/llms.txt Configure engine-specific settings, builtins, and startup tests for different JavaScript engines. ```swift let v8Profile = Profile( processArgs: { randomize in var args = [ "--expose-gc", "--omit-quit", "--allow-natives-syntax", "--fuzzing", "--jit-fuzzing", "--future", "--harmony", "--reprl", ] if randomize { args.append("--no-lazy=\(probability(0.5) ? "true" : "false")") args.append("--no-flush-bytecode=\(probability(0.5) ? "true" : "false")") } return args }, processArgsReference: nil, processEnv: ["UBSAN_OPTIONS": "handle_segv=0"], maxExecsBeforeRespawn: 1000, timeout: Timeout.value(250), codePrefix: "", codeSuffix: "gc();", ecmaVersion: ECMAScriptVersion.es6, startupTests: [ ("fuzzilli('FUZZILLI_PRINT', 'test')", .shouldSucceed), ("fuzzilli('FUZZILLI_CRASH', 0)", .shouldCrash), ], additionalCodeGenerators: [ (ForceJITCompilationGenerator, 10), (GcGenerator, 5), ], additionalProgramTemplates: WeightedList([ (MapTransitionTemplate, 5), ]), disabledCodeGenerators: [], disabledMutators: [], additionalBuiltins: [ "gc": .function([] => .undefined), "%OptimizeFunctionOnNextCall": .function([.function()] => .undefined), "%PrepareFunctionForOptimization": .function([.function()] => .undefined), "%NeverOptimizeFunction": .function([.function()] => .undefined), "%DeoptimizeFunction": .function([.function()] => .undefined), "%DeoptimizeNow": .function([] => .undefined), "%ClearFunctionFeedback": .function([.function()] => .undefined), ], additionalObjectGroups: [], additionalEnumerations: [], optionalPostProcessor: nil ) // Available profiles let profiles: [String: Profile] = [ "jsc": jscProfile, "spidermonkey": spidermonkeyProfile, "v8": v8Profile, "duktape": duktapeProfile, "jerryscript": jerryscriptProfile, ] ``` -------------------------------- ### Define a ProgramTemplate for JIT testing Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/HowFuzzilliWorks.md Defines a template that generates a function, triggers JIT compilation, and executes the function repeatedly. ```swift ProgramTemplate("JITFunction") { b in // Start with a random prefix and some random code. b.buildPrefix() b.build(n: 5) // Generate a larger function and a signature for it let f = b.buildPlainFunction(with: b.randomParameters()) { args in assert(args.count > 0) b.build(n: 30) b.doReturn(b.randomJsVariable()) } // Trigger JIT optimization b.buildRepeatLoop(n: 100) { _ in b.callFunction(f, withArgs: b.randomArguments(forCalling: f)) } ``` -------------------------------- ### Build NJS for Fuzzing Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Targets/njs/README.md Commands to configure and compile the NJS target with coverage instrumentation. ```bash ./configure --cc=clang --cc-opt="-g -fsanitize-coverage=trace-pc-guard" ``` ```bash make njs_fuzzilli ``` -------------------------------- ### Construct FuzzIL Programs with ProgramBuilder Source: https://context7.com/googleprojectzero/fuzzilli/llms.txt Use the ProgramBuilder to create FuzzIL instructions, load primitive values, construct arrays and objects, perform property and element operations, and build binary/unary operations. This builder is essential for program construction. ```swift let b = fuzzer.makeBuilder() let int42 = b.loadInt(42) let float = b.loadFloat(13.37) let str = b.loadString("Hello") let bool = b.loadBool(true) let undef = b.loadUndefined() let null = b.loadNull() let arr = b.createArray(with: [int42, float]) let obj = b.createObject(with: ["x": int42, "y": float]) let prop = b.getProperty("x", of: obj) b.setProperty("z", of: obj, to: str) b.deleteProperty("z", of: obj) let elem = b.getElement(0, of: arr) b.setElement(1, of: arr, to: int42) let sum = b.binary(int42, float, with: .Add) let neg = b.unary(.Minus, sum) let cmp = b.compare(int42, with: float, using: .lessThan) ``` ```swift let f = b.buildPlainFunction(with: .parameters(n: 2)) { args in let x = b.getProperty("x", of: args[0]) let y = b.getProperty("y", of: args[0]) let sum = b.binary(x, y, with: .Add) let result = b.binary(sum, args[1], with: .Mul) b.doReturn(result) } ``` ```swift let arg1 = b.createObject(with: ["x": b.loadInt(10), "y": b.loadInt(20)]) let arg2 = b.loadInt(5) let result = b.callFunction(f, withArgs: [arg1, arg2]) ``` ```swift b.buildIfElse(cmp, ifBody: { b.callFunction(f, withArgs: [arg1, arg2]) }, elseBody: { b.loadInt(0) }) ``` ```swift b.buildRepeatLoop(n: 100) { i in b.callFunction(f, withArgs: [arg1, i]) } ``` ```swift b.buildForInLoop(obj) { key in let val = b.getComputedProperty(key, of: obj) b.callFunction(f, withArgs: [val, b.loadInt(1)]) } ``` ```swift b.buildTryCatchFinally(tryBody: { let exception = b.loadInt(42) b.throwException(exception) }, catchBody: { error in b.loadString("caught error") }) ``` ```swift let program = b.finalize() let js = fuzzer.lifter.lift(program) print(js) ``` -------------------------------- ### Apply Patches for Fuzzing Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Targets/QTJS/README.md Apply the provided patches from the qtdeclarative/ submodule. Ensure these patches are compatible with the specified git revision. ```bash Apply Patches/* from within the qtdeclarative/ submodule. ``` -------------------------------- ### Profile Configuration Fields Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Targets/README.md Detailed explanation of each configurable field within a Fuzzilli profile. ```APIDOC ## Profile Fields This section describes the various fields that can be configured within a Fuzzilli profile to customize its behavior. ### `processArgs` **Description**: Command line arguments to call the Javascript engine with. ### `processEnv` **Description**: Environment variables to set when calling the Javascript engine. ### `maxExecsBeforeRespawn` **Description**: How many samples to execute in the same target process (via REPRL) before starting a fresh process. ### `timeout` **Description**: The timeout in milliseconds after which to terminate the target process. ### `codePrefix` and `codeSuffix` **Description**: Javascript code that is added to the beginning/end of each generated test case. This can setup and call `main`, force garbage collection, etc. ### `startupTests` **Description**: Functions to call to test that the engine behaves as expected and that crashes are detected. ### `additionalCodeGenerators` **Description**: Additional code generators, called the fuzzer in building test cases. An example use case is producing code to trigger JIT compilation in V8. ### `additionalProgramTemplates` **Description**: Additional [program templates](../Docs/HowFuzzilliWorks.md#program-templates) for the fuzzer to generate programs from. Examples for ProgramTemplates can be found in [ProgramTemplates.swift](../Sources/Fuzzilli/CodeGen/ProgramTemplates.swift). ### `disabledCodeGenerators` **Description**: List of code generators to disable. The current list of code generators is in [CodeGenerators.swift](../Sources/Fuzzilli/CodeGen/CodeGenerators.swift) with their respective weights in [CodeGeneratorWeights.swift](../Sources/Fuzzilli/CodeGen/CodeGeneratorWeights.swift). ### `disabledMutators` **Description**: List of mutators to disable, in other words, the mutators in this list will not be selected to mutate input during the fuzzing loop. The current list of enabled mutators is in [FuzzilliCli/main.swift](../Sources/FuzzilliCli/main.swift). ### `additionalBuiltins` **Description**: Additional unique builtins for the JS engine. The list does not have to be exhaustive, but should include functionality likely to cause bugs. An example would be a function that triggers garbage collection. ### `additionalObjectGroups` **Description**: Additional unique [ObjectGroup](../Sources/Fuzzilli/Environment/JavaScriptEnvironment.swift)s for the JS engine. Examples for ObjectGroups can be found in [JavaScriptEnvironment.swift](../Sources/Fuzzilli/Environment/JavaScriptEnvironment.swift). ### `optionalPostProcessor` **Description**: An optional post-processor which can modify generated programs before executing them on the target. ``` -------------------------------- ### Run Fuzzilli CLI Source: https://context7.com/googleprojectzero/fuzzilli/llms.txt Execute the Fuzzilli CLI with various configurations for profiles, engines, and distributed fuzzing modes. ```bash # Basic fuzzing with a profile swift run -c release FuzzilliCli --profile=jsc /path/to/jsc # Multi-job fuzzing (parallel instances) swift run -c release FuzzilliCli --profile=v8 --jobs=8 /path/to/d8 # Fuzzing with hybrid engine and storage swift run -c release FuzzilliCli \ --profile=spidermonkey \ --engine=hybrid \ --storagePath=/tmp/fuzz_output \ --timeout=500 \ /path/to/js # Distributed fuzzing as root node swift run -c release FuzzilliCli \ --profile=v8 \ --instanceType=root \ --bindTo=0.0.0.0:1337 \ --storagePath=/tmp/fuzzer \ /path/to/d8 # Distributed fuzzing as leaf node swift run -c release FuzzilliCli \ --profile=v8 \ --instanceType=leaf \ --connectTo=192.168.1.100:1337 \ /path/to/d8 # Import existing corpus and resume swift run -c release FuzzilliCli \ --profile=jsc \ --importCorpus=/path/to/corpus \ --corpusImportMode=default \ --storagePath=/tmp/fuzz_output \ /path/to/jsc # Enable inspection mode for debugging swift run -c release FuzzilliCli \ --profile=v8 \ --inspect \ --diagnostics \ --logLevel=verbose \ /path/to/d8 ``` -------------------------------- ### Auto-generate program.proto Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Sources/Fuzzilli/Protobuf/README.md Runs the Python script to update program.proto after adding new IL operations. ```bash python3 ./gen_programproto.py ``` -------------------------------- ### Attach to a running Fuzzilli session Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Cloud/GCE/README.md Connects to the root instance and attaches to the Docker container to view statistics. ```bash gcloud compute ssh $SESSION-root # Now on the GCE instance docker ps # Copy the container name # Disable the sig proxy so ctrl-c detaches and doesn't stop Fuzzilli docker attach --sig-proxy=false $CONTAINER ``` -------------------------------- ### Build XS Test Tool (xst) Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Targets/XS/README.md Build the `xst` tool using the Moddable SDK makefiles. Ensure the FUZZILLI environment variable is set to 1. This command is specific to macOS. ```console cd $MODDABLE/xs/makefiles/mac FUZZILLI=1 make ``` -------------------------------- ### Convert FuzzIL protobuf to text Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/HowFuzzilliWorks.md Command-line usage for the FuzzILTool to convert a serialized protobuf program into its textual representation. ```bash swift run FuzzILTool --liftToFuzzIL path/to/program.protobuf ``` -------------------------------- ### Compile Fuzzer with Swift Source: https://github.com/googleprojectzero/fuzzilli/blob/main/README.md Compile the Fuzzilli fuzzer using Swift. Use '-c release' for a release build. ```bash swift build [-c release] ``` -------------------------------- ### Collect crashes from the root instance Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Cloud/GCE/README.md Compresses and downloads crash files from the root GCE instance to the local machine. ```bash NAME=$SESSION-root gcloud compute ssh $NAME --command "cd ~/fuzz/ && sudo tar czf ~/crashes.tgz crashes" gcloud compute scp $NAME:/home/$USER/crashes.tgz . tar xzf ./crashes.tgz && rm crashes.tgz ``` -------------------------------- ### Locate Fuzzing Harness Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Targets/QTJS/README.md The compiled fuzzing harness executable will be located in the qt6/qtdeclarative/examples/qml/shell/shell directory after a successful build. ```bash qt6/qtdeclarative/examples/qml/shell/shell ``` -------------------------------- ### Manipulate FuzzIL Programs with FuzzILTool Source: https://context7.com/googleprojectzero/fuzzilli/llms.txt Use the FuzzILTool command-line interface to lift, check, or compile FuzzIL programs. ```bash # Lift a protobuf program to FuzzIL text representation swift run FuzzILTool --liftToFuzzIL /path/to/program.fzil # Lift a protobuf program to JavaScript swift run FuzzILTool --liftToJS /path/to/program.fzil # Lift with comments included swift run FuzzILTool --liftToJS --includeComments /path/to/program.fzil # Check program validity swift run FuzzILTool --check /path/to/program.fzil # Compile JavaScript to FuzzIL (experimental) swift run FuzzILTool --compile /path/to/script.js --output /path/to/output.fzil ``` -------------------------------- ### Translate FuzzIL to JavaScript (with intermediate variables) Source: https://github.com/googleprojectzero/fuzzilli/blob/main/README.md Shows a direct translation of the FuzzIL IL to JavaScript, preserving intermediate variables. ```javascript const v0 = 0; const v1 = 10; const v2 = 1; let v3 = 0; for (let v4 = v0; v4 < v1; v4 = v4 + v2) { const v6 = v3 + v4; v3 = v6; } const v7 = "Result: "; const v8 = v7 + v3; const v9 = console; const v10 = v9.log(v8); ``` -------------------------------- ### Run Fuzzilli Fuzzer Source: https://github.com/googleprojectzero/fuzzilli/blob/main/README.md Run the Fuzzilli fuzzer with a specified profile and other CLI options. The path to the JavaScript engine shell is required. ```bash swift run [-c release] FuzzilliCli --profile= [other cli options] /path/to/jsshell ``` -------------------------------- ### JavaScript Function Definition with Unknown Parameters Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/HowFuzzilliWorks.md Illustrates a JavaScript function definition where parameter types are initially unknown, posing a challenge for generating meaningful code within the function body. ```javascript function foo(v4, v5) { ... } ``` -------------------------------- ### Implement Custom Instruction Mutators in Swift Source: https://context7.com/googleprojectzero/fuzzilli/llms.txt Define custom mutation logic by subclassing BaseInstructionMutator and register them with weights in a WeightedList. ```swift // Input mutator - changes variable inputs to instructions public class InputMutator: BaseInstructionMutator { public let typeAwareness: TypeAwareness public enum TypeAwareness { case loose // Pick any visible variable case aware // Pick variables with compatible types } public init(typeAwareness: TypeAwareness) { self.typeAwareness = typeAwareness super.init(name: "InputMutator") } public override func canMutate(_ instr: Instruction) -> Bool { return instr.numInputs > 0 } public override func mutate(_ instr: Instruction, _ b: ProgramBuilder) { var inouts = b.adopt(instr.inouts) let selectedInput = Int.random(in: 0.. Bool { return instr.op.isMutable } public override func mutate(_ instr: Instruction, _ b: ProgramBuilder) { let newOp = instr.op.mutate() b.append(Instruction(newOp, inouts: b.adopt(instr.inouts))) } } // Register mutators with weights let mutators = WeightedList([ (ExplorationMutator(), 3), (CodeGenMutator(), 2), (SpliceMutator(), 2), (ProbingMutator(), 2), (InputMutator(typeAwareness: .loose), 2), (InputMutator(typeAwareness: .aware), 1), (OperationMutator(), 1), (CombineMutator(), 1), ]) ``` -------------------------------- ### Translate FuzzIL to JavaScript (inlined) Source: https://github.com/googleprojectzero/fuzzilli/blob/main/README.md Demonstrates a more concise JavaScript translation of the FuzzIL IL by inlining intermediate expressions. ```javascript let v3 = 0; for (let v4 = 0; v4 < 10; v4++) { v3 = v3 + v4; } console.log("Result: " + v3); ``` -------------------------------- ### Manually Invoke JavaScript Parser Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Sources/Fuzzilli/Compiler/Parser/README.md Manually invoke the JavaScript parser from the command line. This command generates a protobuf AST from a JavaScript file. The FuzzIL compiler typically invokes this parser automatically. ```bash node parser.js ../../Protobuf/ast.proto code.js output.ast.proto ``` -------------------------------- ### REPRL Loop Pseudocode Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Targets/README.md High-level logic for implementing the Read-Eval-Print-Reset loop to minimize execution overhead. ```text (Must include the 4 defined File Descriptor numbers REPRL_CRFD, REPRL_CWFD, REPRL_DRFD, REPRL_DWFD) if REPRL_MODE on commandline: write "HELO" on REPRL_CWFD read 4 bytes on REPRL_CRFD break if 4 read bytes do not equal "HELO" optionally, mmap the REPRL_DRFD with size REPRL_MAX_DATA_SIZE while true: read 4 bytes on REPRL_CRFD break if 4 read bytes do not equal "cexe" read 8 bytes on REPRL_CRFD, store as unsigned 64 bit integer size allocate size+1 bytes read size bytes from REPRL_DRFD into allocated buffer, either via memory mapped IO or the read syscall (make sure to account for short reads in the latter case) Execute buffer as javascript code Store return value from JS execution Flush stdout and stderr. As REPRL sets them to regular files, libc uses full bufferring for them, which means they need to be flushed after every execution Mask return value with 0xff and shift it left by 8, then write that value over REPRL_CWFD Reset the Javascript engine Call __sanitizer_cov_reset_edgeguards to reset coverage ``` -------------------------------- ### Define JIT Compilation Trigger Generator Source: https://context7.com/googleprojectzero/fuzzilli/llms.txt Implement an engine-specific CodeGenerator designed to trigger JIT compilation (like DFG). It repeatedly calls a function to encourage optimization. ```swift let ForceDFGCompilationGenerator = CodeGenerator( "ForceDFGCompilationGenerator", inputs: .required(.function()) ) { b, f in let arguments = b.randomArguments(forCalling: f) b.buildRepeatLoop(n: 100) { _ in b.callFunction(f, withArgs: arguments) } } ``` -------------------------------- ### Enqueueing asynchronous tasks to the Fuzzer queue Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/ProcessingModel.md Use the async method to safely interact with a fuzzer instance from a different thread or queue. ```swift fuzzer.async { // Can now interact with the fuzzer         fuzzer.importProgram(someProgram) } ``` -------------------------------- ### Run Fuzzilli Triage Script Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Cloud/Triage/README.md Executes the triage script against a directory of crashes using a specific JS engine build and command-line arguments. ```bash ./check.sh ./crashes ~/WebKit/AsanBuild/Debug/bin/jsc --validateOptions=true --useConcurrentJIT=false --useConcurrentGC=false --thresholdForJITSoon=10 --thresholdForJITAfterWarmUp=10 --thresholdForOptimizeAfterWarmUp=100 --thresholdForOptimizeAfterLongWarmUp=100 --thresholdForOptimizeAfterLongWarmUp=100 --thresholdForFTLOptimizeAfterWarmUp=1000 --thresholdForFTLOptimizeSoon=1000 --gcAtEnd=true ``` -------------------------------- ### JavaScript Function and Loop Generation Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/HowFuzzilliWorks.md Shows the JavaScript code generated from the Fuzzilli intermediate representation, including a function definition and a loop to call it. Includes an initial guarded assignment. ```javascript function f4(a5, a6) { let v8 = bar(); try { v8[a5] = a6; } catch {} return v8; } for (let v9 = 0; v9 < 100; v9++) { f4("foo", 42 * 1337); } ``` -------------------------------- ### Type Inference Rules Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/HowFuzzilliWorks.md Logic for inferring the output types of specific FuzzIL operations like typeof, instanceof, and comparison. ```swift case is TypeOf: set(instr.output, environment.stringType) case is InstanceOf: set(instr.output, environment.booleanType) case is Compare: set(instr.output, environment.booleanType) ``` -------------------------------- ### Define Code Generator with Input Requirements Source: https://context7.com/googleprojectzero/fuzzilli/llms.txt Implement a CodeGenerator for binary operations that requires two number inputs. It includes logic to add a guard for potential bigint operations. ```swift let BinaryOpGenerator = CodeGenerator( "BinaryOpGenerator", inputs: .preferred(.number, .number) ) { b, lhs, rhs in let needGuard = b.type(of: lhs).MayBe(.bigint) || b.type(of: rhs).MayBe(.bigint) b.binary(lhs, rhs, with: chooseUniform(from: allBinaryOperators), guard: needGuard) } ``` -------------------------------- ### Register Code Generators with Weights Source: https://context7.com/googleprojectzero/fuzzilli/llms.txt Combine various CodeGenerators into a WeightedList, assigning specific weights to each generator. This list is used by Fuzzilli to select generators during fuzzing. ```swift let codeGenerators = WeightedList([ (IntegerGenerator, 10), (BinaryOpGenerator, 5), (FunctionCallGenerator, 10), (MethodCallGenerator, 5), (ArrayGenerator, 5), (ForceDFGCompilationGenerator, 3), ]) ``` -------------------------------- ### Define a simple CodeGenerator Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/HowFuzzilliWorks.md Creates a new variable containing a random integer value using the CodeGenerator constructor. ```swift CodeGenerator("IntegerGenerator") { b in b.loadInt(b.genInt()) } ``` -------------------------------- ### JavaScript Property Access Chaining Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/HowFuzzilliWorks.md This JavaScript code demonstrates accessing nested properties (a.b.c) of an object, requiring knowledge of the object's and its properties' types. ```javascript function foo(v3) { return v3.a.b.c; } ``` -------------------------------- ### Define a Function Call Generator Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/HowFuzzilliWorks.md Initial implementation of a code generator that selects random variables for function calls without type awareness. ```swift CodeGenerator("FunctionCallGenerator") { b in let f = b.randomVariable() let arguments = [b.randomJsVariable(), b.randomJsVariable(), b.randomJsVariable()] b.callFunction(f, with: arguments) } ``` -------------------------------- ### Register Fuzzer Event Listeners in Swift Source: https://context7.com/googleprojectzero/fuzzilli/llms.txt Hook into fuzzer lifecycle events such as crashes, program discovery, and execution outcomes. ```swift // Register for crash events fuzzer.registerEventListener(for: fuzzer.events.CrashFound) { (program, behaviour, isUnique, origin) in print("Crash found! Behaviour: \(behaviour), Unique: \(isUnique)") // Lift and print the crashing program let js = fuzzer.lifter.lift(program) print("Crashing JavaScript:\n\(js)") // Access crash info from comments if let footer = program.comments.at(.footer) { print("Crash info:\n\(footer)") } } // Register for interesting program discovery fuzzer.registerEventListener(for: fuzzer.events.InterestingProgramFound) { (program, origin) in print("Found interesting program with \(program.size) instructions") } // Register for shutdown fuzzer.registerEventListener(for: fuzzer.events.Shutdown) { reason in print("Fuzzer shutting down: \(reason)") } // Register for statistics updates fuzzer.registerEventListener(for: fuzzer.events.StatisticsUpdated) { stats in print("Executions: \(stats.totalExecs), Corpus size: \(stats.corpusSize)") } // Handle program execution fuzzer.registerEventListener(for: fuzzer.events.PostExecute) { execution in switch execution.outcome { case .succeeded: // Program executed successfully break case .failed: // Program threw an exception break case .crashed(let signal): print("Program crashed with signal \(signal)") case .timedOut: print("Program timed out") case .differential: print("Differential behavior detected") } } ``` -------------------------------- ### Fuzzilli Custom Object Type Definition Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/HowFuzzilliWorks.md This Fuzzilli pseudocode defines a custom object type 'ObjType1' with nested properties and their respective types, enabling structured property access generation. ```fuzzil v3 = .object("ObjType1", [ .a: .object("ObjType2", [ .b: .object("ObjType3", [ .c: .integer ]) ]) ]) ``` -------------------------------- ### ES6 Class Definition in FuzzIL Source: https://github.com/googleprojectzero/fuzzilli/blob/main/Docs/HowFuzzilliWorks.md Representation of an ES6 class structure within the FuzzIL intermediate language. ```text v0 <- BeginClassDefinition ClassAddInstanceProperty "foo", v5 BeginClassInstanceMethod "bar" -> v8 (this), v9 ... implementation of method "bar" EndClassInstanceMethod BeginClassInstanceMethod "baz" -> v6 (this) ... implementation of method "baz" EndClassInstanceMethod EndClassDefinition ```