Commit ee1630beea

Jakub Konka <kubkon@jakubkonka.com>
2023-12-05 16:31:47
elf: exit early with an error when parsing or init failed
1 parent 205857e
Changed files (3)
src
test
link
src/link/Elf/Object.zig
@@ -72,7 +72,7 @@ pub fn parse(self: *Object, elf_file: *Elf) !void {
     {
         try elf_file.reportParseError2(
             self.index,
-            "corrupted header: section header table extends past the end of file",
+            "corrupt header: section header table extends past the end of file",
             .{},
         );
         return error.MalformedObject;
@@ -86,14 +86,23 @@ pub fn parse(self: *Object, elf_file: *Elf) !void {
     try self.shdrs.ensureTotalCapacityPrecise(gpa, shdrs.len);
 
     for (shdrs) |shdr| {
-        if (self.data.len < shdr.sh_offset or self.data.len < shdr.sh_offset + shdr.sh_size) {
-            try elf_file.reportParseError2(self.index, "corrupted section header", .{});
-            return error.MalformedObject;
+        if (shdr.sh_type != elf.SHT_NOBITS) {
+            if (self.data.len < shdr.sh_offset or self.data.len < shdr.sh_offset + shdr.sh_size) {
+                try elf_file.reportParseError2(self.index, "corrupt section: extends past the end of file", .{});
+                return error.MalformedObject;
+            }
         }
         self.shdrs.appendAssumeCapacity(try ElfShdr.fromElf64Shdr(shdr));
     }
 
-    try self.strtab.appendSlice(gpa, self.shdrContents(self.header.?.e_shstrndx));
+    const shstrtab = self.shdrContents(self.header.?.e_shstrndx);
+    for (shdrs) |shdr| {
+        if (shdr.sh_name >= shstrtab.len) {
+            try elf_file.reportParseError2(self.index, "corrupt section name offset", .{});
+            return error.MalformedObject;
+        }
+    }
+    try self.strtab.appendSlice(gpa, shstrtab);
 
     const symtab_index = for (self.shdrs.items, 0..) |shdr, i| switch (shdr.sh_type) {
         elf.SHT_SYMTAB => break @as(u16, @intCast(i)),
@@ -105,7 +114,10 @@ pub fn parse(self: *Object, elf_file: *Elf) !void {
         self.first_global = shdr.sh_info;
 
         const raw_symtab = self.shdrContents(index);
-        const nsyms = @divExact(raw_symtab.len, @sizeOf(elf.Elf64_Sym));
+        const nsyms = math.divExact(usize, raw_symtab.len, @sizeOf(elf.Elf64_Sym)) catch {
+            try elf_file.reportParseError2(self.index, "symbol table not evenly divisible", .{});
+            return error.MalformedObject;
+        };
         const symtab = @as([*]align(1) const elf.Elf64_Sym, @ptrCast(raw_symtab.ptr))[0..nsyms];
 
         const strtab_bias = @as(u32, @intCast(self.strtab.items.len));
src/link/Elf.zig
@@ -1160,6 +1160,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
         };
     }
 
+    if (self.misc_errors.items.len > 0) return error.FlushFailure;
+
     // Init all objects
     for (self.objects.items) |index| {
         try self.file(index).?.object.init(self);
@@ -1168,6 +1170,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
         try self.file(index).?.shared_object.init(self);
     }
 
+    if (self.misc_errors.items.len > 0) return error.FlushFailure;
+
     // Dedup shared objects
     {
         var seen_dsos = std.StringHashMap(void).init(gpa);
@@ -1294,6 +1298,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
         self.error_flags.no_entry_point_found = false;
         try self.writeElfHeader();
     }
+
+    if (self.misc_errors.items.len > 0) return error.FlushFailure;
 }
 
 pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void {
@@ -2803,7 +2809,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
                     }));
                 } else {
                     self.error_flags.missing_libc = true;
-                    return error.FlushFailure;
                 }
             }
         }
test/link/elf.zig
@@ -1877,8 +1877,6 @@ fn testMismatchedCpuArchitectureError(b: *Build, opts: Options) *Step {
     expectLinkErrors(exe, test_step, .{ .exact = &.{
         "invalid cpu architecture: aarch64",
         "note: while parsing /?/a.o",
-        "undefined symbol: foo",
-        "note: referenced by /?/a.o:.text",
     } });
 
     return test_step;
@@ -3309,10 +3307,8 @@ fn testUnknownFileTypeError(b: *Build, opts: Options) *Step {
     expectLinkErrors(exe, test_step, .{ .exact = &.{
         "invalid token in LD script: '\\x00\\x00\\x00\\x0c\\x00\\x00\\x00/usr/lib/dyld\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0d' (0:829)",
         "note: while parsing /?/liba.dylib",
-        "error: unexpected error: parsing input file failed with error InvalidLdScript",
+        "unexpected error: parsing input file failed with error InvalidLdScript",
         "note: while parsing /?/liba.dylib",
-        "undefined symbol: foo",
-        "note: referenced by /?/a.o:.text",
     } });
 
     return test_step;