Skip to content

Rebase on upstream main and update Bun profile with missing APIs#8

Open
robobun wants to merge 16 commits intooven-sh:mainfrom
robobun:farm/6d2cda71/rebase-and-update-profile
Open

Rebase on upstream main and update Bun profile with missing APIs#8
robobun wants to merge 16 commits intooven-sh:mainfrom
robobun:farm/6d2cda71/rebase-and-update-profile

Conversation

@robobun
Copy link
Copy Markdown

@robobun robobun commented Apr 2, 2026

Merges upstream googleprojectzero/fuzzilli main (was 14 commits behind, now current) and updates the Bun profile with missing APIs.

After merging this PR, the fork will be only ahead of upstream (0 behind) — upstream/main is an ancestor of this branch via the merge commit, so GitHub won't show "N behind".

Important: merge this PR (don't squash), so the merge commit's upstream parent link is preserved. Squashing would lose it and GitHub would show "behind" again.

New APIs added to BunProfile

Functions:

  • Bun.connect — TCP/TLS client connections
  • Bun.listen — TCP/TLS server listeners
  • Bun.sliceAnsi — ANSI-aware string slicing
  • Bun.readableStreamToFormData — stream-to-FormData conversion
  • Bun.cron / Bun.cron.remove / Bun.cron.parse — cron scheduling
  • Bun.plugin — plugin registration
  • Bun.gc — garbage collection trigger

Properties:

  • Bun.argv, Bun.env, Bun.main, Bun.cwd
  • Bun.stdin, Bun.stdout, Bun.stderr

Object groups:

  • Listener — returned by Bun.listen()
  • UDPSocket — returned by Bun.udpSocket()
  • BuildArtifact — returned by Bun.build()

Fixes

  • Bun.JSONL: methods are parse + parseChunk (was incorrectly stringify)
  • Bun.markdown: added react method (was missing, only had html/render)
  • Bun.dns: expanded from just lookup to include resolve, prefetch, getCacheStats, reverse
  • Bun.udpSocket: now returns typed BunUDPSocket instead of jsAnything

Verification

Swift 6.1 build passes. upstream/main is a merge ancestor — post-merge shows 0 behind.

Liedtke and others added 16 commits March 18, 2026 10:53
While this changes the IL to emit wasm-gc signatures for the functions,
it doesn't yet actually allow using wasm-gc types in them.
A few places (WasmDefineTable and WasmCallIndirect /
WasmReturnCallIndirect) still need to be adapted to allow wasm-gc types
before we can actually allow indexed wasm-gc types in function
signatures.

Bug: 445356784
Change-Id: I5715f584cfa5ee664f957a28e28bf80b6f3cdd9e
Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/9115296
Commit-Queue: Matthias Liedtke <mliedtke@google.com>
Reviewed-by: Manos Koukoutos <manoskouk@google.com>
Change-Id: I4e2111aca7b7619584bffe9d008c60f55da18999
Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/9122916
Auto-Submit: Michael Achenbach <machenbach@google.com>
Reviewed-by: Matthias Liedtke <mliedtke@google.com>
Commit-Queue: Matthias Liedtke <mliedtke@google.com>
This simplifies and reduces a lot of code and prepares adding support
for more kinds of class members without exploding the number of
instructions due to the additional factor 2 for static and instance
members.

Concretely this merges instructions for all members (properties,
elements and methods) that have a static and non-static (instance)
variant. The static bit is represented by a variable in the
instruction.

This was also tested locally with and without this change, both with
large number for class-related code generators. Both versions
resulted in similar correctness stats without any crashes.

Bug: 446634535
Change-Id: I57b3261e202dffeb57704d0040b2a8d02b50a9e6
Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/9094176
Reviewed-by: Matthias Liedtke <mliedtke@google.com>
Commit-Queue: Michael Achenbach <machenbach@google.com>
The TableType will need to be adapted for tracking wasm-gc
signatures. I just couldn't find a good reason why we'd need to store
the TableType on Table.get and Table.set?

Bug: 445356784
Change-Id: Ia115d287b27cc18f52a48ddce25b897f1a19b293
Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/9123736
Reviewed-by: Manos Koukoutos <manoskouk@google.com>
Commit-Queue: Matthias Liedtke <mliedtke@google.com>
Change-Id: I99bc88a3cefdd5d4cbaf645b10e1cdcd66138a52
Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/9123977
Commit-Queue: Manos Koukoutos <manoskouk@google.com>
Reviewed-by: Manos Koukoutos <manoskouk@google.com>
Auto-Submit: Matthias Liedtke <mliedtke@google.com>
The WasmThrowRefGenerator requires an exnref as an input. Without having
a generator that produces it, it isn't very likely that there is an
exnref available in the current program, so the generator cannot be run
in most cases.

Registering a generator producing that exnref (if a tag is available)
helps significantly.

Change-Id: Idbd9337f5a7339d58fe1f76e264569907f7081ce
Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/9123976
Auto-Submit: Matthias Liedtke <mliedtke@google.com>
Reviewed-by: Manos Koukoutos <manoskouk@google.com>
Commit-Queue: Manos Koukoutos <manoskouk@google.com>
The first attempt of fixing this was
commit 89691a1,
however this means we might end up not typing the inner outputs (the
tag's "elements" available inside the catch) which breaks the typer's
assumptions that everything gets typed.
Typing it with some dummy value can also lead to issues downstream (e.g.
by the next instruction taking now an input that isn't of the needed
type any more), so instead we solve this issue by always also adding a
signature as an input. As the signature is defined in Wasm, input
replacement can only happen with strict type checks, so it is safe to
rely on this.

It's a bit annoying for the WasmBeginCatch to take an extra input for
this specific problem, however, WasmBeginCatch is anyways related to the
"legacy" exception handling which isn't a properly spec'ed Wasm feature
but a "browsers have been shipping this without a finished spec" kind of
thing.

Bug: 448860865
Change-Id: I06638ccbb5ed0c9dbb7355ac198b7ace25f521b8
Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/9129497
Reviewed-by: Michael Achenbach <machenbach@google.com>
Auto-Submit: Matthias Liedtke <mliedtke@google.com>
Commit-Queue: Matthias Liedtke <mliedtke@google.com>
The issue was introduced with
commit 7fb8254

While I was running the fuzzer for multiple hours, the fuzzer is more
persmissive in not crashing on invalid programs send over the wire, so
this wasn't detected.

Change-Id: I34f04902915539cb688c5c6eb6825d28a123ccb0
Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/9130176
Reviewed-by: Michael Achenbach <machenbach@google.com>
Commit-Queue: Michael Achenbach <machenbach@google.com>
Auto-Submit: Matthias Liedtke <mliedtke@google.com>
Reviewed-by: Olivier Flückiger <olivf@google.com>
Change-Id: I6a3f252f20742dac630864ab4b07e493dbde46ec
Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/9133476
Commit-Queue: Michael Achenbach <machenbach@google.com>
Reviewed-by: Michael Achenbach <machenbach@google.com>
Commit-Queue: Matthias Liedtke <mliedtke@google.com>
Auto-Submit: Matthias Liedtke <mliedtke@google.com>
Similar to method names, this supports all allowed ways to
define properties. Approximated valid identifiers will be used
as is, everything else will be quoted, except positive integers.

Since such a property can leak into the type information of an
object or class, also all property accesses are adapted now, similar
to method calls.

This also refactors the import of object fields and methods, unifying
the same property-key logic used in class definitions.

Computed getters and setters for object literals and classes are still
a TODO.

This also lifts some restrictions from runtime assisted mutators,
which previously only allowed simple identifiers as property names.

Bug: 446634535
Change-Id: I35a65c0073fee9bac238205557958e80c60e1186
Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/9111376
Commit-Queue: Michael Achenbach <machenbach@google.com>
Reviewed-by: Matthias Liedtke <mliedtke@google.com>
Bug: 495679730
Change-Id: I45c1af939f3e1a81fc1c3a2649652e25c644cc82
Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/9137477
Reviewed-by: Darius Mercadier <dmercadier@google.com>
Commit-Queue: Matthias Liedtke <mliedtke@google.com>
When a program instrumented by RuntimeAssistedMutator crashes, we avoid calling
processCrash() on it immediately. This is because the boilerplate code added
during instrumentation makes such crashes difficult to minimize
(see, e.g., https://g-issues.chromium.org/issues/488963988?pli=1&authuser=0).

Instead, we follow this procedure:
1. Always log the crash of the instrumented program.
2. Check if the process()'d version of the instrumented program also crashes.
3. If yes, we call processCrash() on that program instead, as its more straightforward to minimize.

Bug: 488963988
Change-Id: Iffefc9435f4ef31a3fbf798d374a04f9f1fc115a
Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/9129498
Reviewed-by: Matthias Liedtke <mliedtke@google.com>
Commit-Queue: Leon Bettscheider <bettscheider@google.com>
We need at least "warning" level to see logs from worker threads.

Change-Id: I4ec5d9d89f5697cf5710a250888e054789716f78
Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/9151416
Commit-Queue: Leon Bettscheider <bettscheider@google.com>
Reviewed-by: Matthias Liedtke <mliedtke@google.com>
Reviewed-by: Michael Achenbach <machenbach@google.com>
Fixed: 496097209
Change-Id: Icb0f88bcf619791fa3a45af7f0f2cd73428d37df
Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/9141456
Auto-Submit: Michael Achenbach <machenbach@google.com>
Commit-Queue: Matthias Liedtke <mliedtke@google.com>
Reviewed-by: Matthias Liedtke <mliedtke@google.com>
- Add Bun.connect, Bun.listen, Bun.sliceAnsi, Bun.readableStreamToFormData
- Add Bun.cron (.remove, .parse), Bun.plugin, Bun.gc
- Add Bun.argv, Bun.env, Bun.main, Bun.cwd, Bun.stdin/stdout/stderr
- Add Bun.markdown.react method
- Add Listener, UDPSocket, BuildArtifact object groups
- Fix JSONL methods (parse + parseChunk, not stringify)
- Fix Bun.dns to include resolve/prefetch/getCacheStats/reverse
- Fix Bun.udpSocket return type
@robobun robobun force-pushed the farm/6d2cda71/rebase-and-update-profile branch from 4710684 to e62eb32 Compare April 2, 2026 20:28
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 2, 2026

Walkthrough

This PR consolidates instance/static/private class member operation variants into unified opcodes accepting an isStatic flag, refactors Wasm function operations to use parameter/output counts instead of full signatures, simplifies Wasm table access operations by removing embedded type information, updates string fuzzing distribution and property name validation, and introduces a new Wasm exception reference generator.

Changes

Cohort / File(s) Summary
Protobuf Schema Consolidation
Sources/Fuzzilli/Protobuf/operations.proto, operations.pb.swift, program.proto, ast.proto, ast.pb.swift
Unified class member messages by replacing instance/static/private variants with single messages carrying is_static boolean field; simplified Wasm function messages to use counts instead of type arrays; removed embedded table-type fields from Wasm table access messages; consolidated object literal key handling from oneof variants to single PropertyKey field.
Class Opcode Definitions and Operations
Sources/Fuzzilli/FuzzIL/Opcodes.swift, JsOperations.swift, Instruction.swift
Consolidated 30\+ opcode variants for class members into 13 unified opcodes with isStatic parameter; updated protobuf conversion logic to handle new consolidated message structure.
Class Member Code Generation
Sources/Fuzzilli/CodeGen/CodeGenerators.swift, Sources/Fuzzilli/Compiler/Compiler.swift, Sources/Fuzzilli/Base/ProgramBuilder.swift
Replaced separate instance/static method/property/getter/setter emission with unified begin/end opcodes accepting isStatic flag; consolidated object-literal key handling in compiler; updated builder state tracking for new opcode shape.
Wasm Operation Refactoring
Sources/Fuzzilli/FuzzIL/WasmOperations.swift, CodeGen/WasmCodeGenerators.swift, Lifting/WasmLifter.swift
Changed BeginWasmFunction/EndWasmFunction from signature-based to parameter/output count-based construction; removed table-type fields from WasmTableGet/WasmTableSet; refactored Wasm function construction to use signature-definition inputs; optimized section emission to skip empty sections.
Type System Integration
Sources/Fuzzilli/FuzzIL/JSTyper.swift, Semantics.swift
Updated class member type handling to route through unified opcodes using op.isStatic; adjusted Wasm operation typing to derive information from inputs instead of payloads; updated begin/end opcode matching for class members.
Wasm Exception Reference Generator
Sources/Fuzzilli/CodeGen/CodeGeneratorWeights.swift, WasmCodeGenerators.swift
Added new WasmCreateExnRefGenerator code generator producing .wasmExnRef() from .wasmTag input; registered generator with weight 1 in fuzzing weights.
Parser and Compilation
Sources/Fuzzilli/Compiler/Parser/parser.js
Unified object property/method/getter/setter key handling using single visitMemberKey function; replaced conditional inline type checks with consolidated key-assignment logic.
String Generation and Validation
Sources/Fuzzilli/Environment/JavaScriptEnvironment.swift, Lifting/JavaScriptExploreLifting.swift, JavaScriptProbeLifting.swift, JavaScriptRuntimeAssistedMutatorLifting.swift, Mutators/ProbingMutator.swift
Expanded random string distribution to include empty strings and much longer strings (0-33 characters); added empty string to interesting strings; changed custom property names; refactored identifier validation to use static regexes; introduced isShortString predicate (length < 50); removed property-name validation filtering.
Lifting and Code Emission
Sources/Fuzzilli/Lifting/JavaScriptLifter.swift, FuzzILLifter.swift, JavaScriptExploreLifting.swift
Updated class member and property lifting to use unified opcodes with conditional static prefix; introduced quoteIdentifierIfNeeded for property names; added guarded member access support with optional-chain syntax; updated super property access concatenation.
Minimization and Mutation
Sources/Fuzzilli/Minimization/BlockReducer.swift, InliningReducer.swift, Mutators/OperationMutator.swift
Updated block reducer, inlining reducer, and operation mutator to use unified class member opcodes; consolidated switch cases for instance/static/private variants.
Fuzzer Infrastructure
Sources/Fuzzilli/Fuzzer.swift, Mutators/RuntimeAssistedMutator.swift
Refactored crash metadata collection into collectCrashInfo helper; added caching of execution outputs to avoid invalidation; added new instrumentedProgramCrashed outcome case.
Profile Updates
Sources/Fuzzilli/Profiles/BunProfile.swift
Extended BunJSONL to use parseChunk instead of stringify; added IL type definitions and object groups for BunListener, BunUDPSocket, BunBuildArtifact; expanded Bun API surface with DNS, cron, plugin, and I/O builtins.
Test Additions and Updates
Tests/FuzzilliTests/LifterTest.swift, MinimizerTest.swift, ProgramBuilderTest.swift, computed_and_indexed_properties.js, CrashingInstrumentationMutator.swift, RuntimeAssistedMutatorTests.swift
Added tests for property lifting with weird names, super property access, empty Wasm modules, and instrumented program crash reporting; updated Wasm function return value expectations from consti32 to consti64; added WasmThrowRefGenerator scheduling test.
GitHub Actions
.github/workflows/swift.yml
Updated Node.js runtime from 25-nightly to 26-nightly.

Possibly related PRs

  • Sync upstream/main (60 commits) #7 - Overlapping changes that consolidate class instance/static/private opcode variants into unified forms with isStatic flag, and refactor Wasm operations to use count-based representations instead of full signature/type information.
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: rebasing on upstream main and updating the Bun profile with missing APIs. It is concise, clear, and directly reflects the primary objectives of the pull request.
Description check ✅ Passed The PR description clearly relates to the changeset, describing a rebase on upstream main and updates to the Bun profile with new APIs, fixes, and verification details that match the file changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
Sources/Fuzzilli/Profiles/BunProfile.swift (1)

2020-2026: ⚠️ Potential issue | 🟡 Minor

Add the optional boundary parameter for Bun.readableStreamToFormData.

The Bun runtime supports Bun.readableStreamToFormData(stream, multipartBoundaryExcludingDashes?) for parsing multipart form data with a custom boundary. The second parameter is optional and accepts string | Uint8Array | ArrayBufferView, but the current signature only models the single-argument path.

Consider using .opt(.jsAnything) instead of .opt(.string) to fully represent the accepted parameter types:

Suggested fix
-        "Bun.readableStreamToFormData"    : .function([.jsAnything] => .jsPromise),
+        "Bun.readableStreamToFormData"    : .function([.jsAnything, .opt(.jsAnything)] => .jsPromise),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/Fuzzilli/Profiles/BunProfile.swift` around lines 2020 - 2026, The
signature for Bun.readableStreamToFormData currently models only a
single-argument path; update its type to accept the optional boundary parameter
which can be string | Uint8Array | ArrayBufferView by replacing the
second-argument type with an optional jsAnything (e.g. change the entry for
"Bun.readableStreamToFormData" to a function taking [.jsAnything,
.opt(.jsAnything)] => .jsPromise or use .opt(.jsAnything) instead of
.opt(.string)) so the profile reflects the runtime's accepted types.
Sources/Fuzzilli/FuzzIL/JSTyper.swift (1)

806-822: ⚠️ Potential issue | 🟠 Major

Validate the referenced signature before using it to drive op arity.

These branches now trust instr.input(0) to define parameter/output counts, but the instruction shape is still fixed by numOutputs, numInnerOutputs, and numInputs. If mutation or minimization swaps in a different signature definition, wasmJsCall can touch instr.output when the op has no outputs, and the begin/end function paths can leave the function shape inconsistent with what the lifter expects. Please compare the signature counts against the op counts before using them and reject or fall back on mismatches.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/Fuzzilli/FuzzIL/JSTyper.swift` around lines 806 - 822, Validate the
wasm signature's parameter/output counts against the instruction's expected
shape before using it in wasmJsCall, beginWasmFunction, and endWasmFunction: for
wasmJsCall check that signature.outputTypes.count matches instr.numOutputs (or
is zero when instr has no outputs) before calling setType(of: instr.output, ...)
and before using instr.input(1)'s signature in addWasmFunction; for
beginWasmFunction ensure signature.parameter count matches instr.numInputs (and
output count matches instr.numInnerOutputs/numOutputs as appropriate) before
calling wasmTypeBeginBlock; for endWasmFunction only call setType(of:
instr.output, ...) and addWasmFunction when the signature counts match,
otherwise fall back to a safe default (e.g. use
Signature.forUnknownFunction/skip setting types) and/or log/reject the
inconsistent signature so mutation/minimization swaps don't corrupt op arity;
reference wasmFunctionSignatureDefSignature, instr.input(0), instr.output,
wasmTypeBeginBlock, setType, dynamicObjectGroupManager.addWasmFunction,
ProgramBuilder.convertWasmSignatureToJsSignature, and defUseAnalyzer.definition
when making these checks and fallbacks.
Sources/Fuzzilli/Protobuf/operations.pb.swift (1)

4001-4018: ⚠️ Potential issue | 🟠 Major

Reuse field 2 for parameterCount and outputCount instead of field 1 to maintain protobuf wire compatibility.

Lines 11111 and 11141 decode field 1 as Int32 for BeginWasmFunction and EndWasmFunction respectively, but field 1 previously held repeated message payloads (parameterTypes / outputTypes). This is a wire-incompatible protobuf change; older serialized corpora and mixed-version workers will fail to deserialize these messages without an explicit migration. Use fresh field numbers (e.g., field 2) for the new count fields in operations.proto to maintain backward compatibility.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/Fuzzilli/Protobuf/operations.pb.swift` around lines 4001 - 4018, The
new Int32 fields parameterCount (in Fuzzilli_Protobuf_BeginWasmFunction) and
outputCount (in Fuzzilli_Protobuf_EndWasmFunction) are using field number 1
which collides with the original repeated message fields
(parameterTypes/outputTypes) and breaks wire compatibility; update the proto and
generated Swift handling to use a fresh field number (e.g., field 2) instead:
change the field numbers in operations.proto for these count fields to 2, then
regenerate the Swift protobuf sources (or, if editing generated code directly,
change the tag handling for parameterCount and outputCount to the field-2 tag
and update encode/decode paths and default values accordingly) so older
serialized data remains compatible.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Sources/Fuzzilli/Base/ProgramBuilder.swift`:
- Around line 4099-4105: The prepass that builds tagSignatures force-unwraps
b.type(of: clause.tag).wasmTagType (in the tagSignatures construction that calls
b.wasmDefineAdHocSignatureType) before the per-clause validation (reportErrorIf)
runs, which causes a trap on non-tag inputs; change the prepass to avoid
force-unwrapping — instead check for a valid wasmTagType (or skip/produce a
placeholder) and only call b.wasmDefineAdHocSignatureType when wasmTagType is
present, leaving the existing reportErrorIf checks inside the catchClauses loop
to emit diagnostics for invalid tags (apply the same pattern to the other
similar helper at the other site).
- Around line 3504-3509: The initializer public init(forBuilder b:
ProgramBuilder, signatureDef: Variable) currently only asserts .wasmTypeDef();
tighten the API boundary by asserting (or preconditioning) that signatureDef is
specifically a wasm function-signature definition (e.g., check b.type(of:
signatureDef).Is(.wasmFunctionSignatureDef()) or that b.type(of:
signatureDef).wasmFunctionSignatureDefSignature is non-nil) so the later use of
wasmFunctionSignatureDefSignature is safe; apply the same stronger validation to
the other overloads/constructors and callers mentioned (the BeginWasmFunction
overloads and the code paths around the other occurrences) and, where possible,
keep BeginWasmFunction parameter types or signatures constrained to
function-signature defs instead of the more generic wasm type def to prevent
accepting arrays/structs.

In `@Sources/Fuzzilli/CodeGen/CodeGenerators.swift`:
- Around line 1260-1265: The private-class-method generators currently call
b.randomParameters() and immediately emit BeginClassPrivateMethod (symbols:
b.randomParameters, BeginClassPrivateMethod) without seeding parameter types;
before emitting BeginClassPrivateMethod call setParameterTypesForNextSubroutine
on the builder with the parameter type information returned by
b.randomParameters() so the private-method body receives the same
typed-parameter context as public class-method generators—apply the same change
to both occurrences (around the blocks that use b.randomParameters and
BeginClassPrivateMethod, including the second occurrence near the other similar
block).

In `@Sources/Fuzzilli/CodeGen/CodeGeneratorWeights.swift`:
- Around line 327-330: The test matrix for GC generator scheduling is missing an
explicit case for the new weighted generator WasmCreateExnRefGenerator; add a
scheduling assertion that verifies WasmCreateExnRefGenerator is scheduled (with
expected weight/priority) similar to the existing WasmThrowRefGenerator entry so
regressions are caught—locate the GC scheduling tests that reference
"WasmThrowRefGenerator" and add a corresponding assertion or test row for
"WasmCreateExnRefGenerator" that checks it appears in the schedule and honors
its weight.

In `@Sources/Fuzzilli/FuzzIL/Instruction.swift`:
- Around line 616-679: The change alters the on-disk protobuf shape for several
class-member (e.g., the Instruction.swift cases classAddProperty,
classAddElement, classAddComputedProperty, classAddPrivateProperty,
beginClassMethod, beginClassComputedMethod, beginClassGetter/Setter, etc.) and
Wasm instruction encodings, so update the persisted-format handling by bumping
the repository's serialized format version (the serialized-format/version
constant used by the Instruction/protobuf serializer) or implement explicit
migration logic in the encoder/decoder path (where instructions are converted
to/from Fuzzilli_Protobuf_* messages) to accept both old and new shapes, and add
a short upgrade note describing the incompatibility; apply the same treatment to
the other changed ranges you mentioned (1261–1264, 1331–1336, 1866–1897,
2329–2332, 2365–2368).

In `@Sources/Fuzzilli/FuzzIL/JSTyper.swift`:
- Around line 1355-1378: Replace the forced casts that follow debug-only asserts
in the .endClassMethod, .endClassGetter and .endClassSetter cases with safe
guarded downcasts: after the existing assert(...) keep it but change the `let
beginOp = begin.op as! BeginClassMethod/BeginClassGetter/BeginClassSetter` to a
guarded conditional downcast (`guard let beginOp = begin.op as?
BeginClassMethod` / `BeginClassGetter` / `BeginClassSetter` else { return } or
otherwise exit the case), then proceed to call
dynamicObjectGroupManager.update... using the safe beginOp; this preserves the
assert in debug builds but avoids crashes in optimized builds when begin.op is
malformed.

In `@Sources/Fuzzilli/Lifting/JavaScriptLifter.swift`:
- Around line 537-542: The class method emitter in the beginClassMethod case
currently sets METHOD = quoteIdentifierIfNeeded(op.methodName) and emits
"\(staticStr)\(METHOD)(\(PARAMS)) {", which when op.methodName == "constructor"
and op.isStatic == false produces a real constructor; change the logic to detect
the special case (op.methodName == "constructor" && !op.isStatic) and instead
set METHOD to a bracketed quoted form (e.g. "[\"constructor\"]") or a computed
property string so the emitted line becomes non-constructor regular method
syntax; update the code surrounding case .beginClassMethod, METHOD, and the
w.emit call to use this alternate METHOD only for that condition.

In `@Sources/Fuzzilli/Mutators/RuntimeAssistedMutator.swift`:
- Line 126: Replace the use of execution.fuzzout with the cached oldFuzzout when
calling process(...) to match the caching strategy used elsewhere; specifically
update the call in RuntimeAssistedMutator where process(...) is invoked (the
tuple assignment to (mutatedProgram, outcome)) to pass oldFuzzout so it remains
consistent with the cached value invalidation logic used around execute(),
processInstrumentedProgram, and the later reference at line 150.
- Around line 139-141: After calling logger.warning(...) and
fuzzer.processCrash(instrumentedProgram, withSignal: signal, withStderr:
oldStderr, withStdout: stdout, origin: .local, withExectime: execution.execTime)
you must return immediately to avoid falling through and re-processing the
program; add a return statement right after the fuzzer.processCrash(...) call in
the same scope (the function that later calls process()) so the function exits
once the instrumented crash has been reported.

In `@Sources/Fuzzilli/Profiles/BunProfile.swift`:
- Around line 132-136: The BunJSONL ILType currently models both methods as
string->jsAnything; update the bunJSONL ILType (symbol bunJSONL) so parse
accepts a union input type (string | TypedArray | DataView | ArrayBufferLike)
and returns an array of JS values, and parseChunk accepts the same union input
plus optional numeric start and end parameters and returns a structured object
with properties { values: Array, read: Number, done: Boolean, error: Any|null }
so the profile can exercise zero-copy/partial-buffer paths and validate the
incremental parser result shape for methods "parse" and "parseChunk".
- Around line 246-250: The BunBuildArtifact IL type (bunBuildArtifact) is
missing the documented bytes() method and the sourcemap property is incorrectly
typed; update the ILType.object for bunBuildArtifact to add "bytes" to the
withMethods array while keeping "json", and change the "sourcemap" property to
be nullable and reference a BuildArtifact (i.e., make its type an optional
BuildArtifact/ILType.object reference rather than .jsAnything) so it correctly
models Promise<Uint8Array> for bytes() and the sourcemap relationship.

In `@Sources/Fuzzilli/Protobuf/ast.pb.swift`:
- Around line 1479-1486: The generated change replaces individual key fields
with an embedded PropertyKey message for
Compiler_Protobuf_ObjectProperty/ObjectMethod/ObjectGetter/ObjectSetter which
may break wire-format compatibility; inspect ast.proto and confirm the field
numbers and types for the affected messages and the PropertyKey message, then
either restore the original scalar/oneof fields and their original tag numbers
or add the new embedded field under a new tag while keeping the old tags (mark
them deprecated) so older binaries can still parse existing payloads, implement
a version/migration field if you intend to change semantics, and finally
regenerate Sources/Fuzzilli/Protobuf/ast.pb.swift (ensuring
Compiler_Protobuf_ObjectProperty, Compiler_Protobuf_ObjectMethod,
Compiler_Protobuf_ObjectGetter, Compiler_Protobuf_ObjectSetter and PropertyKey
definitions align with the stable tags).

In `@Tests/FuzzilliTests/CrashingInstrumentationMutator.swift`:
- Line 33: The statement calling b.eval contains a trailing semicolon which is
unnecessary in Swift; update the expression b.eval("fuzzilli('FUZZILLI_CRASH',
0)"); by removing the final semicolon so it becomes
b.eval("fuzzilli('FUZZILLI_CRASH', 0)") to match Swift style and avoid
extraneous punctuation.

---

Outside diff comments:
In `@Sources/Fuzzilli/FuzzIL/JSTyper.swift`:
- Around line 806-822: Validate the wasm signature's parameter/output counts
against the instruction's expected shape before using it in wasmJsCall,
beginWasmFunction, and endWasmFunction: for wasmJsCall check that
signature.outputTypes.count matches instr.numOutputs (or is zero when instr has
no outputs) before calling setType(of: instr.output, ...) and before using
instr.input(1)'s signature in addWasmFunction; for beginWasmFunction ensure
signature.parameter count matches instr.numInputs (and output count matches
instr.numInnerOutputs/numOutputs as appropriate) before calling
wasmTypeBeginBlock; for endWasmFunction only call setType(of: instr.output, ...)
and addWasmFunction when the signature counts match, otherwise fall back to a
safe default (e.g. use Signature.forUnknownFunction/skip setting types) and/or
log/reject the inconsistent signature so mutation/minimization swaps don't
corrupt op arity; reference wasmFunctionSignatureDefSignature, instr.input(0),
instr.output, wasmTypeBeginBlock, setType,
dynamicObjectGroupManager.addWasmFunction,
ProgramBuilder.convertWasmSignatureToJsSignature, and defUseAnalyzer.definition
when making these checks and fallbacks.

In `@Sources/Fuzzilli/Profiles/BunProfile.swift`:
- Around line 2020-2026: The signature for Bun.readableStreamToFormData
currently models only a single-argument path; update its type to accept the
optional boundary parameter which can be string | Uint8Array | ArrayBufferView
by replacing the second-argument type with an optional jsAnything (e.g. change
the entry for "Bun.readableStreamToFormData" to a function taking [.jsAnything,
.opt(.jsAnything)] => .jsPromise or use .opt(.jsAnything) instead of
.opt(.string)) so the profile reflects the runtime's accepted types.

In `@Sources/Fuzzilli/Protobuf/operations.pb.swift`:
- Around line 4001-4018: The new Int32 fields parameterCount (in
Fuzzilli_Protobuf_BeginWasmFunction) and outputCount (in
Fuzzilli_Protobuf_EndWasmFunction) are using field number 1 which collides with
the original repeated message fields (parameterTypes/outputTypes) and breaks
wire compatibility; update the proto and generated Swift handling to use a fresh
field number (e.g., field 2) instead: change the field numbers in
operations.proto for these count fields to 2, then regenerate the Swift protobuf
sources (or, if editing generated code directly, change the tag handling for
parameterCount and outputCount to the field-2 tag and update encode/decode paths
and default values accordingly) so older serialized data remains compatible.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9b1d7e48-a066-4ec5-98e7-e1864aca627b

📥 Commits

Reviewing files that changed from the base of the PR and between 56cb233 and e62eb32.

📒 Files selected for processing (39)
  • .github/workflows/swift.yml
  • Sources/Fuzzilli/Base/ProgramBuilder.swift
  • Sources/Fuzzilli/CodeGen/CodeGeneratorWeights.swift
  • Sources/Fuzzilli/CodeGen/CodeGenerators.swift
  • Sources/Fuzzilli/CodeGen/WasmCodeGenerators.swift
  • Sources/Fuzzilli/Compiler/Compiler.swift
  • Sources/Fuzzilli/Compiler/Parser/parser.js
  • Sources/Fuzzilli/Environment/JavaScriptEnvironment.swift
  • Sources/Fuzzilli/FuzzIL/Instruction.swift
  • Sources/Fuzzilli/FuzzIL/JSTyper.swift
  • Sources/Fuzzilli/FuzzIL/JsOperations.swift
  • Sources/Fuzzilli/FuzzIL/Opcodes.swift
  • Sources/Fuzzilli/FuzzIL/Semantics.swift
  • Sources/Fuzzilli/FuzzIL/WasmOperations.swift
  • Sources/Fuzzilli/Fuzzer.swift
  • Sources/Fuzzilli/Lifting/FuzzILLifter.swift
  • Sources/Fuzzilli/Lifting/JavaScriptExploreLifting.swift
  • Sources/Fuzzilli/Lifting/JavaScriptLifter.swift
  • Sources/Fuzzilli/Lifting/JavaScriptProbeLifting.swift
  • Sources/Fuzzilli/Lifting/JavaScriptRuntimeAssistedMutatorLifting.swift
  • Sources/Fuzzilli/Lifting/WasmLifter.swift
  • Sources/Fuzzilli/Minimization/BlockReducer.swift
  • Sources/Fuzzilli/Minimization/InliningReducer.swift
  • Sources/Fuzzilli/Mutators/OperationMutator.swift
  • Sources/Fuzzilli/Mutators/ProbingMutator.swift
  • Sources/Fuzzilli/Mutators/RuntimeAssistedMutator.swift
  • Sources/Fuzzilli/Profiles/BunProfile.swift
  • Sources/Fuzzilli/Protobuf/ast.pb.swift
  • Sources/Fuzzilli/Protobuf/ast.proto
  • Sources/Fuzzilli/Protobuf/operations.pb.swift
  • Sources/Fuzzilli/Protobuf/operations.proto
  • Sources/Fuzzilli/Protobuf/program.pb.swift
  • Sources/Fuzzilli/Protobuf/program.proto
  • Tests/FuzzilliTests/CompilerTests/computed_and_indexed_properties.js
  • Tests/FuzzilliTests/CrashingInstrumentationMutator.swift
  • Tests/FuzzilliTests/LifterTest.swift
  • Tests/FuzzilliTests/MinimizerTest.swift
  • Tests/FuzzilliTests/ProgramBuilderTest.swift
  • Tests/FuzzilliTests/RuntimeAssistedMutatorTests.swift
💤 Files with no reviewable changes (1)
  • Sources/Fuzzilli/Mutators/ProbingMutator.swift

Comment on lines +3504 to +3509
public init(forBuilder b: ProgramBuilder, signatureDef: Variable) {
assert(b.type(of: signatureDef).Is(.wasmTypeDef()))
self.b = b
self.signature = signature
self.signature = b.type(of: signatureDef).wasmFunctionSignatureDefSignature
self.jsSignature = convertWasmSignatureToJsSignature(signature)
self.signatureDef = signatureDef
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Validate signatureDef as a function signature, not just any wasm type def.

Line 3505 only checks .wasmTypeDef(), while Line 3507 and Line 4536 immediately assume a function-signature definition. The new public overload can therefore accept an array/struct type definition and only fail later in the builder path. Tighten this invariant at the API boundary, and keep the BeginWasmFunction input typed as well.

Also applies to: 4530-4539, 5069-5070

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/Fuzzilli/Base/ProgramBuilder.swift` around lines 3504 - 3509, The
initializer public init(forBuilder b: ProgramBuilder, signatureDef: Variable)
currently only asserts .wasmTypeDef(); tighten the API boundary by asserting (or
preconditioning) that signatureDef is specifically a wasm function-signature
definition (e.g., check b.type(of: signatureDef).Is(.wasmFunctionSignatureDef())
or that b.type(of: signatureDef).wasmFunctionSignatureDefSignature is non-nil)
so the later use of wasmFunctionSignatureDefSignature is safe; apply the same
stronger validation to the other overloads/constructors and callers mentioned
(the BeginWasmFunction overloads and the code paths around the other
occurrences) and, where possible, keep BeginWasmFunction parameter types or
signatures constrained to function-signature defs instead of the more generic
wasm type def to prevent accepting arrays/structs.

Comment on lines +4099 to +4105
// Define tag signatures before the try block so they don't interfere with the try/catch
// bodies and their scoping.
// TODO(mliedtke): We should reuse the signature of the tag once tags use a wasm-gc
// signature.
let tagSignatures = catchClauses.map {
b.wasmDefineAdHocSignatureType(signature: b.type(of: $0.tag).wasmTagType!.parameters => [])
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Don't force-unwrap wasmTagType before the existing validation.

The new tagSignatures prepass evaluates b.type(of: clause.tag).wasmTagType! before the later reportErrorIf inside the catch loop. A non-tag input now traps here instead of producing the intended diagnostic.

Suggested fix for both helpers
-            let tagSignatures = catchClauses.map {
-                b.wasmDefineAdHocSignatureType(signature: b.type(of: $0.tag).wasmTagType!.parameters => [])
-            }
+            let tagSignatures = catchClauses.map { clause in
+                let tagType = b.type(of: clause.tag)
+                b.reportErrorIf(!tagType.isWasmTagType,
+                    "Expected tag misses the WasmTagType extension for variable \(clause.tag), typed \(tagType).")
+                return b.wasmDefineAdHocSignatureType(signature: tagType.wasmTagType!.parameters => [])
+            }

Also applies to: 4142-4148

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/Fuzzilli/Base/ProgramBuilder.swift` around lines 4099 - 4105, The
prepass that builds tagSignatures force-unwraps b.type(of:
clause.tag).wasmTagType (in the tagSignatures construction that calls
b.wasmDefineAdHocSignatureType) before the per-clause validation (reportErrorIf)
runs, which causes a trap on non-tag inputs; change the prepass to avoid
force-unwrapping — instead check for a valid wasmTagType (or skip/produce a
placeholder) and only call b.wasmDefineAdHocSignatureType when wasmTagType is
present, leaving the existing reportErrorIf checks inside the catchClauses loop
to emit diagnostics for invalid tags (apply the same pattern to the other
similar helper at the other site).

Comment on lines 1260 to +1265
let parameters = b.randomParameters()
b.emit(
BeginClassPrivateInstanceMethod(
BeginClassPrivateMethod(
methodName: methodName,
parameters: parameters.parameters))
parameters: parameters.parameters,
isStatic: false))
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Seed private-method parameter types before opening the subroutine.

These two generators pick randomized parameters but still skip setParameterTypesForNextSubroutine, unlike the public class-method generators above. That means private-method bodies lose the same typed parameter information the other method bodies get.

♻️ Proposed fix
                 let methodName = b.generateString(b.randomCustomPrivateMethodName,
                     notIn: b.currentClassDefinition.privateFields)
                 let parameters = b.randomParameters()
+                b.setParameterTypesForNextSubroutine(parameters.parameterTypes)
                 b.emit(
                     BeginClassPrivateMethod(
                         methodName: methodName,
                         parameters: parameters.parameters,
                         isStatic: false))
@@
                 let methodName = b.generateString(b.randomCustomPrivateMethodName,
                     notIn: b.currentClassDefinition.privateFields)
                 let parameters = b.randomParameters()
+                b.setParameterTypesForNextSubroutine(parameters.parameterTypes)
                 b.emit(
                     BeginClassPrivateMethod(
                         methodName: methodName,
                         parameters: parameters.parameters,
                         isStatic: true))

Also applies to: 1298-1303

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/Fuzzilli/CodeGen/CodeGenerators.swift` around lines 1260 - 1265, The
private-class-method generators currently call b.randomParameters() and
immediately emit BeginClassPrivateMethod (symbols: b.randomParameters,
BeginClassPrivateMethod) without seeding parameter types; before emitting
BeginClassPrivateMethod call setParameterTypesForNextSubroutine on the builder
with the parameter type information returned by b.randomParameters() so the
private-method body receives the same typed-parameter context as public
class-method generators—apply the same change to both occurrences (around the
blocks that use b.randomParameters and BeginClassPrivateMethod, including the
second occurrence near the other similar block).

Comment on lines +327 to 330
// This generator is mostly just there, so that the WasmThrowRefGenerator
// can create an exnref on demand (if a wasm tag is present).
"WasmCreateExnRefGenerator": 1,
"WasmThrowRefGenerator": 6,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Add an explicit scheduling test for WasmCreateExnRefGenerator.

A new weighted generator is introduced here, but there’s no direct scheduling assertion for it in the GC scheduling test matrix yet. Adding one would make regressions easier to catch.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/Fuzzilli/CodeGen/CodeGeneratorWeights.swift` around lines 327 - 330,
The test matrix for GC generator scheduling is missing an explicit case for the
new weighted generator WasmCreateExnRefGenerator; add a scheduling assertion
that verifies WasmCreateExnRefGenerator is scheduled (with expected
weight/priority) similar to the existing WasmThrowRefGenerator entry so
regressions are caught—locate the GC scheduling tests that reference
"WasmThrowRefGenerator" and add a corresponding assertion or test row for
"WasmCreateExnRefGenerator" that checks it appears in the schedule and honors
its weight.

Comment on lines +616 to 679
case .classAddProperty(let op):
$0.classAddProperty = Fuzzilli_Protobuf_ClassAddProperty.with {
$0.propertyName = op.propertyName
$0.hasValue_p = op.hasValue
$0.isStatic = op.isStatic
}
case .classAddInstanceElement(let op):
$0.classAddInstanceElement = Fuzzilli_Protobuf_ClassAddInstanceElement.with {
case .classAddElement(let op):
$0.classAddElement = Fuzzilli_Protobuf_ClassAddElement.with {
$0.index = op.index
$0.hasValue_p = op.hasValue
$0.isStatic = op.isStatic
}
case .classAddInstanceComputedProperty(let op):
$0.classAddInstanceComputedProperty = Fuzzilli_Protobuf_ClassAddInstanceComputedProperty.with { $0.hasValue_p = op.hasValue }
case .beginClassInstanceMethod(let op):
$0.beginClassInstanceMethod = Fuzzilli_Protobuf_BeginClassInstanceMethod.with {
$0.methodName = op.methodName
$0.parameters = convertParameters(op.parameters)
case .classAddComputedProperty(let op):
$0.classAddComputedProperty = Fuzzilli_Protobuf_ClassAddComputedProperty.with {
$0.hasValue_p = op.hasValue
$0.isStatic = op.isStatic
}
case .endClassInstanceMethod:
$0.endClassInstanceMethod = Fuzzilli_Protobuf_EndClassInstanceMethod()
case .beginClassInstanceComputedMethod(let op):
$0.beginClassInstanceComputedMethod = Fuzzilli_Protobuf_BeginClassInstanceComputedMethod.with {
case .endClassMethod:
$0.endClassMethod = Fuzzilli_Protobuf_EndClassMethod()
case .beginClassComputedMethod(let op):
$0.beginClassComputedMethod = Fuzzilli_Protobuf_BeginClassComputedMethod.with {
$0.parameters = convertParameters(op.parameters)
$0.isStatic = op.isStatic
}
case .endClassInstanceComputedMethod:
$0.endClassInstanceComputedMethod = Fuzzilli_Protobuf_EndClassInstanceComputedMethod()
case .beginClassInstanceGetter(let op):
$0.beginClassInstanceGetter = Fuzzilli_Protobuf_BeginClassInstanceGetter.with { $0.propertyName = op.propertyName }
case .endClassInstanceGetter:
$0.endClassInstanceGetter = Fuzzilli_Protobuf_EndClassInstanceGetter()
case .beginClassInstanceSetter(let op):
$0.beginClassInstanceSetter = Fuzzilli_Protobuf_BeginClassInstanceSetter.with { $0.propertyName = op.propertyName }
case .endClassInstanceSetter:
$0.endClassInstanceSetter = Fuzzilli_Protobuf_EndClassInstanceSetter()
case .classAddStaticProperty(let op):
$0.classAddStaticProperty = Fuzzilli_Protobuf_ClassAddStaticProperty.with {
case .endClassComputedMethod:
$0.endClassComputedMethod = Fuzzilli_Protobuf_EndClassComputedMethod()
case .beginClassGetter(let op):
$0.beginClassGetter = Fuzzilli_Protobuf_BeginClassGetter.with {
$0.propertyName = op.propertyName
$0.hasValue_p = op.hasValue
$0.isStatic = op.isStatic
}
case .classAddStaticElement(let op):
$0.classAddStaticElement = Fuzzilli_Protobuf_ClassAddStaticElement.with {
$0.index = op.index
$0.hasValue_p = op.hasValue
}
case .classAddStaticComputedProperty(let op):
$0.classAddStaticComputedProperty = Fuzzilli_Protobuf_ClassAddStaticComputedProperty.with { $0.hasValue_p = op.hasValue }
case .beginClassStaticInitializer:
$0.beginClassStaticInitializer = Fuzzilli_Protobuf_BeginClassStaticInitializer()
case .endClassStaticInitializer:
$0.endClassStaticInitializer = Fuzzilli_Protobuf_EndClassStaticInitializer()
case .beginClassStaticMethod(let op):
$0.beginClassStaticMethod = Fuzzilli_Protobuf_BeginClassStaticMethod.with {
case .beginClassPrivateMethod(let op):
$0.beginClassPrivateMethod = Fuzzilli_Protobuf_BeginClassPrivateMethod.with {
$0.methodName = op.methodName
$0.parameters = convertParameters(op.parameters)
$0.isStatic = op.isStatic
}
case .endClassStaticMethod:
$0.endClassStaticMethod = Fuzzilli_Protobuf_EndClassStaticMethod()
case .beginClassStaticComputedMethod(let op):
$0.beginClassStaticComputedMethod = Fuzzilli_Protobuf_BeginClassStaticComputedMethod.with {
case .endClassPrivateMethod:
$0.endClassPrivateMethod = Fuzzilli_Protobuf_EndClassPrivateMethod()
case .beginClassMethod(let op):
$0.beginClassMethod = Fuzzilli_Protobuf_BeginClassMethod.with {
$0.methodName = op.methodName
$0.parameters = convertParameters(op.parameters)
$0.isStatic = op.isStatic
}
case .endClassStaticComputedMethod:
$0.endClassStaticComputedMethod = Fuzzilli_Protobuf_EndClassStaticComputedMethod()
case .beginClassStaticGetter(let op):
$0.beginClassStaticGetter = Fuzzilli_Protobuf_BeginClassStaticGetter.with { $0.propertyName = op.propertyName }
case .endClassStaticGetter:
$0.endClassStaticGetter = Fuzzilli_Protobuf_EndClassStaticGetter()
case .beginClassStaticSetter(let op):
$0.beginClassStaticSetter = Fuzzilli_Protobuf_BeginClassStaticSetter.with { $0.propertyName = op.propertyName }
case .endClassStaticSetter:
$0.endClassStaticSetter = Fuzzilli_Protobuf_EndClassStaticSetter()
case .classAddPrivateInstanceProperty(let op):
$0.classAddPrivateInstanceProperty = Fuzzilli_Protobuf_ClassAddPrivateInstanceProperty.with {
case .endClassGetter:
$0.endClassGetter = Fuzzilli_Protobuf_EndClassGetter()
case .beginClassSetter(let op):
$0.beginClassSetter = Fuzzilli_Protobuf_BeginClassSetter.with {
$0.propertyName = op.propertyName
$0.hasValue_p = op.hasValue
}
case .beginClassPrivateInstanceMethod(let op):
$0.beginClassPrivateInstanceMethod = Fuzzilli_Protobuf_BeginClassPrivateInstanceMethod.with {
$0.methodName = op.methodName
$0.parameters = convertParameters(op.parameters)
$0.isStatic = op.isStatic
}
case .endClassPrivateInstanceMethod:
$0.endClassPrivateInstanceMethod = Fuzzilli_Protobuf_EndClassPrivateInstanceMethod()
case .classAddPrivateStaticProperty(let op):
$0.classAddPrivateStaticProperty = Fuzzilli_Protobuf_ClassAddPrivateStaticProperty.with {
case .endClassSetter:
$0.endClassSetter = Fuzzilli_Protobuf_EndClassSetter()
case .beginClassStaticInitializer:
$0.beginClassStaticInitializer = Fuzzilli_Protobuf_BeginClassStaticInitializer()
case .endClassStaticInitializer:
$0.endClassStaticInitializer = Fuzzilli_Protobuf_EndClassStaticInitializer()
case .classAddPrivateProperty(let op):
$0.classAddPrivateProperty = Fuzzilli_Protobuf_ClassAddPrivateProperty.with {
$0.propertyName = op.propertyName
$0.hasValue_p = op.hasValue
$0.isStatic = op.isStatic
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Please make the serialized-format change explicit.

These encoder/decoder updates change the persisted shape of class-member and Wasm instructions. If stored corpora or serialized programs are expected to survive upgrade, this needs a format/version bump or an explicit reset/migration note in the upgrade path.

Also applies to: 1261-1264, 1331-1336, 1866-1897, 2329-2332, 2365-2368

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/Fuzzilli/FuzzIL/Instruction.swift` around lines 616 - 679, The change
alters the on-disk protobuf shape for several class-member (e.g., the
Instruction.swift cases classAddProperty, classAddElement,
classAddComputedProperty, classAddPrivateProperty, beginClassMethod,
beginClassComputedMethod, beginClassGetter/Setter, etc.) and Wasm instruction
encodings, so update the persisted-format handling by bumping the repository's
serialized format version (the serialized-format/version constant used by the
Instruction/protobuf serializer) or implement explicit migration logic in the
encoder/decoder path (where instructions are converted to/from
Fuzzilli_Protobuf_* messages) to accept both old and new shapes, and add a short
upgrade note describing the incompatibility; apply the same treatment to the
other changed ranges you mentioned (1261–1264, 1331–1336, 1866–1897, 2329–2332,
2365–2368).

Comment on lines +139 to +141
// If we reach here, the process()'d program did not crash, so we need to report the instrumented program.
logger.warning("Mutated program did not crash, reporting original crash of the instrumented program")
fuzzer.processCrash(instrumentedProgram, withSignal: signal, withStderr: oldStderr, withStdout: stdout, origin: .local, withExectime: execution.execTime)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Missing return after reporting instrumented program crash.

After reporting the crash at line 141, the code falls through to line 150, which calls process() again and may return a "successful" mutation. This results in inconsistent behavior: a crash is reported AND a mutated program is returned.

🐛 Proposed fix: Add return statement
             // If we reach here, the process()'d program did not crash, so we need to report the instrumented program.
             logger.warning("Mutated program did not crash, reporting original crash of the instrumented program")
             fuzzer.processCrash(instrumentedProgram, withSignal: signal, withStderr: oldStderr, withStdout: stdout, origin: .local, withExectime: execution.execTime)
+            return failure(.instrumentedProgramCrashed)
         case .succeeded:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// If we reach here, the process()'d program did not crash, so we need to report the instrumented program.
logger.warning("Mutated program did not crash, reporting original crash of the instrumented program")
fuzzer.processCrash(instrumentedProgram, withSignal: signal, withStderr: oldStderr, withStdout: stdout, origin: .local, withExectime: execution.execTime)
// If we reach here, the process()'d program did not crash, so we need to report the instrumented program.
logger.warning("Mutated program did not crash, reporting original crash of the instrumented program")
fuzzer.processCrash(instrumentedProgram, withSignal: signal, withStderr: oldStderr, withStdout: stdout, origin: .local, withExectime: execution.execTime)
return failure(.instrumentedProgramCrashed)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/Fuzzilli/Mutators/RuntimeAssistedMutator.swift` around lines 139 -
141, After calling logger.warning(...) and
fuzzer.processCrash(instrumentedProgram, withSignal: signal, withStderr:
oldStderr, withStdout: stdout, origin: .local, withExectime: execution.execTime)
you must return immediately to avoid falling through and re-processing the
program; add a return statement right after the fuzzer.processCrash(...) call in
the same scope (the function that later calls process()) so the function exits
once the instrumented crash has been reported.

Comment on lines +132 to +136
// BunJSONL - JSONL parser
static let bunJSONL = ILType.object(
ofGroup: "BunJSONL",
withProperties: [],
withMethods: ["parse", "stringify"]
withMethods: ["parse", "parseChunk"]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n Sources/Fuzzilli/Profiles/BunProfile.swift | sed -n '130,140p'

Repository: oven-sh/fuzzilli

Length of output: 416


🏁 Script executed:

cat -n Sources/Fuzzilli/Profiles/BunProfile.swift | sed -n '760,780p'

Repository: oven-sh/fuzzilli

Length of output: 657


🌐 Web query:

Bun JSONL API parse parseChunk official documentation

💡 Result:

Bun provides official support for parsing JSONL (newline-delimited JSON) via the Bun.JSONL API, including parse for complete inputs and parseChunk for streaming scenarios. ## Bun.JSONL.parse(input) Parses a complete JSONL string, ArrayBufferLike, TypedArray, or DataView into an array of JavaScript values. Throws SyntaxError if no values parse successfully. Example: const results = Bun.JSONL.parse('{"name":"Alice"}\n{"name":"Bob"}\n'); // [{ name: "Alice" }, { name: "Bob" }] ## Bun.JSONL.parseChunk(input, start?, end?) For streaming, parses as many complete values as possible from the chunk. Returns ParseChunkResult { values: any[], read: number, done: boolean, error: SyntaxError | null }. Does not throw; errors are in the result. 'read' indicates consumed bytes/characters for resuming. Example: const chunk = '{"id":1}\n{"id":2}\n{"id":3'; const result = Bun.JSONL.parseChunk(chunk); console.log(result.values); // [{ id: 1 }, { id: 2 }] console.log(result.read); // 17 console.log(result.done); // false console.log(result.error); // null Streaming example: let buffer = ""; async function processStream(stream) { for await (const chunk of stream) { buffer += chunk; const result = Bun.JSONL.parseChunk(buffer); if (result.error) throw result.error; for (const value of result.values) handle(value); buffer = buffer.slice(result.read); } // Final parse remaining buffer } Official docs: https://bun.sh/docs/runtime/jsonl and https://bun.sh/reference/bun/JSONL. Parser in C++ using JavaScriptCore for speed, supports ASCII typed arrays without copying.

Citations:


Model Bun.JSONL with its real streaming contract.

Lines 770 and 771 currently reduce both APIs to string -> jsAnything, but Bun's official API accepts string | TypedArray | DataView | ArrayBufferLike; parse() returns an array of values, and parseChunk() also takes optional start and end offsets and returns a structured { values, read, done, error } result. As written, the profile misses zero-copy/partial-buffer paths and cannot exercise the incremental parser surface or result structure validation.

Suggested shape update
 public let bunJSONLGroup = ObjectGroup(
     name: "BunJSONL",
     instanceType: .bunJSONL,
     properties: [:],
     methods: [
-        "parse": [.string] => .jsAnything,
-        "parseChunk": [.string] => .jsAnything,
+        "parse": [.jsAnything] => .jsArray,
+        "parseChunk": [.jsAnything, .opt(.integer), .opt(.integer)] => .object(),
     ]
 )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/Fuzzilli/Profiles/BunProfile.swift` around lines 132 - 136, The
BunJSONL ILType currently models both methods as string->jsAnything; update the
bunJSONL ILType (symbol bunJSONL) so parse accepts a union input type (string |
TypedArray | DataView | ArrayBufferLike) and returns an array of JS values, and
parseChunk accepts the same union input plus optional numeric start and end
parameters and returns a structured object with properties { values: Array,
read: Number, done: Boolean, error: Any|null } so the profile can exercise
zero-copy/partial-buffer paths and validate the incremental parser result shape
for methods "parse" and "parseChunk".

Comment on lines +246 to +250
// BunBuildArtifact - result of Bun.build()
static let bunBuildArtifact = ILType.object(
ofGroup: "BunBuildArtifact",
withProperties: ["path", "size", "hash", "sourcemap", "loader", "type", "kind"],
withMethods: ["text", "json", "arrayBuffer", "slice", "stream"]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "BunProfile.swift" -type f

Repository: oven-sh/fuzzilli

Length of output: 104


🏁 Script executed:

cat -n ./Sources/Fuzzilli/Profiles/BunProfile.swift | sed -n '240,260p'

Repository: oven-sh/fuzzilli

Length of output: 1793


🏁 Script executed:

cat -n ./Sources/Fuzzilli/Profiles/BunProfile.swift | sed -n '1100,1125p'

Repository: oven-sh/fuzzilli

Length of output: 968


🏁 Script executed:

grep -n "bunBlob" ./Sources/Fuzzilli/Profiles/BunProfile.swift | head -20

Repository: oven-sh/fuzzilli

Length of output: 464


🏁 Script executed:

cat -n ./Sources/Fuzzilli/Profiles/BunProfile.swift | sed -n '485,495p'

Repository: oven-sh/fuzzilli

Length of output: 552


🏁 Script executed:

cat -n ./Sources/Fuzzilli/Profiles/BunProfile.swift | sed -n '732,750p'

Repository: oven-sh/fuzzilli

Length of output: 695


🌐 Web query:

Bun.build() BuildArtifact documentation API methods bytes

💡 Result:

The Bun.BuildArtifact interface represents files generated by Bun.build. It is returned in the BuildOutput.outputs array from Bun.build(config). Key properties: - hash: null | string - kind: 'entry-point' | 'chunk' | 'asset' | 'sourcemap' | 'bytecode' - loader: Loader - path: string - readonly size: number - sourcemap: null | BuildArtifact - readonly type: string API methods (Blob-like): - arrayBuffer: Promise - bytes: Promise - Returns the contents as Uint8Array (equivalent to new Uint8Array(await arrayBuffer)) - formData: Promise - json: Promise - Decodes UTF-8 then parses JSON - slice(start?: number, end?: number, contentType?: string): Blob - stream: ReadableStream - text: Promise Example usage: const result = await Bun.build({ entrypoints: ['./src/index.ts'], outdir: './dist' }); if (result.success) { for (const artifact of result.outputs) { console.log(${artifact.path}: ${artifact.size} bytes (${artifact.kind})); const bytes = await artifact.bytes; // Access bytes } } The bytes method provides direct access to the artifact's binary contents as a Uint8Array, useful for in-memory processing or writing to custom locations.

Citations:


Add missing bytes() method; don't remove json().

Bun documents BuildArtifact as supporting both json() and bytes() methods. The current implementation correctly includes json() but omits bytes(), preventing access to the documented Promise<Uint8Array> API. Additionally, the sourcemap property (line 1109) is typed as .jsAnything but should be nullable and represent a BuildArtifact reference per documentation.

Suggested method fix
     methods: [
         "text":        [] => .jsPromise,
         "json":        [] => .jsPromise,
+        "bytes":       [] => .jsPromise,
         "arrayBuffer": [] => .jsPromise,
         "slice":       [.opt(.integer), .opt(.integer)] => .bunBlob,
         "stream":      [] => .object(),
     ]

Also applies to: 1102-1121

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/Fuzzilli/Profiles/BunProfile.swift` around lines 246 - 250, The
BunBuildArtifact IL type (bunBuildArtifact) is missing the documented bytes()
method and the sourcemap property is incorrectly typed; update the ILType.object
for bunBuildArtifact to add "bytes" to the withMethods array while keeping
"json", and change the "sourcemap" property to be nullable and reference a
BuildArtifact (i.e., make its type an optional BuildArtifact/ILType.object
reference rather than .jsAnything) so it correctly models Promise<Uint8Array>
for bytes() and the sourcemap relationship.

Comment on lines +1479 to +1486
public var key: Compiler_Protobuf_PropertyKey {
get {_key ?? Compiler_Protobuf_PropertyKey()}
set {_key = newValue}
}
/// Returns true if `key` has been explicitly set.
public var hasKey: Bool {self._key != nil}
/// Clears the value of `key`. Subsequent reads from it will return its default value.
public mutating func clearKey() {self._key = nil}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

print_message_from_file() {
  local file="$1"
  local msg="$2"
  awk -v msg="$msg" '
    $0 ~ "^[[:space:]]*message[[:space:]]+" msg "[[:space:]]*\\{" {printing=1}
    printing {
      print
      opens += gsub(/\{/, "{")
      closes += gsub(/\}/, "}")
      if (opens > 0 && opens == closes) exit
    }
  ' "$file"
}

proto_file="$(fd 'ast\.proto$' | head -n1 || true)"
if [ -z "${proto_file:-}" ]; then
  echo "ast.proto not found"
  exit 0
fi

echo "=== Current ast.proto definitions ==="
for msg in ObjectProperty ObjectMethod ObjectGetter ObjectSetter; do
  echo "-- $msg"
  print_message_from_file "$proto_file" "$msg"
  echo
done

echo "=== Previous ast.proto revision (if available) ==="
prev_commit="$(git log --format='%H' --skip=1 -n 1 -- "$proto_file" || true)"
if [ -n "${prev_commit:-}" ]; then
  tmp="$(mktemp)"
  git show "${prev_commit}:${proto_file}" > "$tmp" || true
  for msg in ObjectProperty ObjectMethod ObjectGetter ObjectSetter; do
    echo "-- $msg"
    print_message_from_file "$tmp" "$msg"
    echo
  done
  rm -f "$tmp"
else
  echo "No previous ast.proto revision found in local git history."
fi

echo "=== AST protobuf serialization/deserialization sites ==="
rg -n -C2 'Compiler_Protobuf_AST|Compiler_Protobuf_Object(Property|Method|Getter|Setter)|serialized(Data|Bytes)|init\(serialized(Data|Bytes):|merge\(serialized' .

Repository: oven-sh/fuzzilli

Length of output: 28059


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find the proto file
proto_file="$(fd 'ast\.proto$' | head -n1 || true)"
if [ -z "${proto_file:-}" ]; then
  echo "ast.proto not found"
  exit 0
fi

echo "=== Full git log for ast.proto ==="
git log --oneline -- "$proto_file" | head -20

echo -e "\n=== Checking if there are changes in the current staged/working state ==="
git diff --stat -- "$proto_file" || echo "No diff"
git diff --cached --stat -- "$proto_file" || echo "No cached diff"

echo -e "\n=== Last commit that touched ast.proto ==="
last_commit="$(git log -n 1 --format='%H' -- "$proto_file")"
if [ -n "$last_commit" ]; then
  echo "Commit: $last_commit"
  echo "=== Diff in that commit ==="
  git show "$last_commit:$proto_file" | head -100
fi

Repository: oven-sh/fuzzilli

Length of output: 2528


🏁 Script executed:

#!/bin/bash
set -euo pipefail

proto_file="$(fd 'ast\.proto$' | head -n1 || true)"

# Check the parent commit
current_commit="e62eb32680afb62e87fb052a559237524b063f1c"
parent_commit="$(git rev-parse "${current_commit}^" 2>/dev/null || echo '')"

if [ -z "$parent_commit" ]; then
  echo "No parent commit found"
  exit 0
fi

echo "=== Comparing ObjectProperty in parent vs current ==="
echo "Parent commit: $parent_commit"
git show "${parent_commit}:${proto_file}" 2>/dev/null | grep -A 5 "^message ObjectProperty" || echo "ObjectProperty not found in parent"

echo -e "\n=== Comparing ObjectMethod in parent vs current ==="
git show "${parent_commit}:${proto_file}" 2>/dev/null | grep -A 8 "^message ObjectMethod" || echo "ObjectMethod not found in parent"

echo -e "\n=== Comparing ObjectGetter in parent vs current ==="
git show "${parent_commit}:${proto_file}" 2>/dev/null | grep -A 5 "^message ObjectGetter" || echo "ObjectGetter not found in parent"

echo -e "\n=== Comparing ObjectSetter in parent vs current ==="
git show "${parent_commit}:${proto_file}" 2>/dev/null | grep -A 6 "^message ObjectSetter" || echo "ObjectSetter not found in parent"

echo -e "\n=== Full diff for these messages between parent and current ==="
git diff "${parent_commit}..${current_commit}" -- "$proto_file" | grep -A 10 -B 2 "ObjectProperty\|ObjectMethod\|ObjectGetter\|ObjectSetter" | head -100

Repository: oven-sh/fuzzilli

Length of output: 651


🏁 Script executed:

#!/bin/bash
set -euo pipefail

proto_file="$(fd 'ast\.proto$' | head -n1 || true)"

echo "=== Full git log for ast.proto (if exists) ==="
git log --all --pretty=format:"%H %s" -- "$proto_file" 2>/dev/null | head -20

echo -e "\n=== Search for commit introducing PropertyKey ==="
git log -p --all -- "$proto_file" 2>/dev/null | grep -B 5 "message PropertyKey" | head -20

echo -e "\n=== Search for commit introducing ObjectProperty ==="
git log -p --all -- "$proto_file" 2>/dev/null | grep -B 5 "message ObjectProperty" | head -20

echo -e "\n=== Check current HEAD ==="
git log --oneline -n 5

echo -e "\n=== Check if there are uncommitted changes to generated swift file ==="
git status Sources/Fuzzilli/Protobuf/ast.pb.swift || true
</parameter>

Repository: oven-sh/fuzzilli

Length of output: 2169


🏁 Script executed:

#!/bin/bash
set -euo pipefail

proto_file="$(fd 'ast\.proto$' | head -n1 || true)"

echo "=== Commits that mention 'object' or 'property' in their subjects ==="
git log --all --pretty=format:"%H %s" -- "$proto_file" | grep -i "computed methods\|object literal" | head -10

echo -e "\n=== Check commit 91b69ee (computed methods in object literals) ==="
git show 91b69ee:Sources/Fuzzilli/Protobuf/ast.proto 2>/dev/null | grep -A 6 "message ObjectProperty" || echo "Not found"

echo -e "\n=== Check commit 2dc79c4 (class support) ==="
git show 2dc79c4:Sources/Fuzzilli/Protobuf/ast.proto 2>/dev/null | grep -A 6 "message ObjectProperty" || echo "Not found"

echo -e "\n=== Check a few commits back from HEAD ==="
for commit in adfa084a c88625162 2c145337; do
  echo "--- Commit $commit ---"
  git show ${commit}:Sources/Fuzzilli/Protobuf/ast.proto 2>/dev/null | grep -A 6 "message ObjectProperty" || echo "Message not found"
  echo
done

echo -e "\n=== Show the actual diff that introduced/modified ObjectProperty ==="
git log -p --all -- "$proto_file" 2>/dev/null | grep -B 10 -A 10 "message ObjectProperty" | head -80

Repository: oven-sh/fuzzilli

Length of output: 146


Ensure protobuf wire-format stability for persisted AST data.

The generated changes in Sources/Fuzzilli/Protobuf/ast.pb.swift for Compiler_Protobuf_ObjectProperty, Compiler_Protobuf_ObjectMethod, Compiler_Protobuf_ObjectGetter, and Compiler_Protobuf_ObjectSetter (lines 1479–1502, 1510–1537, 1545–1560, 1568–1593, and corresponding message implementations at 5305–5474) depend on field layout and tag assignments in the underlying proto schema. AST protobufs are actively serialized to disk and exchanged across processes throughout the codebase (Storage, ProtoUtils, Sync, tests). Any changes to field tags or message structure in Sources/Fuzzilli/Protobuf/ast.proto must maintain backward compatibility with persisted data, or a versioning and migration strategy must be introduced. If these messages changed from individual key fields to an embedded PropertyKey message, the wire format is incompatible with older payloads. Verify in ast.proto whether field tags and types are stable, or regenerate this file after implementing versioned schema changes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/Fuzzilli/Protobuf/ast.pb.swift` around lines 1479 - 1486, The
generated change replaces individual key fields with an embedded PropertyKey
message for
Compiler_Protobuf_ObjectProperty/ObjectMethod/ObjectGetter/ObjectSetter which
may break wire-format compatibility; inspect ast.proto and confirm the field
numbers and types for the affected messages and the PropertyKey message, then
either restore the original scalar/oneof fields and their original tag numbers
or add the new embedded field under a new tag while keeping the old tags (mark
them deprecated) so older binaries can still parse existing payloads, implement
a version/migration field if you intend to change semantics, and finally
regenerate Sources/Fuzzilli/Protobuf/ast.pb.swift (ensuring
Compiler_Protobuf_ObjectProperty, Compiler_Protobuf_ObjectMethod,
Compiler_Protobuf_ObjectGetter, Compiler_Protobuf_ObjectSetter and PropertyKey
definitions align with the stable tags).


override func instrument(_ program: Program, for fuzzer: Fuzzer) -> Program? {
let b = fuzzer.makeBuilder()
b.eval("fuzzilli('FUZZILLI_CRASH', 0)");
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Remove trailing semicolon.

Swift does not require semicolons at the end of statements.

♻️ Suggested fix
-        b.eval("fuzzilli('FUZZILLI_CRASH', 0)");
+        b.eval("fuzzilli('FUZZILLI_CRASH', 0)")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
b.eval("fuzzilli('FUZZILLI_CRASH', 0)");
b.eval("fuzzilli('FUZZILLI_CRASH', 0)")
🧰 Tools
🪛 SwiftLint (0.63.2)

[Warning] 33-33: Lines should not have trailing semicolons

(trailing_semicolon)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Tests/FuzzilliTests/CrashingInstrumentationMutator.swift` at line 33, The
statement calling b.eval contains a trailing semicolon which is unnecessary in
Swift; update the expression b.eval("fuzzilli('FUZZILLI_CRASH', 0)"); by
removing the final semicolon so it becomes b.eval("fuzzilli('FUZZILLI_CRASH',
0)") to match Swift style and avoid extraneous punctuation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants