Skip to content

Commit

Permalink
changes from PR feedback; base64/hex generators
Browse files Browse the repository at this point in the history
  • Loading branch information
phoddie authored Apr 4, 2024
1 parent 64e53d0 commit 9b72fdd
Showing 1 changed file with 108 additions and 33 deletions.
141 changes: 108 additions & 33 deletions Sources/FuzzilliCli/Profiles/XSProfile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import Fuzzilli

fileprivate let StressXSGC = CodeGenerator("StressXSGC", inputs: .required(.function())) { b, f in
guard b.type(of: f).Is(.function()) else { return } //@@ where did this come from??
let arguments = b.randomArguments(forCalling: f)

let index = b.loadInt(1)
Expand All @@ -26,15 +25,13 @@ fileprivate let StressXSGC = CodeGenerator("StressXSGC", inputs: .required(.func
b.callFunction(f, withArgs: arguments)
b.unary(.PostInc, index)
let result = b.callFunction(gc, withArgs: [index])
b.buildIfElse(result, ifBody: {
b.buildIf(result) {
b.loopBreak();
}, elseBody: {
});
}
}
}

fileprivate let StressXSMemoryFail = CodeGenerator("StressXSMemoryFail", inputs: .required(.function())) { b, f in
guard b.type(of: f).Is(.function()) else { return } //@@ where did this come from??
let arguments = b.randomArguments(forCalling: f)

let index = b.loadInt(1)
Expand All @@ -54,9 +51,9 @@ fileprivate let StressXSMemoryFail = CodeGenerator("StressXSMemoryFail", inputs:
fileprivate let HardenGenerator = CodeGenerator("HardenGenerator", inputs: .required(.object())) { b, obj in
let harden = b.loadBuiltin("harden")

if (Int.random(in: 0...20) < 1) {
if probability(0.05) {
let lockdown = b.loadBuiltin("lockdown")
b.callFunction(lockdown, withArgs: [])
b.callFunction(lockdown)
}
b.callFunction(harden, withArgs: [obj])
}
Expand Down Expand Up @@ -104,23 +101,23 @@ fileprivate let CompartmentGenerator = RecursiveCodeGenerator("CompartmentGenera
options["loadNowHook"] = loadNowHook;
options["loadHook"] = loadHook;

if (Int.random(in: 0...100) < 50) {
if probability(0.5) {
options["globalLexicals"] = endowmentsObject
endowmentsObject = b.createObject(with: [:])
}
let optionsObject = b.createObject(with: options)

let compartment = b.construct(compartmentConstructor, withArgs: [endowmentsObject, moduleMapObject, optionsObject])

if (Int.random(in: 0...100) < 50) {
if probability(0.5) {
let code = b.buildCodeString() {
b.buildRecursive(block: 4, of: 4)
}
b.callMethod("evaluate", on: compartment, withArgs: [code])
}
}

fileprivate let UnicodeStringGenerator = CodeGenerator("UnicodeStringGenerator", inputs: .required(.object())) { b, obj in
fileprivate let UnicodeStringGenerator = CodeGenerator("UnicodeStringGenerator") { b in
var s = ""
for _ in 0..<Int.random(in: 1...100) {
let codePoint = UInt32.random(in: 0..<0x10FFFF)
Expand All @@ -134,20 +131,95 @@ fileprivate let UnicodeStringGenerator = CodeGenerator("UnicodeStringGenerator",
b.loadString(s)
}

/*
The inputs to this aren't filtered to jsCompartment but seem to be any just .object()
That's not very useful, so leaving this disabled until that is sorted out
let hexValues = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "A", "B", "C", "D", "E", "F"]

fileprivate let HexGenerator = CodeGenerator("HexGenerator") { b in
let Uint8Array = b.loadBuiltin("Uint8Array")

withEqualProbability({
var s = ""
for _ in 0..<Int.random(in: 1...10) {
s += chooseUniform(from: hexValues)
s += chooseUniform(from: hexValues)
}
let hex = b.loadString(s)

if probability(0.5) {
b.callMethod("fromHex", on: Uint8Array, withArgs: [hex])
}
else {
let target = b.construct(Uint8Array, withArgs: [b.loadInt(Int64.random(in: 0...0x100))])
b.callMethod("setFromHex", on: target, withArgs: [hex])
}
}, {
var values = [Variable]()
for _ in 0..<Int.random(in: 1...20) {
values.append(b.loadInt(Int64.random(in: 0...0xFF)))
}

let bytes = b.callMethod("of", on: Uint8Array, withArgs: values)
b.callMethod("toHex", on: bytes, withArgs: [])
}
)
}

let base64Alphabet = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "/"]
let base64URLAlphabet = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "-", "_"]

fileprivate let Base64Generator = CodeGenerator("Base64Generator") { b in
let Uint8Array = b.loadBuiltin("Uint8Array")

withEqualProbability({
var options = [String: Variable]()
var alphabet = chooseUniform(from: [base64Alphabet, base64URLAlphabet])

options["alphabet"] = b.loadString((alphabet == base64Alphabet) ? "base64" : "base64url")
options["lastChunkHandling"] = b.loadString(
chooseUniform(
from: ["loose", "strict", "stop-before-partial"]
)
)

var s = ""
for _ in 0..<Int.random(in: 1...128) {
s += chooseUniform(from: alphabet)
}

if probability(0.5) {
while (0 != (s.count % 4)) {
s += "=";
}
}
let base64 = b.loadString(s)

let optionsObject = b.createObject(with: options)
if probability(0.5) {
b.callMethod("fromBase64", on: Uint8Array, withArgs: [base64, optionsObject])
}
else {
let target = b.construct(Uint8Array, withArgs: [b.loadInt(Int64.random(in: 0...0x100))])
b.callMethod("setFromBase64", on: target, withArgs: [base64, optionsObject])
}
}, {
var values = [Variable]()
for _ in 0..<Int.random(in: 1...64) {
values.append(b.loadInt(Int64.random(in: 0...0xFF)))
}

let bytes = b.callMethod("of", on: Uint8Array, withArgs: values)
b.callMethod("toBase64", on: bytes, withArgs: [])
}
)
}

fileprivate let CompartmentEvaluateGenerator = CodeGenerator("CompartmentEvaluateGenerator", inputs: .required(.jsCompartment)) { b, target in
fileprivate let CompartmentEvaluateGenerator = CodeGenerator("CompartmentEvaluateGenerator", inputs: .required(.object(ofGroup: "Compartment"))) { b, target in
let code = b.buildCodeString() {
b.buildRecursive()
}
b.callMethod("evaluate", on: target, withArgs: [code])
}
*/

// This template fuzzes the RegExp engine.
// It finds bugs like: crbug.com/1437346 and crbug.com/1439691.
// this template taken from V8Profile.swift (with light modifications for XS)
fileprivate let RegExpFuzzer = ProgramTemplate("RegExpFuzzer") { b in
// Taken from: https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:v8/test/fuzzer/regexp-builtins.cc;l=212;drc=a61b95c63b0b75c1cfe872d9c8cdf927c226046e
let twoByteSubjectString = "f\\uD83D\\uDCA9ba\\u2603"
Expand Down Expand Up @@ -235,13 +307,13 @@ fileprivate let RegExpFuzzer = ProgramTemplate("RegExpFuzzer") { b in
b.doReturn(resultVar)
}

b.eval("%SetForceSlowPath(false)");
// b.eval("%SetForceSlowPath(false)");
// compile the regexp once
b.callFunction(f)
let resFast = b.callFunction(f)
b.eval("%SetForceSlowPath(true)");
// b.eval("%SetForceSlowPath(true)");
let resSlow = b.callFunction(f)
b.eval("%SetForceSlowPath(false)");
// b.eval("%SetForceSlowPath(false)");

b.build(n: 15)
}
Expand All @@ -250,11 +322,11 @@ public extension ILType {
/// Type of a JavaScript Compartment object.
static let jsCompartment = ILType.object(ofGroup: "Compartment", withProperties: ["globalThis"], withMethods: ["evaluate", "import", "importNow" /* , "module" */])

static let jsCompartmentConstructor = ILType.constructor([.function()] => .jsCompartment) + .object(ofGroup: "CompartmentConstructor", withProperties: ["prototype"], withMethods: [])
static let jsCompartmentConstructor = ILType.constructor([.opt(.object()), .opt(.object()), .opt(.object())] => .jsCompartment) + .object(ofGroup: "CompartmentConstructor", withProperties: ["prototype"], withMethods: [])

static let jsModuleSource = ILType.object(ofGroup: "ModuleSource", withProperties: ["bindings", "needsImport", "needsImportMeta"])

static let jsModuleSourceConstructor = ILType.constructor([.function()] => .jsModuleSource) + .object(ofGroup: "ModuleSourceConstructor", withProperties: ["prototype"], withMethods: [])
static let jsModuleSourceConstructor = ILType.constructor([.opt(.string)] => .jsModuleSource) + .object(ofGroup: "ModuleSourceConstructor", withProperties: ["prototype"], withMethods: [])
}

/// Object group modelling JavaScript compartments.
Expand Down Expand Up @@ -336,12 +408,15 @@ let xsProfile = Profile(
],

additionalCodeGenerators: [
(StressXSMemoryFail, 5),
(StressXSGC, 5),
(HardenGenerator, 5),
(CompartmentGenerator, 5),
(UnicodeStringGenerator, 2),
(ModuleSourceGenerator, 3)
(StressXSMemoryFail, 5),
(StressXSGC, 5),
(HardenGenerator, 5),
(CompartmentGenerator, 5),
(CompartmentEvaluateGenerator, 5),
(UnicodeStringGenerator, 2),
(ModuleSourceGenerator, 3),
(HexGenerator, 2),
(Base64Generator, 2),
],

additionalProgramTemplates: WeightedList<ProgramTemplate>([
Expand All @@ -358,12 +433,12 @@ let xsProfile = Profile(
"print" : .function([.string] => .undefined),

// hardened javascript
"Compartment" : .function([] => .jsCompartmentConstructor),
"ModuleSource" : .function([] => .jsModuleSourceConstructor),
"harden" : .function([.plain(.anything)] => .undefined),
"Compartment" : .function([.opt(.object()), .opt(.object()), .opt(.object())] => .jsCompartmentConstructor),
"ModuleSource" : .function([.opt(.string)] => .jsModuleSourceConstructor),
"harden" : .function([.object()] => .object()),
"lockdown" : .function([] => .undefined) ,
"petrify" : .function([.plain(.anything)] => .undefined),
"mutabilities" : .function([.plain(.anything)] => .object())
"petrify" : .function([.anything] => .anything),
"mutabilities" : .function([.object()] => .object())
],

additionalObjectGroups: [jsCompartments, jsCompartmentConstructor, jsModuleSources, jsModuleSourceConstructor],
Expand Down

0 comments on commit 9b72fdd

Please sign in to comment.