diff --git a/Sources/Fuzzilli/CodeGen/CodeGenerators.swift b/Sources/Fuzzilli/CodeGen/CodeGenerators.swift index f8a9cd5f7..32f79772b 100644 --- a/Sources/Fuzzilli/CodeGen/CodeGenerators.swift +++ b/Sources/Fuzzilli/CodeGen/CodeGenerators.swift @@ -845,7 +845,7 @@ public let CodeGenerators: [CodeGenerator] = [ // TODO: for now we simply look for numbers, since those probably make the most sense for binary operations. But we may also want BigInts or strings sometimes. let rhs = b.randomVariable(forUseAs: .number) - b.updateProperty(propertyName, of: obj, with: rhs, using: chooseUniform(from: BinaryOperator.allCases)) + b.updateProperty(propertyName, of: obj, with: rhs, using: chooseUniform(from: BinaryOperator.allCaseWithoutNCO())) }, CodeGenerator("PropertyRemovalGenerator", inputs: .preferred(.object())) { b, obj in @@ -895,7 +895,7 @@ public let CodeGenerators: [CodeGenerator] = [ let index = b.randomIndex() // TODO: for now we simply look for numbers, since those probably make the most sense for binary operations. But we may also want BigInts or strings sometimes. let rhs = b.randomVariable(forUseAs: .number) - b.updateElement(index, of: obj, with: rhs, using: chooseUniform(from: BinaryOperator.allCases)) + b.updateElement(index, of: obj, with: rhs, using: chooseUniform(from: BinaryOperator.allCaseWithoutNCO())) }, CodeGenerator("ElementRemovalGenerator", inputs: .preferred(.object())) { b, obj in @@ -937,7 +937,7 @@ public let CodeGenerators: [CodeGenerator] = [ let propertyName = b.randomVariable() // TODO: for now we simply look for numbers, since those probably make the most sense for binary operations. But we may also want BigInts or strings sometimes. let rhs = b.randomVariable(forUseAs: .number) - b.updateComputedProperty(propertyName, of: obj, with: rhs, using: chooseUniform(from: BinaryOperator.allCases)) + b.updateComputedProperty(propertyName, of: obj, with: rhs, using: chooseUniform(from: BinaryOperator.allCaseWithoutNCO())) }, CodeGenerator("ComputedPropertyRemovalGenerator", inputs: .preferred(.object())) { b, obj in @@ -1228,7 +1228,7 @@ public let CodeGenerators: [CodeGenerator] = [ guard !b.currentClassDefinition.privateProperties.isEmpty else { return } let propertyName = chooseUniform(from: b.currentClassDefinition.privateProperties) b.buildTryCatchFinally(tryBody: { - b.updatePrivateProperty(propertyName, of: obj, with: value, using: chooseUniform(from: BinaryOperator.allCases)) + b.updatePrivateProperty(propertyName, of: obj, with: value, using: chooseUniform(from: BinaryOperator.allCaseWithoutNCO())) }, catchBody: { e in }) }, @@ -1281,7 +1281,7 @@ public let CodeGenerators: [CodeGenerator] = [ // TODO: for now we simply look for numbers, since those probably make the most sense for binary operations. But we may also want BigInts or strings sometimes. let rhs = b.randomVariable(forUseAs: .number) - b.updateSuperProperty(propertyName, with: rhs, using: chooseUniform(from: BinaryOperator.allCases)) + b.updateSuperProperty(propertyName, with: rhs, using: chooseUniform(from: BinaryOperator.allCaseWithoutNCO())) }, RecursiveCodeGenerator("IfElseGenerator", inputs: .preferred(.boolean) ){ b, cond in diff --git a/Sources/Fuzzilli/FuzzIL/JSTyper.swift b/Sources/Fuzzilli/FuzzIL/JSTyper.swift index dc9858454..f71dc9175 100644 --- a/Sources/Fuzzilli/FuzzIL/JSTyper.swift +++ b/Sources/Fuzzilli/FuzzIL/JSTyper.swift @@ -427,7 +427,8 @@ public struct JSTyper: Analyzer { .UnRShift: return maybeBigIntOr(.integer) case .LogicAnd, - .LogicOr: + .LogicOr, + .NCO: return state.type(of: inputs[0]) | state.type(of: inputs[1]) } } diff --git a/Sources/Fuzzilli/FuzzIL/JsOperations.swift b/Sources/Fuzzilli/FuzzIL/JsOperations.swift index bab2bd749..164c5789e 100644 --- a/Sources/Fuzzilli/FuzzIL/JsOperations.swift +++ b/Sources/Fuzzilli/FuzzIL/JsOperations.swift @@ -1403,12 +1403,19 @@ public enum BinaryOperator: String, CaseIterable { case RShift = ">>" case Exp = "**" case UnRShift = ">>>" + // Nullish coalescing operator (??) + case NCO = "??" var token: String { return self.rawValue } + + static public func allCaseWithoutNCO() -> Array { + return BinaryOperator.allCases.filter { $0 != .NCO } + } } + final class BinaryOperation: JsOperation { override var opcode: Opcode { .binaryOperation(self) } diff --git a/Sources/Fuzzilli/Mutators/RuntimeAssistedMutator.swift b/Sources/Fuzzilli/Mutators/RuntimeAssistedMutator.swift index 67498ea21..b1c4589c2 100644 --- a/Sources/Fuzzilli/Mutators/RuntimeAssistedMutator.swift +++ b/Sources/Fuzzilli/Mutators/RuntimeAssistedMutator.swift @@ -186,6 +186,7 @@ public class RuntimeAssistedMutator: Mutator { case LogicalAnd = "LOGICAL_AND" case LogicalOr = "LOGICAL_OR" case LogicalNot = "LOGICAL_NOT" + case NCO = "NCO" case BitwiseAnd = "BITWISE_AND" case BitwiseOr = "BITWISE_OR" case BitwiseXor = "BITWISE_XOR" @@ -385,6 +386,8 @@ extension RuntimeAssistedMutator.Action { try translateBinaryOperation(.BitOr) case .BitwiseXor: try translateBinaryOperation(.Xor) + case .NCO: + try translateBinaryOperation(.NCO) case .LeftShift: try translateBinaryOperation(.LShift) case .SignedRightShift: