Skip to content
Open
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
158 changes: 151 additions & 7 deletions Sources/Fuzzilli/Profiles/BunProfile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,11 @@ public extension ILType {
withMethods: ["parse"]
)

// BunJSONL - JSONL parser/stringifier
// BunJSONL - JSONL parser
static let bunJSONL = ILType.object(
ofGroup: "BunJSONL",
withProperties: [],
withMethods: ["parse", "stringify"]
withMethods: ["parse", "parseChunk"]
)

// BunFile - File handle returned by Bun.file()
Expand Down Expand Up @@ -227,6 +227,36 @@ public extension ILType {
withMethods: ["get", "set", "del", "exists", "keys", "ping", "quit", "subscribe", "publish"]
)

// BunListener - result of Bun.listen()
static let bunListener = ILType.object(
ofGroup: "BunListener",
withProperties: ["fd", "port", "unix", "hostname"],
withMethods: ["stop", "ref", "unref", "reload"]
)

// BunUDPSocket - result of Bun.udpSocket()
static let bunUDPSocket = ILType.object(
ofGroup: "BunUDPSocket",
withProperties: ["hostname", "port", "address", "closed"],
withMethods: ["send", "sendMany", "close", "reload", "ref", "unref",
"setBroadcast", "setTTL", "setMulticastTTL", "setMulticastLoopback",
"setMulticastInterface", "addMembership", "dropMembership"]
)

// 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"]
)

// BunCronJob - in-process cron handle returned by Bun.cron(schedule, handler)
static let bunCronJob = ILType.object(
ofGroup: "BunCronJob",
withProperties: ["cron"],
withMethods: ["stop", "ref", "unref"]
)

// Hash constructor instance types (each needs its own group to match builtin name)
static let bunMD4 = ILType.object(ofGroup: "Bun.MD4", withProperties: [], withMethods: ["update", "digest", "copy"])
static let bunMD5 = ILType.object(ofGroup: "Bun.MD5", withProperties: [], withMethods: ["update", "digest", "copy"])
Expand Down Expand Up @@ -744,8 +774,10 @@ public let bunJSONLGroup = ObjectGroup(
instanceType: .bunJSONL,
properties: [:],
methods: [
"parse": [.string] => .jsAnything,
"stringify": [.jsAnything] => .string,
// parse/parseChunk accept string | TypedArray | DataView | ArrayBuffer,
// with optional start/end offsets (bytes for typed arrays, chars for strings).
"parse": [.jsAnything, .opt(.integer), .opt(.integer)] => .jsArray,
"parseChunk": [.jsAnything, .opt(.integer), .opt(.integer)] => .object(),
]
)

Expand Down Expand Up @@ -1033,6 +1065,83 @@ public let bunSHA512_256Group = ObjectGroup(
]
)

public let bunListenerGroup = ObjectGroup(
name: "BunListener",
instanceType: .bunListener,
properties: [
"fd": .integer,
"port": .integer,
"unix": .string | .undefined,
"hostname": .string,
],
methods: [
"stop": [.opt(.boolean)] => .undefined,
"ref": [] => .undefined,
"unref": [] => .undefined,
"reload": [.object()] => .undefined,
]
)

public let bunUDPSocketGroup = ObjectGroup(
name: "BunUDPSocket",
instanceType: .bunUDPSocket,
properties: [
"hostname": .string,
"port": .integer,
"address": .object(),
"closed": .boolean,
],
methods: [
"send": [.jsAnything, .opt(.integer), .opt(.string)] => .boolean,
"sendMany": [.object()] => .integer,
"close": [] => .undefined,
"reload": [.object()] => .undefined,
"ref": [] => .undefined,
"unref": [] => .undefined,
"setBroadcast": [.boolean] => .undefined,
"setTTL": [.integer] => .undefined,
"setMulticastTTL": [.integer] => .undefined,
"setMulticastLoopback": [.boolean] => .undefined,
"setMulticastInterface": [.string] => .undefined,
"addMembership": [.string, .opt(.string)] => .undefined,
"dropMembership": [.string, .opt(.string)] => .undefined,
]
)

public let bunBuildArtifactGroup = ObjectGroup(
name: "BunBuildArtifact",
instanceType: .bunBuildArtifact,
properties: [
"path": .string,
"size": .integer,
"hash": .string | .undefined,
"sourcemap": .jsAnything,
"loader": .string,
"type": .string,
"kind": .string,
],
methods: [
"text": [] => .jsPromise,
"json": [] => .jsPromise,
"arrayBuffer": [] => .jsPromise,
"slice": [.opt(.integer), .opt(.integer)] => .bunBlob,
"stream": [] => .object(),
]
)

public let bunCronJobGroup = ObjectGroup(
name: "BunCronJob",
instanceType: .bunCronJob,
properties: [
"cron": .string,
],
methods: [
"stop": [] => .bunCronJob,
"ref": [] => .bunCronJob,
"unref": [] => .bunCronJob,
]
)

// MARK: - Bun Code Generators

// Generator that safely exercises Bun.spawn with harmless commands
Expand Down Expand Up @@ -1936,17 +2045,20 @@ let bunProfile = Profile(
"Bun.resolve" : .function([.string, .string] => .jsPromise),

// DNS
"Bun.dns" : .object(withMethods: ["lookup"]),
"Bun.dns" : .object(withMethods: ["lookup", "resolve", "prefetch", "getCacheStats", "reverse"]),

// Text formatting
"Bun.wrapAnsi" : .function([.string, .integer, .opt(.object())] => .string),
"Bun.sliceAnsi" : .function([.string, .opt(.integer), .opt(.integer), .opt(.jsAnything), .opt(.boolean)] => .string),

// Server / networking
"Bun.serve" : .function([.object()] => .bunServer),
"Bun.connect" : .function([.object()] => .jsPromise),
"Bun.listen" : .function([.object()] => .bunListener),
"Bun.fetch" : .function([.string, .opt(.object())] => .jsPromise),
"Bun.build" : .function([.object()] => .jsPromise),
"Bun.mmap" : .function([.string] => .object()),
"Bun.udpSocket" : .function([.object()] => .jsAnything),
"Bun.udpSocket" : .function([.object()] => .jsPromise),

// SQL
"Bun.sql" : .function([.opt(.string)] => .jsAnything),
Expand All @@ -1960,13 +2072,41 @@ let bunProfile = Profile(
"Bun.readableStreamToJSON" : .function([.jsAnything] => .jsPromise),
"Bun.readableStreamToBlob" : .function([.jsAnything] => .jsPromise),
"Bun.readableStreamToBytes" : .function([.jsAnything] => .jsPromise),
"Bun.readableStreamToFormData" : .function([.jsAnything] => .jsPromise),

// Markdown
"Bun.markdown" : .object(withMethods: ["html", "render", "ansi"]),
"Bun.markdown" : .object(withMethods: ["html", "render", "ansi", "react"]),

// CSRF
"Bun.CSRF" : .object(withMethods: ["generate", "verify"]),

// Cron
// Bun.cron has two overloads: (schedule, handler) => CronJob (in-process,
// synchronous) and (path, schedule, title) => Promise (OS-level). A Fuzzilli
// builtin maps to a single signature, so we model the in-process callback form:
// it has no host side effects (the OS-level form writes to crontab/launchd/Task
// Scheduler) and returns a CronJob the fuzzer can keep operating on.
"Bun.cron" : .function([.string, .function()] => .bunCronJob),
"Bun.cron.remove" : .function([.string] => .jsPromise),
"Bun.cron.parse" : .function([.string, .opt(.jsAnything)] => .jsAnything),
Comment thread
coderabbitai[bot] marked this conversation as resolved.

// Plugin
"Bun.plugin" : .function([.object()] => .jsAnything),

// Metadata properties
"Bun.argv" : .jsArray,
"Bun.env" : .object(),
"Bun.main" : .string,
"Bun.cwd" : .function([] => .string),

// Standard IO
"Bun.stdin" : .object(),
"Bun.stdout" : .object(),
"Bun.stderr" : .object(),

// GC
"Bun.gc" : .function([.opt(.boolean)] => .undefined),

// Classes
"Bun.Archive" : .constructor([.jsAnything, .opt(.object())] => .bunArchive),
"Bun.ArrayBufferSink" : .constructor([] => .bunArrayBufferSink),
Expand Down Expand Up @@ -2016,6 +2156,10 @@ let bunProfile = Profile(
bunFileSystemRouterGroup,
bunArchiveGroup,
bunServerGroup,
bunListenerGroup,
bunUDPSocketGroup,
bunBuildArtifactGroup,
bunCronJobGroup,
bunArrayBufferSinkGroup,
bunCookieGroup,
bunCookieMapGroup,
Expand Down