Skip to content

Commit e9c2157

Browse files
LiedtkeV8-internal LUCI CQ
authored andcommitted
Add BindFunction to bind receiver and arguments
Bug: 408162715 Change-Id: I0dcce2908f87b50c578c3ac0b54122b7d6f0bb6e Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/8432040 Commit-Queue: Matthias Liedtke <[email protected]> Reviewed-by: Carl Smith <[email protected]>
1 parent 5d1f780 commit e9c2157

16 files changed

+645
-477
lines changed

Sources/Fuzzilli/Base/ProgramBuilder.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2623,6 +2623,11 @@ public class ProgramBuilder {
26232623
return emit(BindMethod(methodName: name), withInputs: [object]).output
26242624
}
26252625

2626+
@discardableResult
2627+
public func bindFunction(_ fct: Variable, boundArgs arguments: [Variable]) -> Variable {
2628+
return emit(BindFunction(numInputs: arguments.count + 1), withInputs: [fct] + arguments).output
2629+
}
2630+
26262631
@discardableResult
26272632
public func callComputedMethod(_ name: Variable, on object: Variable, withArgs arguments: [Variable] = [], guard isGuarded: Bool = false) -> Variable {
26282633
return emit(CallComputedMethod(numArguments: arguments.count, isGuarded: isGuarded), withInputs: [object, name] + arguments).output

Sources/Fuzzilli/CodeGen/CodeGeneratorWeights.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ public let codeGeneratorWeights = [
139139
"SuperMethodCallGenerator": 20,
140140
"UnboundFunctionCallGenerator": 10,
141141
"UnboundFunctionApplyGenerator": 10,
142+
"UnboundFunctionBindGenerator": 10,
143+
"FunctionBindGenerator": 10,
142144

143145
// These will only be used inside class methods, and only if private properties were previously declared in that class.
144146
"PrivatePropertyRetrievalGenerator": 30,

Sources/Fuzzilli/CodeGen/CodeGenerators.swift

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,8 +1149,6 @@ public let CodeGenerators: [CodeGenerator] = [
11491149
b.callMethod("call", on: f, withArgs: [receiver] + arguments, guard: needGuard)
11501150
},
11511151

1152-
// TODO(mliedtke): Add operation and type inference for a BindFunction which binds a receiver
1153-
// and an arbitrary amount of function arguments.
11541152
CodeGenerator("UnboundFunctionApplyGenerator", inputs: .preferred(.unboundFunction())) { b, f in
11551153
let arguments = b.randomArguments(forCalling: f)
11561154
let fctType = b.type(of: f)
@@ -1162,6 +1160,22 @@ public let CodeGenerators: [CodeGenerator] = [
11621160
b.callMethod("apply", on: f, withArgs: [receiver, b.createArray(with: arguments)], guard: needGuard)
11631161
},
11641162

1163+
CodeGenerator("UnboundFunctionBindGenerator", inputs: .required(.unboundFunction())) { b, f in
1164+
let arguments = b.randomArguments(forCalling: f)
1165+
let fctType = b.type(of: f)
1166+
let receiver = b.randomVariable(forUseAs: fctType.receiver ?? .object())
1167+
let boundArgs = [receiver] + arguments
1168+
b.bindFunction(f, boundArgs: Array(boundArgs[0..<Int.random(in: 0...boundArgs.count)]))
1169+
},
1170+
1171+
CodeGenerator("FunctionBindGenerator", inputs: .required(.function())) { b, f in
1172+
let arguments = b.randomArguments(forCalling: f)
1173+
let fctType = b.type(of: f)
1174+
let receiver = b.randomVariable(forUseAs: .object())
1175+
let boundArgs = [receiver] + arguments
1176+
b.bindFunction(f, boundArgs: Array(boundArgs[0..<Int.random(in: 0...boundArgs.count)]))
1177+
},
1178+
11651179
CodeGenerator("SubroutineReturnGenerator", inContext: .subroutine, inputs: .one) { b, val in
11661180
assert(b.context.contains(.subroutine))
11671181
if probability(0.9) {

Sources/Fuzzilli/FuzzIL/Instruction.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,8 @@ extension Instruction: ProtobufConvertible {
10691069
$0.wrapSuspending = Fuzzilli_Protobuf_WrapSuspending()
10701070
case .bindMethod(let op):
10711071
$0.bindMethod = Fuzzilli_Protobuf_BindMethod.with { $0.methodName = op.methodName }
1072+
case .bindFunction(_):
1073+
$0.bindFunction = Fuzzilli_Protobuf_BindFunction()
10721074
case .print(_):
10731075
fatalError("Print operations should not be serialized")
10741076
// Wasm Operations
@@ -2115,6 +2117,8 @@ extension Instruction: ProtobufConvertible {
21152117
op = WrapSuspending()
21162118
case .bindMethod(let p):
21172119
op = BindMethod(methodName: p.methodName)
2120+
case .bindFunction(_):
2121+
op = BindFunction(numInputs: inouts.count - 1)
21182122
case .print(_):
21192123
fatalError("Should not deserialize a Print instruction!")
21202124

Sources/Fuzzilli/FuzzIL/JSTyper.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1724,6 +1724,24 @@ public struct JSTyper: Analyzer {
17241724
let newParameters = [Parameter.plain(.object())] + signature.parameters
17251725
set(instr.output, .function(newParameters => signature.outputType))
17261726

1727+
case .bindFunction(_):
1728+
let inputType = type(ofInput: 0)
1729+
if let signature = inputType.signature {
1730+
if instr.inputs.count == 1 {
1731+
set(instr.output, inputType)
1732+
} else {
1733+
// We only bind any actual parameters if the BindFunction operation has more
1734+
// than 2 inputs(instr.inputs.count - 2) as the first input is the function
1735+
// on which we call .bind() and the second input is the receiver, so the bind
1736+
// only replaces the existing receiver.
1737+
let start = min(instr.inputs.count - 2, signature.parameters.count)
1738+
let params = Array(signature.parameters[start..<signature.parameters.count])
1739+
set(instr.output, .function(params => signature.outputType))
1740+
}
1741+
} else {
1742+
set(instr.output, .jsAnything)
1743+
}
1744+
17271745
case .wasmBeginTypeGroup(_):
17281746
startTypeGroup()
17291747

Sources/Fuzzilli/FuzzIL/JsOperations.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2466,6 +2466,14 @@ class BindMethod: JsOperation {
24662466
}
24672467
}
24682468

2469+
class BindFunction: JsOperation {
2470+
override var opcode: Opcode { .bindFunction(self) }
2471+
2472+
init(numInputs: Int) {
2473+
super.init(numInputs: numInputs, numOutputs: 1, firstVariadicInput: 1,
2474+
attributes: [.isVariadic], requiredContext: .javascript)
2475+
}
2476+
}
24692477

24702478
// This instruction is used to create strongly typed WasmGlobals in the JS world that can be imported by a WasmModule.
24712479
class CreateWasmGlobal: JsOperation {

Sources/Fuzzilli/FuzzIL/Opcodes.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ enum Opcode {
216216
case wrapPromising(WrapPromising)
217217
case wrapSuspending(WrapSuspending)
218218
case bindMethod(BindMethod)
219+
case bindFunction(BindFunction)
219220

220221
// Wasm opcodes
221222
case consti64(Consti64)

Sources/Fuzzilli/Lifting/FuzzILLifter.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,10 @@ public class FuzzILLifter: Lifter {
795795
case .bindMethod(_):
796796
w.emit("\(output()) <- BindMethod \(input(0))")
797797

798+
case .bindFunction(_):
799+
let inputs = instr.inputs.map(lift).joined(separator: ", ")
800+
w.emit("\(output()) <- BindFunction \(inputs)")
801+
798802
// Wasm Instructions
799803

800804
case .beginWasmFunction(let op):

Sources/Fuzzilli/Lifting/JavaScriptLifter.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1435,6 +1435,12 @@ public class JavaScriptLifter: Lifter {
14351435
let LET = w.varKeyword
14361436
w.emit("\(LET) \(V) = Function.prototype.call.bind(\(OBJECT).\(op.methodName));")
14371437

1438+
case .bindFunction(_):
1439+
let V = w.declare(instr.output)
1440+
let function = input(0)
1441+
let args = inputs.dropFirst()
1442+
w.emit("\(w.varKeyword) \(V) = \(function).bind(\(liftCallArguments(args)));")
1443+
14381444
case .beginWasmModule:
14391445
wasmCodeStarts = instr.index
14401446
assert(wasmInstructions.isEmpty)

Sources/Fuzzilli/Minimization/VariadicInputReducer.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ struct VariadicInputReducer: Reducer {
6969
newOp = CallPrivateMethod(methodName: op.methodName, numArguments: op.numArguments - 1)
7070
case .callSuperMethod(let op):
7171
newOp = CallSuperMethod(methodName: op.methodName, numArguments: op.numArguments - 1)
72+
case .bindFunction(let op):
73+
newOp = BindFunction(numInputs: op.numInputs - 1)
7274
case .createTemplateString(let op):
7375
newOp = CreateTemplateString(parts: op.parts.dropLast())
7476
case .wasmEndTypeGroup(_):

0 commit comments

Comments
 (0)