Skip to content

Commit 6f97546

Browse files
LiedtkeV8-internal LUCI CQ
authored andcommitted
[wasm] Add WebAssembly.Memory builtin
and check for consistency between registered ObjectGroups for wasm types in the JavaScriptEnvironment vs. the actual produced types by the high-level FuzzIL instructions. Bug: 440226707 Change-Id: Ib3d7604382c0b5c3d9fe2c4aea111777b35b5aa0 Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/8550562 Reviewed-by: Manos Koukoutos <manoskouk@google.com> Commit-Queue: Matthias Liedtke <mliedtke@google.com> Auto-Submit: Matthias Liedtke <mliedtke@google.com>
1 parent 057e5e4 commit 6f97546

File tree

4 files changed

+47
-15
lines changed

4 files changed

+47
-15
lines changed

Sources/Fuzzilli/Environment/JavaScriptEnvironment.swift

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,8 @@ public class JavaScriptEnvironment: ComponentBase {
364364
registerObjectGroup(.jsWebAssemblyInstanceConstructor)
365365
registerObjectGroup(.jsWebAssemblyInstance)
366366
registerObjectGroup(.jsWebAssemblyModule)
367+
registerObjectGroup(.jsWebAssemblyMemoryPrototype)
368+
registerObjectGroup(.jsWebAssemblyMemoryConstructor)
367369
registerObjectGroup(.jsWebAssembly)
368370
registerObjectGroup(.jsWasmGlobal)
369371
registerObjectGroup(.jsWasmMemory)
@@ -990,6 +992,11 @@ public extension ILType {
990992
ILType.constructor([.plain(.jsWebAssemblyModule), .plain(.object())] => .jsWebAssemblyInstance)
991993
+ .object(ofGroup: "WebAssemblyInstanceConstructor", withProperties: ["prototype"], withMethods: [])
992994

995+
// Similarly to Wasm globals, we do not type the results as being part of an object group as the
996+
// result type doesn't have a valid WasmTypeExtension.
997+
static let jsWebAssemblyMemoryConstructor = ILType.constructor([.plain(.object(withProperties: ["initial"]))] => .object(withProperties: ["buffer"], withMethods: ["grow", "toResizableBuffer", "toFixedLengthBuffer"]))
998+
+ .object(ofGroup: "WebAssemblyMemoryConstructor", withProperties: ["prototype"])
999+
9931000
// The JavaScript WebAssembly.Table object of the given variant, i.e. FuncRef or ExternRef
9941001
static let wasmTable = ILType.object(ofGroup: "WasmTable", withProperties: ["length"], withMethods: ["get", "grow", "set"])
9951002

@@ -1842,6 +1849,17 @@ public extension ObjectGroup {
18421849
methods: [:]
18431850
)
18441851

1852+
static let jsWebAssemblyMemoryPrototype = createPrototypeObjectGroup(jsWasmMemory)
1853+
1854+
static let jsWebAssemblyMemoryConstructor = ObjectGroup(
1855+
name: "WebAssemblyMemoryConstructor",
1856+
instanceType: .jsWebAssemblyMemoryConstructor,
1857+
properties: [
1858+
"prototype": jsWebAssemblyMemoryPrototype.instanceType,
1859+
],
1860+
methods: [:]
1861+
)
1862+
18451863
static let jsWebAssembly = ObjectGroup(
18461864
name: "WebAssembly",
18471865
instanceType: nil,
@@ -1851,6 +1869,7 @@ public extension ObjectGroup {
18511869
"Module": .jsWebAssemblyModuleConstructor,
18521870
"Global": .jsWebAssemblyGlobalConstructor,
18531871
"Instance": .jsWebAssemblyInstanceConstructor,
1872+
"Memory": .jsWebAssemblyMemoryConstructor,
18541873
],
18551874
overloads: [
18561875
"compile": wasmBufferTypes.map {
@@ -2038,7 +2057,8 @@ public extension ObjectGroup {
20382057
"second": .number,
20392058
"millisecond": .number,
20402059
"microsecond": .number,
2041-
"nanosecond": .number, ],
2060+
"nanosecond": .number,
2061+
],
20422062
methods: [
20432063
"add": [jsTemporalDurationLike] => .jsTemporalPlainTime,
20442064
"subtract": [jsTemporalDurationLike] => .jsTemporalPlainTime,

Sources/Fuzzilli/FuzzIL/JSTyper.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,7 @@ public struct JSTyper: Analyzer {
660660
case .wasmSimdExtractLane(let op):
661661
setType(of: instr.output, to: op.kind.laneType())
662662
case .wasmDefineGlobal(let op):
663-
let type = ILType.object(ofGroup: "WasmGlobal", withProperties: ["value"], withWasmType: WasmGlobalType(valueType: op.wasmGlobal.toType(), isMutable: op.isMutable))
663+
let type = ILType.object(ofGroup: "WasmGlobal", withProperties: ["value"], withMethods: ["valueOf"], withWasmType: WasmGlobalType(valueType: op.wasmGlobal.toType(), isMutable: op.isMutable))
664664
dynamicObjectGroupManager.addWasmGlobal(withType: type, forDefinition: instr, forVariable: instr.output)
665665
setType(of: instr.output, to: type)
666666
case .wasmDefineTable(let op):
@@ -1734,7 +1734,7 @@ public struct JSTyper: Analyzer {
17341734

17351735
// TODO: also add other macro instructions here.
17361736
case .createWasmGlobal(let op):
1737-
set(instr.output, .object(ofGroup: "WasmGlobal", withProperties: ["value"], withWasmType: WasmGlobalType(valueType: op.value.toType(), isMutable: op.isMutable)))
1737+
set(instr.output, .object(ofGroup: "WasmGlobal", withProperties: ["value"], withMethods: ["valueOf"], withWasmType: WasmGlobalType(valueType: op.value.toType(), isMutable: op.isMutable)))
17381738

17391739
case .createWasmMemory(let op):
17401740
set(instr.output, .wasmMemory(limits: op.memType.limits, isShared: op.memType.isShared, isMemory64: op.memType.isMemory64))

Tests/FuzzilliTests/JSTyperTests.swift

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,7 +1519,7 @@ class JSTyperTests: XCTestCase {
15191519
let b = fuzzer.makeBuilder()
15201520

15211521
let wasmGlobalf64: Variable = b.createWasmGlobal(value: .wasmf64(1337), isMutable: false)
1522-
XCTAssertEqual(b.type(of: wasmGlobalf64), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withWasmType: WasmGlobalType(valueType: ILType.wasmf64, isMutable: false)))
1522+
XCTAssertEqual(b.type(of: wasmGlobalf64), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withMethods: ["valueOf"], withWasmType: WasmGlobalType(valueType: ILType.wasmf64, isMutable: false)))
15231523

15241524
let maxPages: Int? = isShared ? 4 : nil
15251525
let memory = b.createWasmMemory(minPages: 1, maxPages: maxPages, isShared: isShared)
@@ -1612,10 +1612,10 @@ class JSTyperTests: XCTestCase {
16121612
XCTAssertEqual(reexportedFunction, [[] => .object(ofGroup: "_fuzz_Object0")])
16131613

16141614
let glob0 = b.getProperty("wg0", of: exports)
1615-
XCTAssertEqual(b.type(of: glob0), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withWasmType: WasmGlobalType(valueType: .wasmi64, isMutable: true)))
1615+
XCTAssertEqual(b.type(of: glob0), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withMethods: ["valueOf"], withWasmType: WasmGlobalType(valueType: .wasmi64, isMutable: true)))
16161616

16171617
let glob1 = b.getProperty("iwg0", of: exports)
1618-
XCTAssertEqual(b.type(of: glob1), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withWasmType: WasmGlobalType(valueType: .wasmf64, isMutable: false)))
1618+
XCTAssertEqual(b.type(of: glob1), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withMethods: ["valueOf"], withWasmType: WasmGlobalType(valueType: .wasmf64, isMutable: false)))
16191619

16201620
let mem0 = b.getProperty("wm0", of: exports)
16211621
let memType = ILType.wasmMemory(limits: Limits(min: 3, max: maxPages), isShared: isShared)
@@ -1727,11 +1727,23 @@ class JSTyperTests: XCTestCase {
17271727
// The high-level IL instruction produces properly typed wasm globals.
17281728
let realWasmGlobal = b.createWasmGlobal(value: .wasmi32(1), isMutable: true)
17291729
XCTAssert(b.type(of: realWasmGlobal).Is(.object(ofGroup: "WasmGlobal")))
1730+
XCTAssert(b.type(of: realWasmGlobal).Is(ObjectGroup.jsWasmGlobal.instanceType))
17301731
// The properly typed wasm globals can be used in conjunction with the
17311732
// WebAssembly.Global.prototype.valueOf() function.
17321733
let globalPrototype = b.getProperty("prototype", of: wasmGlobalConstructor)
17331734
let valueOf = b.getProperty("valueOf", of: globalPrototype)
17341735
XCTAssertEqual(b.type(of: valueOf), .unboundFunction([] => .jsAnything, receiver: .object(ofGroup: "WasmGlobal", withProperties: ["value"], withMethods: ["valueOf"])))
1736+
1737+
let wasmMemoryConstructor = b.getProperty("Memory", of: wasm)
1738+
let wasmMemory = b.construct(wasmMemoryConstructor) // In theory this needs arguments.
1739+
XCTAssertFalse(b.type(of: wasmMemory).Is(.object(ofGroup: "WasmMemory")))
1740+
let realWasmMemory = b.createWasmMemory(minPages: 1, maxPages: 1, isShared: false)
1741+
XCTAssert(b.type(of: realWasmMemory).Is(.object(ofGroup: "WasmMemory")))
1742+
XCTAssert(b.type(of: realWasmMemory).Is(ObjectGroup.jsWasmMemory.instanceType))
1743+
let memoryPrototype = b.getProperty("prototype", of: wasmMemoryConstructor)
1744+
let grow = b.getProperty("grow", of: memoryPrototype)
1745+
XCTAssert(b.type(of: grow).Is(.unboundFunction([.number] => .number, receiver: .object(ofGroup: "WasmMemory"))))
1746+
17351747
}
17361748

17371749
func testProducingGenerators() {

Tests/FuzzilliTests/WasmTests.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -188,10 +188,10 @@ class WasmFoundationTests: XCTestCase {
188188

189189
// This test tests whether re-exported imports and module defined globals are re-ordered from the typer.
190190
let wasmGlobali32: Variable = b.createWasmGlobal(value: .wasmi32(1337), isMutable: true)
191-
XCTAssertEqual(b.type(of: wasmGlobali32), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withWasmType: WasmGlobalType(valueType: ILType.wasmi32, isMutable: true)))
191+
XCTAssertEqual(b.type(of: wasmGlobali32), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withMethods: ["valueOf"], withWasmType: WasmGlobalType(valueType: ILType.wasmi32, isMutable: true)))
192192

193193
let wasmGlobalf32: Variable = b.createWasmGlobal(value: .wasmf32(42.0), isMutable: false)
194-
XCTAssertEqual(b.type(of: wasmGlobalf32), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withWasmType: WasmGlobalType(valueType: ILType.wasmf32, isMutable: false)))
194+
XCTAssertEqual(b.type(of: wasmGlobalf32), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withMethods: ["valueOf"], withWasmType: WasmGlobalType(valueType: ILType.wasmf32, isMutable: false)))
195195

196196
let module = b.buildWasmModule { wasmModule in
197197
// Imports are always before internal globals, this breaks the logic if we add a global and then import a global.
@@ -429,7 +429,7 @@ class WasmFoundationTests: XCTestCase {
429429
let b = fuzzer.makeBuilder()
430430

431431
let wasmGlobali64: Variable = b.createWasmGlobal(value: .wasmi64(1337), isMutable: true)
432-
XCTAssertEqual(b.type(of: wasmGlobali64), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withWasmType: WasmGlobalType(valueType: ILType.wasmi64, isMutable: true)))
432+
XCTAssertEqual(b.type(of: wasmGlobali64), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withMethods: ["valueOf"], withWasmType: WasmGlobalType(valueType: ILType.wasmi64, isMutable: true)))
433433

434434
let module = b.buildWasmModule { wasmModule in
435435
let global = wasmModule.addGlobal(wasmGlobal: .wasmi64(1339), isMutable: true)
@@ -499,7 +499,7 @@ class WasmFoundationTests: XCTestCase {
499499
let module = b.buildWasmModule { wasmModule in
500500
// Note that globals of exnref can only be defined in wasm, not in JS.
501501
let global = wasmModule.addGlobal(wasmGlobal: .exnref, isMutable: true)
502-
XCTAssertEqual(b.type(of: global), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withWasmType: WasmGlobalType(valueType: ILType.wasmExnRef, isMutable: true)))
502+
XCTAssertEqual(b.type(of: global), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withMethods: ["valueOf"], withWasmType: WasmGlobalType(valueType: ILType.wasmExnRef, isMutable: true)))
503503

504504
wasmModule.addWasmFunction(with: [] => [.wasmi32]) { function, label, args in
505505
let value = function.wasmLoadGlobal(globalVariable: global)
@@ -586,7 +586,7 @@ class WasmFoundationTests: XCTestCase {
586586

587587
let module = b.buildWasmModule { wasmModule in
588588
let global = wasmModule.addGlobal(wasmGlobal: .externref, isMutable: true)
589-
XCTAssertEqual(b.type(of: global), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withWasmType: WasmGlobalType(valueType: ILType.wasmExternRef, isMutable: true)))
589+
XCTAssertEqual(b.type(of: global), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withMethods: ["valueOf"], withWasmType: WasmGlobalType(valueType: ILType.wasmExternRef, isMutable: true)))
590590

591591
wasmModule.addWasmFunction(with: [] => [.wasmExternRef]) { function, label, args in
592592
[function.wasmLoadGlobal(globalVariable: global)]
@@ -626,7 +626,7 @@ class WasmFoundationTests: XCTestCase {
626626
let b = fuzzer.makeBuilder()
627627

628628
let global: Variable = b.createWasmGlobal(value: .externref, isMutable: true)
629-
XCTAssertEqual(b.type(of: global), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withWasmType: WasmGlobalType(valueType: ILType.wasmExternRef, isMutable: true)))
629+
XCTAssertEqual(b.type(of: global), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withMethods: ["valueOf"], withWasmType: WasmGlobalType(valueType: ILType.wasmExternRef, isMutable: true)))
630630

631631
let outputFunc = b.createNamedVariable(forBuiltin: "output")
632632
// The initial value is "undefined" (because we didn't provide an explicit initialization).
@@ -651,7 +651,7 @@ class WasmFoundationTests: XCTestCase {
651651

652652
let module = b.buildWasmModule { wasmModule in
653653
let global = wasmModule.addGlobal(wasmGlobal: .i31ref, isMutable: true)
654-
XCTAssertEqual(b.type(of: global), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withWasmType: WasmGlobalType(valueType: ILType.wasmI31Ref, isMutable: true)))
654+
XCTAssertEqual(b.type(of: global), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withMethods: ["valueOf"], withWasmType: WasmGlobalType(valueType: ILType.wasmI31Ref, isMutable: true)))
655655

656656
wasmModule.addWasmFunction(with: [] => [.wasmI31Ref]) { function, label, args in
657657
[function.wasmLoadGlobal(globalVariable: global)]
@@ -690,7 +690,7 @@ class WasmFoundationTests: XCTestCase {
690690
let b = fuzzer.makeBuilder()
691691

692692
let global: Variable = b.createWasmGlobal(value: .i31ref, isMutable: true)
693-
XCTAssertEqual(b.type(of: global), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withWasmType: WasmGlobalType(valueType: ILType.wasmI31Ref, isMutable: true)))
693+
XCTAssertEqual(b.type(of: global), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withMethods: ["valueOf"], withWasmType: WasmGlobalType(valueType: ILType.wasmI31Ref, isMutable: true)))
694694

695695
let outputFunc = b.createNamedVariable(forBuiltin: "output")
696696
// The initial value is "null" (because we didn't provide an explicit initialization).
@@ -6268,7 +6268,7 @@ class WasmJSPITests: XCTestCase {
62686268
let b = fuzzer.makeBuilder()
62696269

62706270
let wasmGlobali64: Variable = b.createWasmGlobal(value: .wasmi64(1337), isMutable: true)
6271-
XCTAssertEqual(b.type(of: wasmGlobali64), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withWasmType: WasmGlobalType(valueType: ILType.wasmi64, isMutable: true)))
6271+
XCTAssertEqual(b.type(of: wasmGlobali64), .object(ofGroup: "WasmGlobal", withProperties: ["value"], withMethods: ["valueOf"], withWasmType: WasmGlobalType(valueType: ILType.wasmi64, isMutable: true)))
62726272

62736273
let module = b.buildWasmModule { wasmModule in
62746274
// Function 0, modifies the imported global.

0 commit comments

Comments
 (0)