Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions .github/workflows/swift.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: build
name: build_test

on:
push:
Expand All @@ -7,10 +7,18 @@ on:
branches: [ main ]

jobs:
build:
build_test:
timeout-minutes: 30
strategy:
# If macos-latest fails, we still don't want to cancel ubuntu-latest or the other way around.
fail-fast: false
matrix:
os: [macos-latest, ubuntu-latest]
kind: [debug]
include:
# On linux also build and test release.
- os: ubuntu-latest
kind: release

runs-on: ${{ matrix.os }}

Expand All @@ -26,11 +34,14 @@ jobs:
uses: swift-actions/setup-swift@v2
with:
swift-version: "6.0.3"

- uses: actions/checkout@v2

- name: Build
run: swift build -v

- name: Run tests
run: swift test -v
run: swift build -c ${{ matrix.kind }} -v
- name: Run tests with Node.js
run: swift test -c ${{ matrix.kind }} -v
- name: Install jsvu
run: npm install jsvu -g
- name: Install d8
run: jsvu --os=default --engines=v8
- name: Run tests with d8
run: FUZZILLI_TEST_SHELL=~/.jsvu/engines/v8/v8 swift test -c ${{ matrix.kind }} -v
27 changes: 25 additions & 2 deletions Sources/Fuzzilli/Base/ProgramBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1933,6 +1933,14 @@ public class ProgramBuilder {
}
}

// Like build(n:by) but forcing BuildingMode to generating. Splicing is an operation that
// affects the whole program, so we shouldn't roll a die on every buildRecursive() call in a
// code generator whether we'd want to splice an operation into the current block (which happens
// with the default mode .generatingAndSplicing).
public func buildRecursive(n budget: Int) {
build(n: budget, by: .generating)
}

/// Run ValueGenerators until we have created at least N new variables.
/// Returns both the number of generated instructions and of newly created variables.
@discardableResult
Expand Down Expand Up @@ -1998,7 +2006,7 @@ public class ProgramBuilder {
// We need to update the inputs later, so take note of the visible variables here.
let oldVisibleVariables = visibleVariables

build(n: defaultCodeGenerationAmount)
build(n: defaultCodeGenerationAmount, by: mode)

let newVisibleVariables = visibleVariables.filter { v in
let t = type(of: v)
Expand Down Expand Up @@ -2111,7 +2119,7 @@ public class ProgramBuilder {
// Check if we need to or can create types here.
createRequiredInputVariables(forTypes: inputTypes)
// Build into the block.
build(n: budgetPerYieldPoint)
buildRecursive(n: budgetPerYieldPoint)
// Call the next scheduled stub.
let _ = callNext()
numberOfGeneratedInstructions += code.count - codeSizePre
Expand Down Expand Up @@ -2970,6 +2978,12 @@ public class ProgramBuilder {
}
}

public func maybeReturnRandomJsVariable(_ prob: Double) {
if probability(prob) {
doReturn(randomJsVariable())
}
}

@discardableResult
public func yield(_ value: Variable? = nil) -> Variable {
if let argument = value {
Expand Down Expand Up @@ -3117,6 +3131,15 @@ public class ProgramBuilder {
return emit(CreateNamedAsyncDisposableVariable(name), withInputs: [initialValue]).output
}

@discardableResult
public func createSymbolProperty(_ name: String) -> Variable {
let Symbol = createNamedVariable(forBuiltin: "Symbol")
// The Symbol constructor is just a "side effect" and probably
// shouldn't be used by following generators.
hide(Symbol)
return getProperty(name, of: Symbol)
}

@discardableResult
public func eval(_ string: String, with arguments: [Variable] = [], hasOutput: Bool = false) -> Variable? {
let instr = emit(Eval(string, numArguments: arguments.count, hasOutput: hasOutput), withInputs: arguments)
Expand Down
61 changes: 25 additions & 36 deletions Sources/Fuzzilli/CodeGen/CodeGenerators.swift
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ public let CodeGenerators: [CodeGenerator] = [
}

let o = b.buildObjectLiteral { obj in
b.build(n: Int.random(in: 0...10))
b.buildRecursive(n: Int.random(in: 0...10))
}

objType = b.type(of: o)
Expand Down Expand Up @@ -344,7 +344,7 @@ public let CodeGenerators: [CodeGenerator] = [

// Create the class.
let c = b.buildClassDefinition(withSuperclass: superclass, isExpression: probability(0.3)) { cls in
b.build(n: defaultCodeGenerationAmount)
b.buildRecursive(n: defaultCodeGenerationAmount)
}

// And construct a few instances of it.
Expand Down Expand Up @@ -426,12 +426,11 @@ public let CodeGenerators: [CodeGenerator] = [
"DisposableVariableGenerator", inContext: .single(.subroutine), inputs: .one
) { b, val in
assert(b.context.contains(.subroutine))
let dispose = b.getProperty(
"dispose", of: b.createNamedVariable(forBuiltin: "Symbol"))
let dispose = b.createSymbolProperty("dispose")
let disposableVariable = b.buildObjectLiteral { obj in
obj.addProperty("value", as: val)
obj.addComputedMethod(dispose, with: .parameters(n: 0)) { args in
b.doReturn(b.randomJsVariable())
b.maybeReturnRandomJsVariable(0.9)
}
}
b.loadDisposableVariable(disposableVariable)
Expand All @@ -442,13 +441,12 @@ public let CodeGenerators: [CodeGenerator] = [
inputs: .one
) { b, val in
assert(b.context.contains(.asyncFunction))
let asyncDispose = b.getProperty(
"asyncDispose", of: b.createNamedVariable(forBuiltin: "Symbol"))
let asyncDispose = b.createSymbolProperty("asyncDispose")
let asyncDisposableVariable = b.buildObjectLiteral { obj in
obj.addProperty("value", as: val)
obj.addComputedMethod(asyncDispose, with: .parameters(n: 0)) {
args in
b.doReturn(b.randomJsVariable())
b.maybeReturnRandomJsVariable(0.9)
}
}
b.loadAsyncDisposableVariable(asyncDisposableVariable)
Expand Down Expand Up @@ -861,7 +859,7 @@ public let CodeGenerators: [CodeGenerator] = [
"ClassInstanceMethodEndGenerator",
inContext: .single([.javascript, .subroutine, .method, .classMethod])
) { b in
b.doReturn(b.randomJsVariable())
b.maybeReturnRandomJsVariable(0.9)
b.emit(EndClassInstanceMethod())
},
]),
Expand Down Expand Up @@ -899,7 +897,7 @@ public let CodeGenerators: [CodeGenerator] = [
"ClassInstanceComputedMethodEndGenerator",
inContext: .single([.javascript, .subroutine, .method, .classMethod])
) { b in
b.doReturn(b.randomJsVariable())
b.maybeReturnRandomJsVariable(0.9)
b.emit(EndClassInstanceComputedMethod())
},
]),
Expand Down Expand Up @@ -1107,7 +1105,7 @@ public let CodeGenerators: [CodeGenerator] = [
"ClassStaticMethodEndGenerator",
inContext: .single([.javascript, .classMethod, .subroutine, .method])
) { b in
b.doReturn(b.randomJsVariable())
b.maybeReturnRandomJsVariable(0.9)
b.emit(EndClassStaticMethod())
},
]),
Expand Down Expand Up @@ -1145,7 +1143,7 @@ public let CodeGenerators: [CodeGenerator] = [
"ClassStaticComputedMethodEndGenerator",
inContext: .single([.javascript, .subroutine, .method, .classMethod])
) { b in
b.doReturn(b.randomJsVariable())
b.maybeReturnRandomJsVariable(0.9)
b.emit(EndClassStaticComputedMethod())
},
]),
Expand Down Expand Up @@ -1283,7 +1281,7 @@ public let CodeGenerators: [CodeGenerator] = [
"ClassPrivateInstanceMethodEndGenerator",
inContext: .single([.javascript, .subroutine, .method, .classMethod])
) { b in
b.doReturn(b.randomJsVariable())
b.maybeReturnRandomJsVariable(0.9)
b.emit(EndClassPrivateInstanceMethod())
},
]),
Expand Down Expand Up @@ -1345,7 +1343,7 @@ public let CodeGenerators: [CodeGenerator] = [
"ClassPrivateStaticMethodEndGenerator",
inContext: .single([.javascript, .subroutine, .method, .classMethod])
) { b in
b.doReturn(b.randomJsVariable())
b.maybeReturnRandomJsVariable(0.9)
b.emit(EndClassPrivateStaticMethod())
},

Expand Down Expand Up @@ -2414,7 +2412,7 @@ public let CodeGenerators: [CodeGenerator] = [
let loopVar = b.loadInt(0)
b.buildDoWhileLoop(
do: {
b.build(n: defaultCodeGenerationAmount)
b.buildRecursive(n: defaultCodeGenerationAmount)
b.unary(.PostInc, loopVar)
},
while: {
Expand Down Expand Up @@ -2462,7 +2460,7 @@ public let CodeGenerators: [CodeGenerator] = [
// Generate a for-loop without any loop variables.
let counter = b.loadInt(10)
b.buildForLoop({}, { b.unary(.PostDec, counter) }) {
b.build(n: 4)
b.buildRecursive(n: 4)
}
} else {
// Generate a for-loop with two loop variables.
Expand All @@ -2475,7 +2473,7 @@ public let CodeGenerators: [CodeGenerator] = [
b.unary(.PostDec, vs[1])
}
) { _ in
b.build(n: 4)
b.buildRecursive(n: 4)
}
}
},
Expand Down Expand Up @@ -2672,22 +2670,17 @@ public let CodeGenerators: [CodeGenerator] = [
CodeGenerator(
"WellKnownPropertyLoadGenerator", inputs: .preferred(.object())
) { b, obj in
let Symbol = b.createNamedVariable(forBuiltin: "Symbol")
// The Symbol constructor is just a "side effect" of this generator and probably shouldn't be used by following generators.
b.hide(Symbol)
let name = chooseUniform(from: JavaScriptEnvironment.wellKnownSymbols)
let propertyName = b.getProperty(name, of: Symbol)
let propertyName = b.createSymbolProperty(
chooseUniform(from: JavaScriptEnvironment.wellKnownSymbols))
let needGuard = b.type(of: obj).MayBe(.nullish)
b.getComputedProperty(propertyName, of: obj, guard: needGuard)
},

CodeGenerator(
"WellKnownPropertyStoreGenerator", inputs: .preferred(.object())
) { b, obj in
let Symbol = b.createNamedVariable(forBuiltin: "Symbol")
b.hide(Symbol)
let name = chooseUniform(from: JavaScriptEnvironment.wellKnownSymbols)
let propertyName = b.getProperty(name, of: Symbol)
let propertyName = b.createSymbolProperty(
chooseUniform(from: JavaScriptEnvironment.wellKnownSymbols))
let val = b.randomJsVariable()
b.setComputedProperty(propertyName, of: obj, to: val)
},
Expand Down Expand Up @@ -2932,18 +2925,16 @@ public let CodeGenerators: [CodeGenerator] = [
if probability(0.5) {
imitation = b.buildObjectLiteral { obj in
obj.addMethod("valueOf", with: .parameters(n: 0)) { _ in
b.build(n: 3)
b.buildRecursive(n: 3)
b.doReturn(orig)
}
}
} else {
let toPrimitive = b.getProperty(
"toPrimitive",
of: b.createNamedVariable(forBuiltin: "Symbol"))
let toPrimitive = b.createSymbolProperty("toPrimitive")
imitation = b.buildObjectLiteral { obj in
obj.addComputedMethod(toPrimitive, with: .parameters(n: 0))
{ _ in
b.build(n: 3)
b.buildRecursive(n: 3)
b.doReturn(orig)
}
}
Expand All @@ -2961,14 +2952,14 @@ public let CodeGenerators: [CodeGenerator] = [
let constructor = b.getProperty("constructor", of: orig)
let cls = b.buildClassDefinition(withSuperclass: constructor, isExpression: probability(0.3)) {
_ in
b.build(n: 3)
b.buildRecursive(n: 3)
}
imitation = b.construct(
cls, withArgs: b.randomArguments(forCalling: cls))
} else {
imitation = b.buildObjectLiteral { obj in
obj.setPrototype(to: orig)
b.build(n: 3)
b.buildRecursive(n: 3)
}
}
} else {
Expand Down Expand Up @@ -3081,9 +3072,7 @@ public let CodeGenerators: [CodeGenerator] = [
},

CodeGenerator("IteratorGenerator", produces: [.iterable]) { b in
let Symbol = b.createNamedVariable(forBuiltin: "Symbol")
b.hide(Symbol)
let iteratorSymbol = b.getProperty("iterator", of: Symbol)
let iteratorSymbol = b.createSymbolProperty("iterator")
b.hide(iteratorSymbol)
let iterableObject = b.buildObjectLiteral { obj in
obj.addComputedMethod(iteratorSymbol, with: .parameters(n: 0)) {
Expand Down
Loading