From 2c4c0f47ddd6e8c02f7da6dd883929de0682b952 Mon Sep 17 00:00:00 2001 From: Carl Smith Date: Tue, 12 Mar 2024 13:30:58 +0100 Subject: [PATCH] Revert "Do ValueGeneration in the Splice- and CodeGenMutator." This reverts commit db9aa6ed2fd03b89934685ec3c9ae925f8b3b361. We now allow splicing without visible variables as that is not a strict requirement and also add some more comments as to why we have the visibleVariables requirement for code generation. --- Sources/Fuzzilli/Base/ProgramBuilder.swift | 5 +++-- Sources/Fuzzilli/Mutators/CodeGenMutator.swift | 12 +++++++----- Sources/Fuzzilli/Mutators/SpliceMutator.swift | 7 ------- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/Sources/Fuzzilli/Base/ProgramBuilder.swift b/Sources/Fuzzilli/Base/ProgramBuilder.swift index a3869a44c..cc67038a6 100644 --- a/Sources/Fuzzilli/Base/ProgramBuilder.swift +++ b/Sources/Fuzzilli/Base/ProgramBuilder.swift @@ -1252,7 +1252,6 @@ public class ProgramBuilder { } private func buildInternal(initialBuildingBudget: Int, mode: BuildingMode) { - assert(hasVisibleVariables, "CodeGenerators and our splicing implementation assume that there are visible variables to use. Use buildPrefix() to generate some initial variables in a new program") assert(initialBuildingBudget > 0) // Both splicing and code generation can sometimes fail, for example if no other program with the necessary features exists. @@ -1292,7 +1291,9 @@ public class ProgramBuilder { let codeSizeBefore = code.count switch mode { case .generating: - assert(hasVisibleVariables) + // This requirement might seem somewhat arbitrary but our JavaScript code generators make use of `b.randomVariable` and as such rely on the availability of + // visible Variables. Therefore we should always have some Variables visible if we want to use them. + assert(hasVisibleVariables, "CodeGenerators assume that there are visible variables to use. Use buildPrefix() to generate some initial variables in a new program") // Reset the code generator specific part of the state. state.nextRecursiveBlockOfCurrentGenerator = 1 diff --git a/Sources/Fuzzilli/Mutators/CodeGenMutator.swift b/Sources/Fuzzilli/Mutators/CodeGenMutator.swift index f11e83f4f..030bf1f43 100644 --- a/Sources/Fuzzilli/Mutators/CodeGenMutator.swift +++ b/Sources/Fuzzilli/Mutators/CodeGenMutator.swift @@ -15,6 +15,7 @@ /// A mutator that generates new code at random positions in a program. public class CodeGenMutator: BaseInstructionMutator { private var deadCodeAnalyzer = DeadCodeAnalyzer() + private var variableAnalyzer = VariableAnalyzer() private let minVisibleVariables = 3 public init() { @@ -24,19 +25,20 @@ public class CodeGenMutator: BaseInstructionMutator { public override func beginMutation(of program: Program) { deadCodeAnalyzer = DeadCodeAnalyzer() + variableAnalyzer = VariableAnalyzer() } public override func canMutate(_ instr: Instruction) -> Bool { deadCodeAnalyzer.analyze(instr) - // It only makes sense to generate code if we're not currently in dead code. - return !deadCodeAnalyzer.currentlyInDeadCode + variableAnalyzer.analyze(instr) + // We can only generate code if there are some visible variables to use, and it only + // makes sense to generate code if we're not currently in dead code. + return variableAnalyzer.visibleVariables.count >= minVisibleVariables && !deadCodeAnalyzer.currentlyInDeadCode } public override func mutate(_ instr: Instruction, _ b: ProgramBuilder) { b.adopt(instr) - if b.numberOfVisibleVariables < minVisibleVariables { - b.buildPrefix() - } + assert(b.numberOfVisibleVariables >= minVisibleVariables) b.build(n: defaultCodeGenerationAmount, by: .generating) } } diff --git a/Sources/Fuzzilli/Mutators/SpliceMutator.swift b/Sources/Fuzzilli/Mutators/SpliceMutator.swift index 1932524df..1b1cf0158 100644 --- a/Sources/Fuzzilli/Mutators/SpliceMutator.swift +++ b/Sources/Fuzzilli/Mutators/SpliceMutator.swift @@ -15,7 +15,6 @@ /// A mutator that splices programs together. public class SpliceMutator: BaseInstructionMutator { private var deadCodeAnalyzer = DeadCodeAnalyzer() - private let minVisibleVariables = 3 public init() { super.init(maxSimultaneousMutations: defaultMaxSimultaneousMutations) @@ -33,12 +32,6 @@ public class SpliceMutator: BaseInstructionMutator { public override func mutate(_ instr: Instruction, _ b: ProgramBuilder) { b.adopt(instr) - // If we currently don't have enough visible variables, we will do some value generation. - // This is necessary because our splice implementation requires some visible variables although this is - // not strictly necessary for splicing itself (it helps for rewiring inputs). - if b.numberOfVisibleVariables < minVisibleVariables { - b.buildPrefix() - } b.build(n: defaultCodeGenerationAmount, by: .splicing) } }