googleprojectzero / googleprojectzero/fuzzilli
Assertion failure in `ProgramBuilder.swift:2003` when fuzzing SpiderMonkey
Nobody has claimed this yet.
- Dominant language
- Swift
- Stars
- 2.3k
- Forks
- 367
- Avg merge
- 23h 53m
- Merged PRs (30d)
- 1
Description
Summary
After approximately 24–48 hours of fuzzing SpiderMonkey using Fuzzilli, the fuzzer crashes due to an internal assertion failure in ProgramBuilder.handleInputTypeFailure(). Backtrace and crash context indicate an assertion failure triggered in ProgramBuilder.emit(_:withInputs:types:), propagating from a type mismatch during execution.
Environment
- Fuzzilli version: 1e0aadb417df472d97e0106dfd6dafc61e3a09df
- Target: SpiderMonkey build (
obj-fuzzbuild/dist/bin/js) - Platform: Ubuntu 24.04.3 LTS x86_64
- Runtime:
6.2 (swift-6.2-RELEASE)
Command used
swift run FuzzilliCli --resume --jobs=40 \
--profile=spidermonkey \
--wasm \
--storagePath=/home/fuzz/spidermonkey-output \
/home/fuzz/gecko-dev/obj-fuzzbuild/dist/bin/js
Analysis
- The crash originates from a failed assertion validating input types during the emission of a
WasmJsCall. - The failing input combines
.object()and.function()type unions in a configuration not expected by the builder. - The issue likely results from mismatched inferred types during Wasm code generation (see
WasmJsCallandWasmCodeGenerators.swift:893).
Full crash log
Fuzzilli/ProgramBuilder.swift:2003: Assertion failed: Invalid input 1 v3 with type .object() + .function() | .function() + .constructor(), expected .object() | .function() 10:52:47
💣 Program crashed: Illegal instruction at 0x00007f9e3d2e26b8
Platform: x86_64 Linux (Ubuntu 24.04.3 LTS)
Thread 20 crashed:
0 0x00007f9e3d2e26b8 _assertionFailure(_:_:file:line:flags:) + 264 in libswiftCore.so
1 ProgramBuilder.handleInputTypeFailure(_:) + 1017 in FuzzilliCli at /home/fuzz/fuzzilli/Sources/Fuzzilli/Base/ProgramBuilder.swift:2003:9
2001│ }
2002│ // Fail on debug builds.
2003│ assert(false, message)
│ ▲
2004│ }
2005│
2 closure #1 in ProgramBuilder.emit(_:withInputs:types:) + 1206 in FuzzilliCli at /home/fuzz/fuzzilli/Sources/Fuzzilli/Base/ProgramBuilder.swift:2026:21
2024│ let actualType = self.type(of: input)
2025│ if !actualType.Is(type) {
2026│ handleInputTypeFailure("Invalid input \(n + 1) \(input) with type \(actualType), expected \(type)")
│ ▲
2027│ }
2028│ }
3 0x00007f9e3d32ef1d Sequence.forEach(_:) + 412 in libswiftCore.so
4 ProgramBuilder.emit(_:withInputs:types:) + 1860 in FuzzilliCli at /home/fuzz/fuzzilli/Sources/Fuzzilli/Base/ProgramBuilder.swift:2022:53
2020│ handleInputTypeFailure("expected \(expectedTypes.count) inputs, actual \(inputs.count)")
2021│ }
2022│ zip(inputs, expectedTypes).enumerated().forEach { n, pair in
│ ▲
2023│ let (input, type) = pair
2024│ let actualType = self.type(of: input)
5 ProgramBuilder.WasmFunction.wasmJsCall(function:withArgs:withWasmSignature:) + 931 in FuzzilliCli at /home/fuzz/fuzzilli/Sources/Fuzzilli/Base/ProgramBuilder.swift:3360:27
3358│ @discardableResult
3359│ public func wasmJsCall(function: Variable, withArgs args: [Variable], withWasmSignature signature: WasmSignature) -> Variable? {
3360│ let instr = b.emit(WasmJsCall(signature: signature), withInputs: [function] + args,
│ ▲
3361│ types: [.function() | .object(ofGroup: "WasmSuspendingObject")] + signature.parameterTypes)
3362│ if signature.outputTypes.isEmpty {
6 closure #91 in variable initialization expression of WasmCodeGenerators + 382 in FuzzilliCli at /home/fuzz/fuzzilli/Sources/Fuzzilli/CodeGen/WasmCodeGenerators.swift:893:22
891│ let function = b.currentWasmModule.currentWasmFunction
892│ if let (wasmSignature, arguments) = b.randomWasmArguments(forCallingJsFunction: callable) {
893│ function.wasmJsCall(function: callable, withArgs: arguments, withWasmSignature: wasmSignature)
│ ▲
894│ }
895│ },
7 GeneratorAdapter1Arg.run(in:with:) + 296 in FuzzilliCli at /home/fuzz/fuzzilli/Sources/Fuzzilli/CodeGen/CodeGenerator.swift:46:9
44│ func run(in b: ProgramBuilder, with inputs: [Variable]) {
45│ assert(inputs.count == 1)
46│ f(b, inputs[0])
│ ▲
47│ }
48│ }
8 CodeGenerator.run(in:with:) + 252 in FuzzilliCli at /home/fuzz/fuzzilli/Sources/Fuzzilli/CodeGen/CodeGenerator.swift:194:17
192│ public func run(in b: ProgramBuilder, with inputs: [Variable]) -> Int {
193│ let codeSizeBeforeGeneration = b.indexOfNextInstruction()
194│ adapter.run(in: b, with: inputs)
│ ▲
195│ self.invoked()
196│ let codeSizeAfterGeneration = b.indexOfNextInstruction()
9 ProgramBuilder.run(_:) + 1369 in FuzzilliCli at /home/fuzz/fuzzilli/Sources/Fuzzilli/Base/ProgramBuilder.swift:1973:50
1971│ }
1972│ }
1973│ let numGeneratedInstructions = generator.run(in: self, with: inputs)
│ ▲
1974│ trace("Code generator finished")
1975│
10 ProgramBuilder.buildInternal(initialBuildingBudget:mode:) + 3085 in FuzzilliCli at /home/fuzz/fuzzilli/Sources/Fuzzilli/Base/ProgramBuilder.swift:1824:17
1822│ let generator = availableGenerators.randomElement()
1823│ buildLog?.startAction(generator.name)
1824│ run(generator)
│ ▲
1825│
1826│ case .splicing:
11 ProgramBuilder.build(n:by:) + 299 in FuzzilliCli at /home/fuzz/fuzzilli/Sources/Fuzzilli/Base/ProgramBuilder.swift:1700:9
1698│ public func build(n: Int = 1, by mode: BuildingMode = .generatingAndSplicing) {
1699│ assert(buildStack.isEmpty)
1700│ buildInternal(initialBuildingBudget: n, mode: mode)
│ ▲
1701│ assert(buildStack.isEmpty)
1702│ }
12 CodeGenMutator.mutate(_:_:) + 649 in FuzzilliCli at /home/fuzz/fuzzilli/Sources/Fuzzilli/Mutators/CodeGenMutator.swift:53:15
51│ b.adopt(instr)
52│ assert(b.numberOfVisibleVariables >= minVisibleVariables)
53│ b.build(n: defaultCodeGenerationAmount, by: .generating)
│ ▲
54│ }
55│ }
13 closure #1 in BaseInstructionMutator.mutate(_:using:for:) + 709 in FuzzilliCli at /home/fuzz/fuzzilli/Sources/Fuzzilli/Mutators/BaseInstructionMutator.swift:46:21
44│ for instr in program.code {
45│ if toMutate.contains(instr.index) {
46│ mutate(instr, b)
│ ▲
47│ } else {
48│ b.adopt(instr)
14 ProgramBuilder.adopting(from:_:) + 83 in FuzzilliCli at /home/fuzz/fuzzilli/Sources/Fuzzilli/Base/ProgramBuilder.swift:1297:9
1295│ public func adopting(from program: Program, _ block: () -> Void) {
1296│ beginAdoption(from: program)
1297│ block()
│ ▲
1298│ endAdoption()
1299│ }
15 BaseInstructionMutator.mutate(_:using:for:) + 1486 in FuzzilliCli at /home/fuzz/fuzzilli/Sources/Fuzzilli/Mutators/BaseInstructionMutator.swift:43:11
41│ }
42│
43│ b.adopting(from: program) {
│ ▲
44│ for instr in program.code {
45│ if toMutate.contains(instr.index) {
16 Mutator.mutate(_:for:) + 315 in FuzzilliCli at /home/fuzz/fuzzilli/Sources/Fuzzilli/Mutators/Mutator.swift:26:23
24│ let b = fuzzer.makeBuilder(forMutating: program)
25│ b.traceHeader("Mutating \(program.id) with \(name)")
26│ let program = mutate(program, using: b, for: fuzzer)
│ ▲
27│ program?.contributors.insert(self)
28│ return program
17 MutationEngine.fuzzOne(_:) + 1310 in FuzzilliCli at /home/fuzz/fuzzilli/Sources/Fuzzilli/Engines/MutationEngine.swift:56:41
54│ var mutatedProgram: Program? = nil
55│ for _ in 0..<maxAttempts {
56│ if let result = mutator.mutate(parent, for: fuzzer) {
│ ▲
57│ // Success!
56│ if let result = mutator.mutate(parent, for: fuzzer) {
│ ▲
57│ // Success!
58│ result.contributors.formUnion(parent.contributors)
18 Fuzzer.fuzzOne() + 12496 in FuzzilliCli at /home/fuzz/fuzzilli/Sources/Fuzzilli/Fuzzer.swift:894:20
892│ case .fuzzing:
893│ iterations += 1
894│ engine.fuzzOne(fuzzGroup)
│ ▲
895│ }
896│
19 closure #1 in Fuzzer.fuzzOne() + 26 in FuzzilliCli at /home/fuzz/fuzzilli/Sources/Fuzzilli/Fuzzer.swift:899:18
897│ // Perform the next iteration as soon as all tasks related to the current iteration are finished.
898│ fuzzGroup.notify(queue: queue) {
899│ self.fuzzOne()
│ ▲
900│ }
901│ }
...
Backtrace took 14.56s
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with ProgramBuilder.swift around lines 2003, 2022, and 3360 to trace the input-type validation for WasmJsCall. Then inspect WasmCodeGenerators.swift:893 and reproduce with the provided SpiderMonkey fuzzing command; done means the type mismatch no longer triggers the assertion during this path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- swift, wasm
- Domain
- compilers, testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100