From ed1860f8e8397be4b6739901356de05e95f60c1e Mon Sep 17 00:00:00 2001 From: Jonathan Marler Date: Fri, 18 Oct 2024 13:18:47 -0600 Subject: [PATCH] fix a few unsigned/signed readI/ULEB mismatches (#232) There was a few mismatches where readULEB was being called with signed types. I fixed those and collapsed the readILEB/readULEB into one readLEB function that just uses the signedness of the native type to determine which underlying function to use. --- src/module.zig | 100 +++++++++++---------- src/module/parser.zig | 197 +++++++++++++++++++++--------------------- 2 files changed, 150 insertions(+), 147 deletions(-) diff --git a/src/module.zig b/src/module.zig index 377da69e..acead6ef 100644 --- a/src/module.zig +++ b/src/module.zig @@ -156,7 +156,7 @@ pub const Decoder = struct { else => return err, }; - const size = try self.readULEB128(u32); + const size = try self.readLEB128(u32); const section_start = self.fbs.pos; @@ -181,7 +181,7 @@ pub const Decoder = struct { } fn decodeTypeSection(self: *Decoder, module: *Module) !void { - const count = try self.readULEB128(u32); + const count = try self.readLEB128(u32); module.types.count = count; var f: usize = 0; @@ -189,7 +189,7 @@ pub const Decoder = struct { const tag = try self.readByte(); if (tag != 0x60) return error.ExpectedFuncTypeTag; - const param_count = try self.readULEB128(u32); + const param_count = try self.readLEB128(u32); const params_start = self.fbs.pos; { var i: usize = 0; @@ -199,7 +199,7 @@ pub const Decoder = struct { } const params_end = self.fbs.pos; - const results_count = try self.readULEB128(u32); + const results_count = try self.readLEB128(u32); const results_start = self.fbs.pos; { var i: usize = 0; @@ -228,17 +228,17 @@ pub const Decoder = struct { } fn decodeImportSection(self: *Decoder, module: *Module) !void { - const count = try self.readULEB128(u32); + const count = try self.readLEB128(u32); module.imports.count = count; var i: usize = 0; while (i < count) : (i += 1) { - const module_name_length = try self.readULEB128(u32); + const module_name_length = try self.readLEB128(u32); const module_name = try self.readSlice(module_name_length); if (!unicode.utf8ValidateSlice(module_name)) return error.NameNotUTF8; - const name_length = try self.readULEB128(u32); + const name_length = try self.readLEB128(u32); const name = try self.readSlice(name_length); if (!unicode.utf8ValidateSlice(name)) return error.NameNotUTF8; @@ -263,7 +263,7 @@ pub const Decoder = struct { } fn decodeFunctionSection(self: *Decoder, module: *Module) !void { - const count = try self.readULEB128(u32); + const count = try self.readLEB128(u32); module.functions.count = count; var i: usize = 0; @@ -273,7 +273,7 @@ pub const Decoder = struct { } fn decodeFunction(self: *Decoder, module: *Module, import: ?u32) !void { - const typeidx = try self.readULEB128(u32); + const typeidx = try self.readLEB128(u32); if (typeidx >= module.types.list.items.len) return error.ValidatorInvalidTypeIndex; @@ -288,7 +288,7 @@ pub const Decoder = struct { } fn decodeTableSection(self: *Decoder, module: *Module) !void { - const count = try self.readULEB128(u32); + const count = try self.readLEB128(u32); module.tables.count = count; var i: usize = 0; @@ -300,12 +300,12 @@ pub const Decoder = struct { fn decodeTable(self: *Decoder, module: *Module, import: ?u32) !void { const reftype = try self.readEnum(RefType); const limit_type = try self.readEnum(LimitType); - const min = try self.readULEB128(u32); + const min = try self.readLEB128(u32); const max: ?u32 = blk: { switch (limit_type) { .Min => break :blk null, .MinMax => { - const max = try self.readULEB128(u32); + const max = try self.readLEB128(u32); if (min > max) return error.ValidatorTableMinGreaterThanMax; break :blk max; }, @@ -322,7 +322,7 @@ pub const Decoder = struct { } fn decodeMemorySection(self: *Decoder, module: *Module) !void { - const count = try self.readULEB128(u32); + const count = try self.readLEB128(u32); module.memories.count = count; var i: usize = 0; @@ -335,13 +335,13 @@ pub const Decoder = struct { if (module.memories.list.items.len > 0) return error.ValidatorMultipleMemories; const limit_type = try self.readEnum(LimitType); - const min = try self.readULEB128(u32); + const min = try self.readLEB128(u32); if (min > 65536) return error.ValidatorMemoryMinTooLarge; const max: ?u32 = blk: { switch (limit_type) { .Min => break :blk null, .MinMax => { - const max = try self.readULEB128(u32); + const max = try self.readLEB128(u32); if (min > max) return error.ValidatorMemoryMinGreaterThanMax; if (max > 65536) return error.ValidatorMemoryMaxTooLarge; break :blk max; @@ -358,7 +358,7 @@ pub const Decoder = struct { } fn decodeGlobalSection(self: *Decoder, module: *Module) !void { - const count = try self.readULEB128(u32); + const count = try self.readLEB128(u32); module.globals.count = count; var i: usize = 0; @@ -391,12 +391,12 @@ pub const Decoder = struct { } fn decodeExportSection(self: *Decoder, module: *Module) !void { - const count = try self.readULEB128(u32); + const count = try self.readLEB128(u32); module.exports.count = count; var i: usize = 0; while (i < count) : (i += 1) { - const name_length = try self.readULEB128(u32); + const name_length = try self.readLEB128(u32); const name = try self.readSlice(name_length); if (!unicode.utf8ValidateSlice(name)) return error.NameNotUTF8; @@ -406,7 +406,7 @@ pub const Decoder = struct { } const tag = try self.readEnum(Tag); - const index = try self.readULEB128(u32); + const index = try self.readLEB128(u32); switch (tag) { .Func => { @@ -429,7 +429,7 @@ pub const Decoder = struct { fn decodeStartSection(self: *Decoder, module: *Module) !void { if (module.start != null) return error.MultipleStartSections; - const funcidx = try self.readULEB128(u32); + const funcidx = try self.readLEB128(u32); const func = try module.functions.lookup(funcidx); const functype = try module.types.lookup(func.typeidx); @@ -439,12 +439,12 @@ pub const Decoder = struct { } fn decodeElementSection(self: *Decoder, module: *Module) !void { - const count = try self.readULEB128(u32); + const count = try self.readLEB128(u32); module.elements.count = count; var i: usize = 0; while (i < count) : (i += 1) { - const elem_type = try self.readULEB128(u32); + const elem_type = try self.readLEB128(u32); switch (elem_type) { 0 => { @@ -453,13 +453,13 @@ pub const Decoder = struct { const parsed_offset_code = try self.readConstantExpression(module, .I32); - const data_length = try self.readULEB128(u32); + const data_length = try self.readLEB128(u32); const first_init_offset = module.element_init_offsets.items.len; var j: usize = 0; while (j < data_length) : (j += 1) { - const funcidx = try self.readULEB128(u32); + const funcidx = try self.readLEB128(u32); if (funcidx >= module.functions.list.items.len) return error.ValidatorElemUnknownFunctionIndex; @@ -484,13 +484,13 @@ pub const Decoder = struct { 1 => { _ = try self.readEnum(ElemKind); - const data_length = try self.readULEB128(u32); + const data_length = try self.readLEB128(u32); const first_init_offset = module.element_init_offsets.items.len; var j: usize = 0; while (j < data_length) : (j += 1) { - const funcidx = try self.readULEB128(u32); + const funcidx = try self.readLEB128(u32); if (funcidx >= module.functions.list.items.len) return error.ValidatorElemUnknownFunctionIndex; @@ -510,20 +510,20 @@ pub const Decoder = struct { }); }, 2 => { - const tableidx = try self.readULEB128(u32); + const tableidx = try self.readLEB128(u32); if (tableidx >= module.tables.list.items.len) return error.ValidatorElemUnknownTable; const parsed_offset_code = try self.readConstantExpression(module, .I32); _ = try self.readEnum(ElemKind); - const data_length = try self.readULEB128(u32); + const data_length = try self.readLEB128(u32); const first_init_offset = module.element_init_offsets.items.len; var j: usize = 0; while (j < data_length) : (j += 1) { - const funcidx = try self.readULEB128(u32); + const funcidx = try self.readLEB128(u32); if (funcidx >= module.functions.list.items.len) return error.ValidatorElemUnknownFunctionIndex; @@ -547,13 +547,13 @@ pub const Decoder = struct { }, 3 => { _ = try self.readEnum(ElemKind); - const data_length = try self.readULEB128(u32); + const data_length = try self.readLEB128(u32); const first_init_offset = module.element_init_offsets.items.len; var j: usize = 0; while (j < data_length) : (j += 1) { - const funcidx = try self.readULEB128(u32); + const funcidx = try self.readLEB128(u32); if (funcidx >= module.functions.list.items.len) return error.ValidatorElemUnknownFunctionIndex; @@ -578,7 +578,7 @@ pub const Decoder = struct { const parsed_offset_code = try self.readConstantExpression(module, .I32); - const init_expression_count = try self.readULEB128(u32); + const init_expression_count = try self.readLEB128(u32); const first_init_offset = module.element_init_offsets.items.len; @@ -600,7 +600,7 @@ pub const Decoder = struct { }, 5 => { // Passive const reftype = try self.readEnum(RefType); - const expr_count = try self.readULEB128(u32); + const expr_count = try self.readLEB128(u32); const first_init_offset = module.element_init_offsets.items.len; @@ -620,7 +620,7 @@ pub const Decoder = struct { }, 7 => { // Declarative const reftype = try self.readEnum(RefType); - const expr_count = try self.readULEB128(u32); + const expr_count = try self.readLEB128(u32); const first_init_offset = module.element_init_offsets.items.len; @@ -646,11 +646,11 @@ pub const Decoder = struct { fn decodeDataCountSection(self: *Decoder, module: *Module, size: u32) !void { if (size == 0) return; - module.data_count = try self.readULEB128(u32); + module.data_count = try self.readLEB128(u32); } fn decodeCodeSection(self: *Decoder, module: *Module) !void { - const count = try self.readULEB128(u32); + const count = try self.readLEB128(u32); module.codes.count = count; try module.parsed_code.ensureTotalCapacity(count * 32); @@ -662,9 +662,9 @@ pub const Decoder = struct { var i: usize = 0; while (i < count) : (i += 1) { // size: the number of bytes defining the function, includes bytes defining locals - _ = try self.readULEB128(u32); + _ = try self.readLEB128(u32); - const locals_definitions_count = try self.readULEB128(u32); + const locals_definitions_count = try self.readLEB128(u32); const locals_start = module.local_types.items.len; @@ -672,7 +672,7 @@ pub const Decoder = struct { var j: usize = 0; var locals_count: usize = 0; while (j < locals_definitions_count) : (j += 1) { - const type_count = try self.readULEB128(u32); + const type_count = try self.readLEB128(u32); const local_type = try self.readEnum(ValType); locals_count += type_count; @@ -694,7 +694,7 @@ pub const Decoder = struct { } fn decodeDataSection(self: *Decoder, module: *Module) !void { - const count = try self.readULEB128(u32); + const count = try self.readLEB128(u32); if (module.data_count) |data_count| { if (count != data_count) return error.DataCountSectionDataSectionCountMismatch; @@ -704,7 +704,7 @@ pub const Decoder = struct { var i: usize = 0; while (i < count) : (i += 1) { - const data_section_type = try self.readULEB128(u32); + const data_section_type = try self.readLEB128(u32); switch (data_section_type) { 0 => { @@ -714,7 +714,7 @@ pub const Decoder = struct { const parsed_code = try self.readConstantExpression(module, .I32); - const data_length = try self.readULEB128(u32); + const data_length = try self.readLEB128(u32); const data = try self.readSlice(data_length); try module.datas.list.append(DataSegment{ @@ -727,7 +727,7 @@ pub const Decoder = struct { }); }, 1 => { - const data_length = try self.readULEB128(u32); + const data_length = try self.readLEB128(u32); const data = try self.readSlice(data_length); try module.datas.list.append(DataSegment{ @@ -737,13 +737,13 @@ pub const Decoder = struct { }); }, 2 => { - const memidx = try self.readULEB128(u32); + const memidx = try self.readLEB128(u32); if (memidx >= module.memories.list.items.len) return error.ValidatorDataMemoryReferenceInvalid; const parsed_code = try self.readConstantExpression(module, .I32); - const data_length = try self.readULEB128(u32); + const data_length = try self.readLEB128(u32); const data = try self.readSlice(data_length); try module.datas.list.append(DataSegment{ @@ -765,7 +765,7 @@ pub const Decoder = struct { fn decodeCustomSection(self: *Decoder, module: *Module, size: u32) !void { const offset = self.fbs.pos; - const name_length = try self.readULEB128(u32); + const name_length = try self.readLEB128(u32); const name = try self.readSlice(name_length); if (!unicode.utf8ValidateSlice(name)) return error.NameNotUTF8; @@ -806,8 +806,12 @@ pub const Decoder = struct { return self.fbs.reader().readEnum(T, .little); } - fn readULEB128(self: *Decoder, comptime T: type) !T { - return leb.readULEB128(T, self.fbs.reader()); + fn readLEB128(self: *Decoder, comptime T: type) !T { + const readFn = switch (@typeInfo(T).Int.signedness) { + .signed => std.leb.readILEB128, + .unsigned => std.leb.readULEB128, + }; + return readFn(T, self.fbs.reader()); } pub fn readSlice(self: *Decoder, count: usize) ![]const u8 { diff --git a/src/module/parser.zig b/src/module/parser.zig index d124bc7e..cae03b65 100644 --- a/src/module/parser.zig +++ b/src/module/parser.zig @@ -171,7 +171,7 @@ pub const Parser = struct { .@"unreachable" => rr = Rr.@"unreachable", .nop => rr = Rr.nop, .block => { - const block_type = try self.readILEB128Mem(i32); + const block_type = try self.readLEB128Mem(i32); var block_params: u16 = 0; var block_returns: u16 = if (block_type == -0x40) 0 else 1; @@ -210,7 +210,7 @@ pub const Parser = struct { }; }, .loop => { - const block_type = try self.readILEB128Mem(i32); + const block_type = try self.readLEB128Mem(i32); var block_params: u16 = 0; var block_returns: u16 = if (block_type == -0x40) 0 else 1; @@ -248,7 +248,7 @@ pub const Parser = struct { }; }, .@"if" => { - const block_type = try self.readILEB128Mem(i32); + const block_type = try self.readLEB128Mem(i32); // 1. First assume the number of block params is 0 // 2. The number of return values is 0 if block_type == -0x40 @@ -334,25 +334,25 @@ pub const Parser = struct { rr = Rr.end; }, .br => { - const label = try self.readULEB128Mem(u32); + const label = try self.readLEB128Mem(u32); try self.validator.validateBr(label); rr = Rr{ .br = label }; }, .br_if => { - const label = try self.readULEB128Mem(u32); + const label = try self.readLEB128Mem(u32); try self.validator.validateBrIf(label); rr = Rr{ .br_if = label }; }, .br_table => { const label_start = self.module.br_table_indices.items.len; - const label_count = try self.readULEB128Mem(u32); + const label_count = try self.readLEB128Mem(u32); var j: usize = 0; while (j < label_count) : (j += 1) { - const tmp_label = try self.readULEB128Mem(u32); + const tmp_label = try self.readLEB128Mem(u32); try self.module.br_table_indices.append(tmp_label); } - const ln = try self.readULEB128Mem(u32); + const ln = try self.readLEB128Mem(u32); const l_star = self.module.br_table_indices.items[label_start .. label_start + j]; try self.validator.validateBrTable(l_star, ln); @@ -366,7 +366,7 @@ pub const Parser = struct { }, .@"return" => rr = Rr.@"return", .call => { - const funcidx = try self.readULEB128Mem(u32); + const funcidx = try self.readLEB128Mem(u32); const func = try self.module.functions.lookup(funcidx); const functype = try self.module.types.lookup(func.typeidx); @@ -377,7 +377,7 @@ pub const Parser = struct { // rr = Rr{ .fast_call = .{ .ip_start = 0, .params = 1, .locals = 0, .results = 1 } }; }, .call_indirect => { - const typeidx = try self.readULEB128Mem(u32); + const typeidx = try self.readLEB128Mem(u32); const functype = try self.module.types.lookup(typeidx); const tableidx = try self.readByte(); @@ -395,9 +395,9 @@ pub const Parser = struct { .drop => rr = Rr.drop, .select => rr = Rr.select, .select_t => { - const type_count = try self.readULEB128Mem(u32); + const type_count = try self.readLEB128Mem(u32); if (type_count != 1) return error.OnlyOneSelectTTypeSupported; // Future versions may support more than one - const valuetype_raw = try self.readULEB128Mem(i32); + const valuetype_raw = try self.readLEB128Mem(u32); const valuetype = try std.meta.intToEnum(ValType, valuetype_raw); try self.validator.validateSelectT(valuetype); @@ -405,7 +405,7 @@ pub const Parser = struct { rr = Rr.select; }, .@"global.get" => { - const globalidx = try self.readULEB128Mem(u32); + const globalidx = try self.readLEB128Mem(u32); const global = try self.module.globals.lookup(globalidx); try self.validator.validateGlobalGet(global); @@ -413,7 +413,7 @@ pub const Parser = struct { rr = Rr{ .@"global.get" = globalidx }; }, .@"global.set" => { - const globalidx = try self.readULEB128Mem(u32); + const globalidx = try self.readLEB128Mem(u32); const global = try self.module.globals.lookup(globalidx); try self.validator.validateGlobalSet(global); @@ -421,7 +421,7 @@ pub const Parser = struct { rr = Rr{ .@"global.set" = globalidx }; }, .@"table.get" => { - const tableidx = try self.readULEB128Mem(u32); + const tableidx = try self.readLEB128Mem(u32); const table = try self.module.tables.lookup(tableidx); const reftype: ValType = switch (table.reftype) { @@ -435,7 +435,7 @@ pub const Parser = struct { rr = Rr{ .@"table.get" = tableidx }; }, .@"table.set" => { - const tableidx = try self.readULEB128Mem(u32); + const tableidx = try self.readLEB128Mem(u32); const table = try self.module.tables.lookup(tableidx); const reftype: ValType = switch (table.reftype) { @@ -449,7 +449,7 @@ pub const Parser = struct { rr = Rr{ .@"table.set" = tableidx }; }, .@"local.get" => { - const localidx = try self.readULEB128Mem(u32); + const localidx = try self.readLEB128Mem(u32); const params = self.params orelse return error.ValidatorConstantExpressionRequired; const locals = self.locals orelse return error.ValidatorConstantExpressionRequired; @@ -477,7 +477,7 @@ pub const Parser = struct { rr = Rr{ .@"local.get" = localidx }; }, .@"local.set" => { - const localidx = try self.readULEB128Mem(u32); + const localidx = try self.readLEB128Mem(u32); const params = self.params orelse return error.ValidatorConstantExpressionRequired; const locals = self.locals orelse return error.ValidatorConstantExpressionRequired; @@ -506,7 +506,7 @@ pub const Parser = struct { rr = Rr{ .@"local.set" = localidx }; }, .@"local.tee" => { - const localidx = try self.readULEB128Mem(u32); + const localidx = try self.readLEB128Mem(u32); const params = self.params orelse return error.ValidatorConstantExpressionRequired; const locals = self.locals orelse return error.ValidatorConstantExpressionRequired; @@ -549,11 +549,11 @@ pub const Parser = struct { rr = Rr{ .@"memory.grow" = memidx }; }, .@"i32.const" => { - const i32_const = try self.readILEB128Mem(i32); + const i32_const = try self.readLEB128Mem(i32); rr = Rr{ .@"i32.const" = i32_const }; }, .@"i64.const" => { - const i64_const = try self.readILEB128Mem(i64); + const i64_const = try self.readLEB128Mem(i64); rr = Rr{ .@"i64.const" = i64_const }; }, .@"f32.const" => { @@ -567,8 +567,8 @@ pub const Parser = struct { .@"i32.load" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; @@ -581,8 +581,8 @@ pub const Parser = struct { }, .@"i64.load" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 64) return error.InvalidAlignment; @@ -595,8 +595,8 @@ pub const Parser = struct { }, .@"f32.load" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; @@ -609,8 +609,8 @@ pub const Parser = struct { }, .@"f64.load" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 64) return error.InvalidAlignment; @@ -623,8 +623,8 @@ pub const Parser = struct { }, .@"i32.load8_s" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 8) return error.InvalidAlignment; @@ -637,8 +637,8 @@ pub const Parser = struct { }, .@"i32.load8_u" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 8) return error.InvalidAlignment; @@ -651,8 +651,8 @@ pub const Parser = struct { }, .@"i32.load16_s" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 16) return error.InvalidAlignment; @@ -665,8 +665,8 @@ pub const Parser = struct { }, .@"i32.load16_u" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 16) return error.InvalidAlignment; @@ -679,8 +679,8 @@ pub const Parser = struct { }, .@"i64.load8_s" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 8) return error.InvalidAlignment; @@ -693,8 +693,8 @@ pub const Parser = struct { }, .@"i64.load8_u" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 8) return error.InvalidAlignment; @@ -707,8 +707,8 @@ pub const Parser = struct { }, .@"i64.load16_s" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 16) return error.InvalidAlignment; @@ -721,8 +721,8 @@ pub const Parser = struct { }, .@"i64.load16_u" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 16) return error.InvalidAlignment; @@ -735,8 +735,8 @@ pub const Parser = struct { }, .@"i64.load32_s" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; @@ -749,8 +749,8 @@ pub const Parser = struct { }, .@"i64.load32_u" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; @@ -763,8 +763,8 @@ pub const Parser = struct { }, .@"i32.store" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; @@ -777,8 +777,8 @@ pub const Parser = struct { }, .@"i64.store" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 64) return error.InvalidAlignment; @@ -791,8 +791,8 @@ pub const Parser = struct { }, .@"f32.store" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; @@ -805,8 +805,8 @@ pub const Parser = struct { }, .@"f64.store" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 64) return error.InvalidAlignment; @@ -819,8 +819,8 @@ pub const Parser = struct { }, .@"i32.store8" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 8) return error.InvalidAlignment; @@ -833,8 +833,8 @@ pub const Parser = struct { }, .@"i32.store16" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 16) return error.InvalidAlignment; @@ -847,8 +847,8 @@ pub const Parser = struct { }, .@"i64.store8" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 8) return error.InvalidAlignment; @@ -861,8 +861,8 @@ pub const Parser = struct { }, .@"i64.store16" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 16) return error.InvalidAlignment; @@ -874,8 +874,8 @@ pub const Parser = struct { }; }, .@"i64.store32" => { - const alignment = try self.readULEB128Mem(u32); - const offset = try self.readULEB128Mem(u32); + const alignment = try self.readLEB128Mem(u32); + const offset = try self.readLEB128Mem(u32); if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; @@ -1015,7 +1015,7 @@ pub const Parser = struct { .@"i64.extend16_s" => rr = Rr.@"i64.extend16_s", .@"i64.extend32_s" => rr = Rr.@"i64.extend32_s", .@"ref.null" => { - const rtype = try self.readULEB128Mem(i32); + const rtype = try self.readLEB128Mem(u32); const reftype = std.meta.intToEnum(RefType, rtype) catch return error.MalformedRefType; try self.validator.validateRefNull(reftype); @@ -1023,7 +1023,7 @@ pub const Parser = struct { }, .@"ref.is_null" => rr = Rr.@"ref.is_null", .@"ref.func" => { - const funcidx = try self.readULEB128Mem(u32); + const funcidx = try self.readLEB128Mem(u32); if (funcidx >= self.module.functions.list.items.len) return error.ValidatorInvalidFunction; // Gather funcidx* from constant expressions @@ -1044,7 +1044,7 @@ pub const Parser = struct { rr = Rr{ .@"ref.func" = funcidx }; }, .misc => { - const version = try self.readULEB128Mem(u32); + const version = try self.readLEB128Mem(u32); const misc_opcode = try std.meta.intToEnum(MiscOpcode, version); try self.validator.validateMisc(misc_opcode); @@ -1058,7 +1058,7 @@ pub const Parser = struct { .@"i64.trunc_sat_f64_s" => rr = Rr{ .misc = MiscRr.@"i64.trunc_sat_f64_s" }, .@"i64.trunc_sat_f64_u" => rr = Rr{ .misc = MiscRr.@"i64.trunc_sat_f64_u" }, .@"memory.init" => { - const dataidx = try self.readULEB128Mem(u32); + const dataidx = try self.readLEB128Mem(u32); const memidx = try self.readByte(); const data_count = self.module.data_count orelse return error.InstructionRequiresDataCountSection; @@ -1075,7 +1075,7 @@ pub const Parser = struct { }; }, .@"data.drop" => { - const dataidx = try self.readULEB128Mem(u32); + const dataidx = try self.readLEB128Mem(u32); const data_count = self.module.data_count orelse return error.InstructionRequiresDataCountSection; if (!(dataidx < data_count)) return error.InvalidDataIndex; @@ -1100,10 +1100,10 @@ pub const Parser = struct { rr = Rr{ .misc = MiscRr{ .@"memory.fill" = memidx } }; }, .@"table.init" => { - const elemidx = try self.readULEB128Mem(u32); + const elemidx = try self.readLEB128Mem(u32); const elemtype = try self.module.elements.lookup(elemidx); - const tableidx = try self.readULEB128Mem(u32); + const tableidx = try self.readLEB128Mem(u32); const tabletype = try self.module.tables.lookup(tableidx); if (elemtype.reftype != tabletype.reftype) return error.MismatchedTypes; @@ -1114,17 +1114,17 @@ pub const Parser = struct { } } }; }, .@"elem.drop" => { - const elemidx = try self.readULEB128Mem(u32); + const elemidx = try self.readLEB128Mem(u32); if (elemidx >= self.module.elements.list.items.len) return error.ValidatorInvalidElementIndex; rr = Rr{ .misc = MiscRr{ .@"elem.drop" = .{ .elemidx = elemidx } } }; }, .@"table.copy" => { - const dest_tableidx = try self.readULEB128Mem(u32); + const dest_tableidx = try self.readLEB128Mem(u32); const dest_tabletype = try self.module.tables.lookup(dest_tableidx); - const src_tableidx = try self.readULEB128Mem(u32); + const src_tableidx = try self.readLEB128Mem(u32); const src_tabletype = try self.module.tables.lookup(src_tableidx); if (dest_tabletype.reftype != src_tabletype.reftype) return error.MismatchedTypes; @@ -1135,7 +1135,7 @@ pub const Parser = struct { } } }; }, .@"table.grow" => { - const tableidx = try self.readULEB128Mem(u32); + const tableidx = try self.readLEB128Mem(u32); const table = try self.module.tables.lookup(tableidx); const reftype: ValType = switch (table.reftype) { @@ -1153,7 +1153,7 @@ pub const Parser = struct { } } }; }, .@"table.size" => { - const tableidx = try self.readULEB128Mem(u32); + const tableidx = try self.readLEB128Mem(u32); if (tableidx >= self.module.tables.list.items.len) return error.ValidatorInvalidTableIndex; rr = Rr{ .misc = MiscRr{ .@"table.size" = .{ @@ -1161,7 +1161,7 @@ pub const Parser = struct { } } }; }, .@"table.fill" => { - const tableidx = try self.readULEB128Mem(u32); + const tableidx = try self.readLEB128Mem(u32); const table = try self.module.tables.lookup(tableidx); const reftype: ValType = switch (table.reftype) { @@ -1185,27 +1185,26 @@ pub const Parser = struct { return rr; } - pub fn readULEB128Mem(self: *Parser, comptime T: type) !T { + pub fn readLEB128Mem(self: *Parser, comptime T: type) !T { var buf = std.io.fixedBufferStream(self.code); - const value = try leb.readULEB128(T, buf.reader()); - self.code.ptr += buf.pos; - self.code.len -= buf.pos; - return value; - } - pub fn readILEB128Mem(self: *Parser, comptime T: type) !T { - var buf = std.io.fixedBufferStream(self.code); - const value = try leb.readILEB128(T, buf.reader()); - - // The following is a bit of a kludge that should really - // be fixed in either the std lib self.readILEB128 or using a - // a fresh implementation. The issue is that the wasm spec - // expects the "unused" bits in a negative ILEB128 to all be - // one and the same bits in a positive ILEB128 to be zero. - switch (T) { - i32 => if (buf.pos == 5 and value < 0 and buf.buffer[4] & 0x70 != 0x70) return error.Overflow, - i64 => if (buf.pos == 10 and value < 0 and buf.buffer[9] & 0x7e != 0x7e) return error.Overflow, - else => @compileError("self.readILEB128Mem expects i32 or i64"), + const readFn = switch (@typeInfo(T).Int.signedness) { + .signed => std.leb.readILEB128, + .unsigned => std.leb.readULEB128, + }; + const value = try readFn(T, buf.reader()); + + if (@typeInfo(T).Int.signedness == .signed) { + // The following is a bit of a kludge that should really + // be fixed in either the std lib readILEB128 or using a + // a fresh implementation. The issue is that the wasm spec + // expects the "unused" bits in a negative ILEB128 to all be + // one and the same bits in a positive ILEB128 to be zero. + switch (T) { + i32 => if (buf.pos == 5 and value < 0 and buf.buffer[4] & 0x70 != 0x70) return error.Overflow, + i64 => if (buf.pos == 10 and value < 0 and buf.buffer[9] & 0x7e != 0x7e) return error.Overflow, + else => @compileError("self.readLEB128Mem expects an unsigned type, i32 or i64"), + } } self.code.ptr += buf.pos;