authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-09 23:16:41+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-09 23:16:41+01:00
log08882234d17a93dd44181323db697db993aebe3d
tree73153b030bcb4365acd78f6f6cf62742fe357dff
parent6e797d864871575e6c1c4bec37f1e9eea4c79678

elf: fix overflowing designated capacity when writing COMDAT groups


2 files changed, 40 insertions(+), 54 deletions(-)

src/link/Elf.zig+37-51
......@@ -4797,7 +4797,11 @@ fn writeAtomsObject(self: *Elf) !void {
47974797 return error.Overflow;
47984798 const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;
47994799
4800 log.debug("writing atom({d}) at 0x{x}", .{ atom_index, sh_offset + offset });
4800 log.debug("writing atom({d}) from 0x{x} to 0x{x}", .{
4801 atom_index,
4802 sh_offset + offset,
4803 sh_offset + offset + size,
4804 });
48014805
48024806 // TODO decompress directly into provided buffer
48034807 const out_code = buffer[offset..][0..size];
......@@ -5048,6 +5052,7 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {
50485052 if (!atom_ptr.flags.alive) continue;
50495053 try atom_ptr.writeRelocs(self, &relocs);
50505054 }
5055 assert(relocs.items.len == num_relocs);
50515056
50525057 const SortRelocs = struct {
50535058 pub fn lessThan(ctx: void, lhs: elf.Elf64_Rela, rhs: elf.Elf64_Rela) bool {
......@@ -5058,6 +5063,12 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {
50585063
50595064 mem.sort(elf.Elf64_Rela, relocs.items, {}, SortRelocs.lessThan);
50605065
5066 log.debug("writing {s} from 0x{x} to 0x{x}", .{
5067 self.getShString(shdr.sh_name),
5068 shdr.sh_offset,
5069 shdr.sh_offset + shdr.sh_size,
5070 });
5071
50615072 try self.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), shdr.sh_offset);
50625073 }
50635074
......@@ -5067,6 +5078,11 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {
50675078 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
50685079 defer buffer.deinit();
50695080 try eh_frame.writeEhFrameObject(self, buffer.writer());
5081 log.debug("writing .eh_frame from 0x{x} to 0x{x}", .{
5082 shdr.sh_offset,
5083 shdr.sh_offset + shdr.sh_size,
5084 });
5085 assert(buffer.items.len == sh_size);
50705086 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
50715087 }
50725088 if (self.eh_frame_rela_section_index) |shndx| {
......@@ -5075,6 +5091,11 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {
50755091 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
50765092 defer buffer.deinit();
50775093 try eh_frame.writeEhFrameRelocs(self, buffer.writer());
5094 assert(buffer.items.len == sh_size);
5095 log.debug("writing .rela.eh_frame from 0x{x} to 0x{x}", .{
5096 shdr.sh_offset,
5097 shdr.sh_offset + shdr.sh_size,
5098 });
50785099 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
50795100 }
50805101
......@@ -5091,6 +5112,11 @@ fn writeComdatGroups(self: *Elf) !void {
50915112 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
50925113 defer buffer.deinit();
50935114 try cgs.write(self, buffer.writer());
5115 assert(buffer.items.len == sh_size);
5116 log.debug("writing COMDAT group from 0x{x} to 0x{x}", .{
5117 shdr.sh_offset,
5118 shdr.sh_offset + shdr.sh_size,
5119 });
50945120 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
50955121 }
50965122}
......@@ -5098,6 +5124,7 @@ fn writeComdatGroups(self: *Elf) !void {
50985124fn writeShStrtab(self: *Elf) !void {
50995125 if (self.shstrtab_section_index) |index| {
51005126 const shdr = self.shdrs.items[index];
5127 log.debug("writing .shstrtab from 0x{x} to 0x{x}", .{ shdr.sh_offset, shdr.sh_offset + shdr.sh_size });
51015128 try self.base.file.?.pwriteAll(self.shstrtab.items, shdr.sh_offset);
51025129 }
51035130}
......@@ -5112,7 +5139,15 @@ fn writeSymtab(self: *Elf) !void {
51125139 };
51135140 const nsyms = math.cast(usize, @divExact(symtab_shdr.sh_size, sym_size)) orelse return error.Overflow;
51145141
5115 log.debug("writing {d} symbols at 0x{x}", .{ nsyms, symtab_shdr.sh_offset });
5142 log.debug("writing {d} symbols in .symtab from 0x{x} to 0x{x}", .{
5143 nsyms,
5144 symtab_shdr.sh_offset,
5145 symtab_shdr.sh_offset + symtab_shdr.sh_size,
5146 });
5147 log.debug("writing .strtab from 0x{x} to 0x{x}", .{
5148 strtab_shdr.sh_offset,
5149 strtab_shdr.sh_offset + strtab_shdr.sh_size,
5150 });
51165151
51175152 try self.symtab.resize(gpa, nsyms);
51185153 const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow;
......@@ -5185,55 +5220,6 @@ fn writeSymtab(self: *Elf) !void {
51855220 try self.base.file.?.pwriteAll(self.strtab.items, strtab_shdr.sh_offset);
51865221}
51875222
5188fn writeSymtabZigObject(self: *Elf, zig_object: *ZigObject) !void {
5189 const gpa = self.base.allocator;
5190 const symtab_shdr = self.shdrs.items[self.symtab_section_index.?];
5191 const strtab_shdr = self.shdrs.items[self.strtab_section_index.?];
5192 const sym_size: u64 = switch (self.ptr_width) {
5193 .p32 => @sizeOf(elf.Elf32_Sym),
5194 .p64 => @sizeOf(elf.Elf64_Sym),
5195 };
5196 const nsyms = math.cast(usize, @divExact(symtab_shdr.sh_size, sym_size)) orelse return error.Overflow;
5197
5198 log.debug("writing {d} symbols at 0x{x}", .{ nsyms, symtab_shdr.sh_offset });
5199
5200 try self.symtab.resize(gpa, nsyms);
5201 const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow;
5202 try self.strtab.ensureUnusedCapacity(gpa, needed_strtab_size);
5203
5204 self.writeSectionSymbols();
5205 zig_object.asFile().writeSymtab(self);
5206
5207 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();
5208 switch (self.ptr_width) {
5209 .p32 => {
5210 const buf = try gpa.alloc(elf.Elf32_Sym, self.symtab.items.len);
5211 defer gpa.free(buf);
5212
5213 for (buf, self.symtab.items) |*out, sym| {
5214 out.* = .{
5215 .st_name = sym.st_name,
5216 .st_info = sym.st_info,
5217 .st_other = sym.st_other,
5218 .st_shndx = sym.st_shndx,
5219 .st_value = @as(u32, @intCast(sym.st_value)),
5220 .st_size = @as(u32, @intCast(sym.st_size)),
5221 };
5222 if (foreign_endian) mem.byteSwapAllFields(elf.Elf32_Sym, out);
5223 }
5224 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), symtab_shdr.sh_offset);
5225 },
5226 .p64 => {
5227 if (foreign_endian) {
5228 for (self.symtab.items) |*sym| mem.byteSwapAllFields(elf.Elf64_Sym, sym);
5229 }
5230 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.symtab.items), symtab_shdr.sh_offset);
5231 },
5232 }
5233
5234 try self.base.file.?.pwriteAll(self.strtab.items, strtab_shdr.sh_offset);
5235}
5236
52375223fn writeSectionSymbols(self: *Elf) void {
52385224 var ilocal: u32 = 1;
52395225 for (self.output_sections.keys()) |shndx| {
src/link/Elf/synthetic_sections.zig+3-3
......@@ -1527,7 +1527,7 @@ pub const ComdatGroupSection = struct {
15271527 const cg = elf_file.comdatGroup(cgs.cg_index);
15281528 const object = cgs.file(elf_file).?.object;
15291529 const members = object.comdatGroupMembers(cg.shndx);
1530 try writeInt(@as(u32, elf.GRP_COMDAT), elf_file, writer);
1530 try writer.writeInt(u32, elf.GRP_COMDAT, .little);
15311531 for (members) |shndx| {
15321532 const shdr = object.shdrs.items[shndx];
15331533 switch (shdr.sh_type) {
......@@ -1535,12 +1535,12 @@ pub const ComdatGroupSection = struct {
15351535 const atom_index = object.atoms.items[shdr.sh_info];
15361536 const atom = elf_file.atom(atom_index).?;
15371537 const rela = elf_file.output_rela_sections.get(atom.outputShndx().?).?;
1538 try writeInt(rela.shndx, elf_file, writer);
1538 try writer.writeInt(u32, rela.shndx, .little);
15391539 },
15401540 else => {
15411541 const atom_index = object.atoms.items[shndx];
15421542 const atom = elf_file.atom(atom_index).?;
1543 try writeInt(atom.outputShndx().?, elf_file, writer);
1543 try writer.writeInt(u32, atom.outputShndx().?, .little);
15441544 },
15451545 }
15461546 }