wasm/Object: parse using the correct file size

When an object file is being parsed from within an archive
file, we provide the object file size to ensure we do not
read past the object file. This is because follow up object
files can exist there, as well as an LF character to notate
the end of the file was reached. Such a character is invalid
within the object file.

This also fixes a bug in getting the function/global type
for defined globals/functions from object files as it was missing
the substraction with the import count of the respective type.
This commit is contained in:
Luuk de Gram 2022-08-19 21:15:16 +02:00
parent aca911ca18
commit 1544625df3
No known key found for this signature in database
GPG Key ID: A8CFE58E4DC7D664
3 changed files with 31 additions and 8 deletions

View File

@ -378,7 +378,7 @@ fn parseObjectFile(self: *Wasm, path: []const u8) !bool {
const file = try fs.cwd().openFile(path, .{});
errdefer file.close();
var object = Object.create(self.base.allocator, file, path) catch |err| switch (err) {
var object = Object.create(self.base.allocator, file, path, null) catch |err| switch (err) {
error.InvalidMagicByte, error.NotObjectFile => return false,
else => |e| return e,
};
@ -595,8 +595,8 @@ fn resolveSymbolsInArchives(self: *Wasm) !void {
// Parse object and and resolve symbols again before we check remaining
// undefined symbols.
const object_file_index = @intCast(u16, self.objects.items.len);
const object = try self.objects.addOne(self.base.allocator);
object.* = try archive.parseObject(self.base.allocator, offset.items[0]);
var object = try archive.parseObject(self.base.allocator, offset.items[0]);
try self.objects.append(self.base.allocator, object);
try self.resolveSymbolsInObject(object_file_index);
// continue loop for any remaining undefined symbols that still exist
@ -860,7 +860,8 @@ fn getGlobalType(self: *const Wasm, loc: SymbolLoc) wasm.GlobalType {
if (is_undefined) {
return obj.findImport(.global, symbol.index).kind.global;
}
return obj.globals[symbol.index].global_type;
const import_global_count = obj.importedCountByKind(.global);
return obj.globals[symbol.index - import_global_count].global_type;
}
if (is_undefined) {
return self.imports.get(loc).?.kind.global;
@ -880,7 +881,9 @@ fn getFunctionSignature(self: *const Wasm, loc: SymbolLoc) wasm.Type {
const ty_index = obj.findImport(.function, symbol.index).kind.function;
return obj.func_types[ty_index];
}
return obj.func_types[obj.functions[symbol.index].type_index];
const import_function_count = obj.importedCountByKind(.function);
const type_index = obj.functions[symbol.index - import_function_count].type_index;
return obj.func_types[type_index];
}
if (is_undefined) {
const ty_index = self.imports.get(loc).?.kind.function;

View File

@ -218,6 +218,7 @@ pub fn parseObject(archive: Archive, allocator: Allocator, file_offset: u32) !Ob
const object_file = try std.fs.cwd().openFile(archive.name, .{});
errdefer object_file.close();
const object_file_size = try header.size();
try object_file.seekTo(current_offset);
return Object.create(allocator, object_file, name);
return Object.create(allocator, object_file, name, object_file_size);
}

View File

@ -105,14 +105,33 @@ pub const InitError = error{NotObjectFile} || ParseError || std.fs.File.ReadErro
/// Initializes a new `Object` from a wasm object file.
/// This also parses and verifies the object file.
pub fn create(gpa: Allocator, file: std.fs.File, name: []const u8) InitError!Object {
/// When a max size is given, will only parse up to the given size,
/// else will read until the end of the file.
pub fn create(gpa: Allocator, file: std.fs.File, name: []const u8, maybe_max_size: ?usize) InitError!Object {
var object: Object = .{
.file = file,
.name = try gpa.dupe(u8, name),
};
var is_object_file: bool = false;
try object.parse(gpa, file.reader(), &is_object_file);
const size = maybe_max_size orelse size: {
errdefer gpa.free(object.name);
const stat = try file.stat();
break :size @intCast(usize, stat.size);
};
const file_contents = try gpa.alloc(u8, size);
defer gpa.free(file_contents);
var file_reader = file.reader();
var read: usize = 0;
while (read < size) {
const n = try file_reader.read(file_contents[read..]);
std.debug.assert(n != 0);
read += n;
}
var fbs = std.io.fixedBufferStream(file_contents);
try object.parse(gpa, fbs.reader(), &is_object_file);
errdefer object.deinit(gpa);
if (!is_object_file) return error.NotObjectFile;