diff --git a/Sources/Fuzzilli/FuzzIL/JSTyper.swift b/Sources/Fuzzilli/FuzzIL/JSTyper.swift index dc9858454..cc2c07af1 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, + .NullCoalesce: 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..a7b52cab6 100644 --- a/Sources/Fuzzilli/FuzzIL/JsOperations.swift +++ b/Sources/Fuzzilli/FuzzIL/JsOperations.swift @@ -1403,6 +1403,8 @@ public enum BinaryOperator: String, CaseIterable { case RShift = ">>" case Exp = "**" case UnRShift = ">>>" + // Nullish coalescing operator (??) + case NullCoalesce = "??" var token: String { return self.rawValue diff --git a/Sources/Fuzzilli/Lifting/JavaScriptExploreLifting.swift b/Sources/Fuzzilli/Lifting/JavaScriptExploreLifting.swift index 1bc99d2d5..1863c08b0 100644 --- a/Sources/Fuzzilli/Lifting/JavaScriptExploreLifting.swift +++ b/Sources/Fuzzilli/Lifting/JavaScriptExploreLifting.swift @@ -247,8 +247,7 @@ struct JavaScriptExploreLifting { // function exploreObject(o) { if (o === null) { - // Can't do anything with null. - return NO_ACTION; + return exploreNullish(o); } // TODO: Add special handling for ArrayBuffers: most of the time, wrap these into a Uint8Array to be able to modify them. @@ -405,6 +404,11 @@ struct JavaScriptExploreLifting { return action; } + function exploreNullish(v) { + // Best thing we can do with nullish values is a NullCoalescing (??) operation. + return new Action(OP_NULL_COALESCE, [exploredValueInput, Inputs.randomArgument()]) + } + // Explores the given value and returns an action to perform on it. function exploreValue(id, v) { if (isObject(v)) { @@ -422,8 +426,7 @@ struct JavaScriptExploreLifting { } else if (isBoolean(v)) { return exploreBoolean(v); } else if (isUndefined(v)) { - // Can't do anything with undefined. - return NO_ACTION; + return exploreNullish(v); } else { throw "Unexpected value type: " + typeof v; } diff --git a/Sources/Fuzzilli/Lifting/JavaScriptRuntimeAssistedMutatorLifting.swift b/Sources/Fuzzilli/Lifting/JavaScriptRuntimeAssistedMutatorLifting.swift index 5370c4543..6f9882ad8 100644 --- a/Sources/Fuzzilli/Lifting/JavaScriptRuntimeAssistedMutatorLifting.swift +++ b/Sources/Fuzzilli/Lifting/JavaScriptRuntimeAssistedMutatorLifting.swift @@ -389,6 +389,7 @@ struct JavaScriptRuntimeAssistedMutatorLifting { const OP_LOGICAL_AND = 'LOGICAL_AND'; const OP_LOGICAL_OR = 'LOGICAL_OR'; const OP_LOGICAL_NOT = 'LOGICAL_NOT'; + const OP_NULL_COALESCE = 'NULL_COALESCE'; const OP_BITWISE_AND = 'BITWISE_AND'; const OP_BITWISE_OR = 'BITWISE_OR'; @@ -511,6 +512,7 @@ struct JavaScriptRuntimeAssistedMutatorLifting { [OP_LOGICAL_AND]: (inputs) => inputs[0] && inputs[1], [OP_LOGICAL_OR]: (inputs) => inputs[0] || inputs[1], [OP_LOGICAL_NOT]: (inputs) => !inputs[0], + [OP_NULL_COALESCE]: (inputs) => inputs[0] ?? inputs[1], [OP_BITWISE_AND]: (inputs) => inputs[0] & inputs[1], [OP_BITWISE_OR]: (inputs) => inputs[0] | inputs[1], [OP_BITWISE_XOR]: (inputs) => inputs[0] ^ inputs[1], diff --git a/Sources/Fuzzilli/Mutators/RuntimeAssistedMutator.swift b/Sources/Fuzzilli/Mutators/RuntimeAssistedMutator.swift index 67498ea21..b0f6422a6 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 NullCoalesce = "NULL_COALESCE" 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 .NullCoalesce: + try translateBinaryOperation(.NullCoalesce) case .LeftShift: try translateBinaryOperation(.LShift) case .SignedRightShift: