diff --git a/Sources/Fuzzilli/Fuzzer.swift b/Sources/Fuzzilli/Fuzzer.swift index 141cc088f..2c3514fe2 100644 --- a/Sources/Fuzzilli/Fuzzer.swift +++ b/Sources/Fuzzilli/Fuzzer.swift @@ -145,7 +145,7 @@ public class Fuzzer { /// Currently active corpus import job, if any. private var currentCorpusImportJob = CorpusImportJob(corpus: [], mode: .full) - private var iterationsSinceLastInterestingProgram: Int { + public var iterationsSinceLastInterestingProgram: Int { assert(iterations >= iterationOfLastInteratingSample) return iterations - iterationOfLastInteratingSample } diff --git a/Sources/FuzzilliCli/Profiles/MaglevProfile.swift b/Sources/FuzzilliCli/Profiles/MaglevProfile.swift new file mode 100644 index 000000000..f47c07477 --- /dev/null +++ b/Sources/FuzzilliCli/Profiles/MaglevProfile.swift @@ -0,0 +1,255 @@ +import Fuzzilli + +fileprivate let GcGenerator = CodeGenerator("GcGenerator") { b in + let type = b.loadString(probability(0.25) ? "major" : "minor") + let execution = b.loadString(probability(0.5) ? "sync" : "async") + b.callFunction(b.callFunction(b.createNamedVariable(forBuiltin: "gc")), withArgs: [b.createObject(with: ["type": type, "execution": execution])]) +} + +fileprivate let ForceOSRThroughLoopGenerator = RecursiveCodeGenerator("ForceOSRThroughLoopGenerator") { b in + let numIterations = 100 + b.buildRepeatLoop(n: numIterations) { i in + b.buildRecursive() + let selectedIteration = withEqualProbability({ + assert(numIterations > 10) + return Int.random(in: (numIterations - 10).. ([String], [Variable]) { + if !b.hasVisibleVariables { + b.loadInt(b.randomInt()) + } + + var properties = ["a"] + var values = [b.randomVariable()] + for _ in 0..<3 { + let property = chooseUniform(from: propertyNames) + guard !properties.contains(property) else { continue } + properties.append(property) + values.append(b.randomVariable()) + } + assert(Set(properties).count == values.count) + return (properties, values) + } + + let primitiveValueGenerator = ValueGenerator("PrimitiveValue") { b, n in + for _ in 0..([ + (primitiveValueGenerator, 2), + (createObjectGenerator, 1), + (objectMakerGenerator, 1), + (objectConstructorGenerator, 1), + (objectClassGenerator, 1), + + (propertyStoreGenerator, 10), + (propertyLoadGenerator, 10), + (propertyConfigureGenerator, 5), + (functionDefinitionGenerator, 2), + (functionCallGenerator, 3), + (constructorCallGenerator, 2), + (functionJitCallGenerator, 2) + ])) + + b.buildPrefix() + b.build(n: 100, by: .generating) + + b.fuzzer.setCodeGenerators(prevCodeGenerators) + b.build(n: 10) + + for obj in b.visibleVariables where b.type(of: obj).Is(objType) { + b.eval("%HeapObjectVerify(%@)", with: [obj]) + } +} + +fileprivate let ForceMaglevCompilationGenerator = CodeGenerator("ForceMaglevCompilationGenerator", inputs: .required(.function())) { b, f in + assert(b.type(of: f).Is(.function())) + let arguments = b.randomArguments(forCalling: f) + + b.callFunction(f, withArgs: arguments) + + b.eval("%PrepareFunctionForOptimization(%@)", with: [f]) + + b.callFunction(f, withArgs: arguments) + b.callFunction(f, withArgs: arguments) + + b.eval("%OptimizeMaglevOnNextCall(%@)", with: [f]) + + b.callFunction(f, withArgs: arguments) +} + +let maglevProfile = Profile( + processArgs: { (randomize) in + var args = [ + "--expose-gc", + "--omit-quit", + "--allow-natives-syntax", + "--fuzzing", + "--jit-fuzzing", + // "--future", + "--harmony", + "--js-staging", + "--concurrent-maglev-max-threads=1", + "--no-concurrent_recompilation", + ] + + guard randomize else { return args; } + + return args; + }, + + processEnv: [:], + maxExecsBeforeRespawn: 1000, + timeout: 250, + + codePrefix: """ + fuzzilli(\"FUZZILLI_PROBABILITY\", 0.2); + + // -------- BEGIN -------- + """, + codeSuffix: "", + + ecmaVersion: ECMAScriptVersion.es6, + startupTests: [ + ("fuzzilli('FUZZILLI_PRINT', 'test')", .shouldSucceed), + + ("fuzzilli('FUZZILLI_CRASH', 0)", .shouldCrash), + ("fuzzilli('FUZZILLI_CRASH', 1)", .shouldCrash), + ("fuzzilli('FUZZILLI_CRASH', 2)", .shouldCrash), + ("fuzzilli('FUZZILLI_CRASH', 3)", .shouldCrash), + ], + + additionalCodeGenerators: [ + (GcGenerator, 10), + (ForceMaglevCompilationGenerator, 5), + (ForceOSRThroughLoopGenerator, 5), + ], + additionalProgramTemplates: WeightedList([ + (MapTransitionFuzzer, 1), + ]), + + disabledCodeGenerators: [], + disabledMutators: [], + + additionalBuiltins: [ + "gc" : .function([] => (.undefined | .jsPromise)) + ], + + additionalObjectGroups: [], + optionalPostProcessor: nil +) \ No newline at end of file diff --git a/Sources/FuzzilliCli/Profiles/Profile.swift b/Sources/FuzzilliCli/Profiles/Profile.swift index a00fc69b2..897cc85ef 100644 --- a/Sources/FuzzilliCli/Profiles/Profile.swift +++ b/Sources/FuzzilliCli/Profiles/Profile.swift @@ -52,4 +52,5 @@ let profiles = [ "v8holefuzzing": v8HoleFuzzingProfile, "serenity": serenityProfile, "njs": njsProfile, + "maglev": maglevProfile ] diff --git a/Sources/FuzzilliCli/TerminalUI.swift b/Sources/FuzzilliCli/TerminalUI.swift index 1bb5f1c84..e21d393a8 100644 --- a/Sources/FuzzilliCli/TerminalUI.swift +++ b/Sources/FuzzilliCli/TerminalUI.swift @@ -147,6 +147,7 @@ class TerminalUI { Fuzzer Overhead: \(String(format: "%.2f", stats.fuzzerOverhead * 100))% Minimization Overhead: \(String(format: "%.2f", stats.minimizationOverhead * 100))% Total Execs: \(stats.totalExecs) + Interations since last: \(fuzzer.iterationsSinceLastInterestingProgram) """) } diff --git a/Sources/FuzzilliCli/main.swift b/Sources/FuzzilliCli/main.swift index 5fa4d2629..bb1b60daf 100644 --- a/Sources/FuzzilliCli/main.swift +++ b/Sources/FuzzilliCli/main.swift @@ -98,6 +98,7 @@ Options: --tag=tag : Optional string tag associated with this instance which will be stored in the settings.json file as well as in crashing samples. This can for example be used to remember the target revision that is being fuzzed. --wasm : Enable Wasm CodeGenerators (see WasmCodeGenerators.swift). + --builtinTemplates : Use built-in templates also """) exit(0) @@ -154,6 +155,7 @@ let swarmTesting = args.has("--swarmTesting") let argumentRandomization = args.has("--argumentRandomization") let additionalArguments = args["--additionalArguments"] ?? "" let tag = args["--tag"] +let builtinTemplates = args["--builtinTemplate"] let enableWasm = args.has("--wasm") guard numJobs >= 1 else { @@ -447,13 +449,15 @@ func makeFuzzer(with configuration: Configuration) -> Fuzzer { } } - for template in ProgramTemplates { - guard let weight = programTemplateWeights[template.name] else { - print("Missing weight for program template \(template.name) in ProgramTemplateWeights.swift") - exit(-1) - } + if builtinTemplates != nil { + for template in ProgramTemplates { + guard let weight = programTemplateWeights[template.name] else { + print("Missing weight for program template \(template.name) in ProgramTemplateWeights.swift") + exit(-1) + } - programTemplates.append(template, withWeight: weight) + programTemplates.append(template, withWeight: weight) + } } // The environment containing available builtins, property names, and method names.