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 {...@@ -4797,7 +4797,11 @@ fn writeAtomsObject(self: *Elf) !void {
4797 return error.Overflow;4797 return error.Overflow;
4798 const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;4798 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
4802 // TODO decompress directly into provided buffer4806 // TODO decompress directly into provided buffer
4803 const out_code = buffer[offset..][0..size];4807 const out_code = buffer[offset..][0..size];
...@@ -5048,6 +5052,7 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {...@@ -5048,6 +5052,7 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {
5048 if (!atom_ptr.flags.alive) continue;5052 if (!atom_ptr.flags.alive) continue;
5049 try atom_ptr.writeRelocs(self, &relocs);5053 try atom_ptr.writeRelocs(self, &relocs);
5050 }5054 }
5055 assert(relocs.items.len == num_relocs);
50515056
5052 const SortRelocs = struct {5057 const SortRelocs = struct {
5053 pub fn lessThan(ctx: void, lhs: elf.Elf64_Rela, rhs: elf.Elf64_Rela) bool {5058 pub fn lessThan(ctx: void, lhs: elf.Elf64_Rela, rhs: elf.Elf64_Rela) bool {
...@@ -5058,6 +5063,12 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {...@@ -5058,6 +5063,12 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {
50585063
5059 mem.sort(elf.Elf64_Rela, relocs.items, {}, SortRelocs.lessThan);5064 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
5061 try self.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), shdr.sh_offset);5072 try self.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), shdr.sh_offset);
5062 }5073 }
50635074
...@@ -5067,6 +5078,11 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {...@@ -5067,6 +5078,11 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {
5067 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);5078 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
5068 defer buffer.deinit();5079 defer buffer.deinit();
5069 try eh_frame.writeEhFrameObject(self, buffer.writer());5080 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);
5070 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);5086 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
5071 }5087 }
5072 if (self.eh_frame_rela_section_index) |shndx| {5088 if (self.eh_frame_rela_section_index) |shndx| {
...@@ -5075,6 +5091,11 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {...@@ -5075,6 +5091,11 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {
5075 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);5091 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
5076 defer buffer.deinit();5092 defer buffer.deinit();
5077 try eh_frame.writeEhFrameRelocs(self, buffer.writer());5093 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 });
5078 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);5099 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
5079 }5100 }
50805101
...@@ -5091,6 +5112,11 @@ fn writeComdatGroups(self: *Elf) !void {...@@ -5091,6 +5112,11 @@ fn writeComdatGroups(self: *Elf) !void {
5091 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);5112 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
5092 defer buffer.deinit();5113 defer buffer.deinit();
5093 try cgs.write(self, buffer.writer());5114 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 });
5094 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);5120 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
5095 }5121 }
5096}5122}
...@@ -5098,6 +5124,7 @@ fn writeComdatGroups(self: *Elf) !void {...@@ -5098,6 +5124,7 @@ fn writeComdatGroups(self: *Elf) !void {
5098fn writeShStrtab(self: *Elf) !void {5124fn writeShStrtab(self: *Elf) !void {
5099 if (self.shstrtab_section_index) |index| {5125 if (self.shstrtab_section_index) |index| {
5100 const shdr = self.shdrs.items[index];5126 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 });
5101 try self.base.file.?.pwriteAll(self.shstrtab.items, shdr.sh_offset);5128 try self.base.file.?.pwriteAll(self.shstrtab.items, shdr.sh_offset);
5102 }5129 }
5103}5130}
...@@ -5112,7 +5139,15 @@ fn writeSymtab(self: *Elf) !void {...@@ -5112,7 +5139,15 @@ fn writeSymtab(self: *Elf) !void {
5112 };5139 };
5113 const nsyms = math.cast(usize, @divExact(symtab_shdr.sh_size, sym_size)) orelse return error.Overflow;5140 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
5117 try self.symtab.resize(gpa, nsyms);5152 try self.symtab.resize(gpa, nsyms);
5118 const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow;5153 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 {...@@ -5185,55 +5220,6 @@ fn writeSymtab(self: *Elf) !void {
5185 try self.base.file.?.pwriteAll(self.strtab.items, strtab_shdr.sh_offset);5220 try self.base.file.?.pwriteAll(self.strtab.items, strtab_shdr.sh_offset);
5186}5221}
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
5237fn writeSectionSymbols(self: *Elf) void {5223fn writeSectionSymbols(self: *Elf) void {
5238 var ilocal: u32 = 1;5224 var ilocal: u32 = 1;
5239 for (self.output_sections.keys()) |shndx| {5225 for (self.output_sections.keys()) |shndx| {
src/link/Elf/synthetic_sections.zig+3-3
...@@ -1527,7 +1527,7 @@ pub const ComdatGroupSection = struct {...@@ -1527,7 +1527,7 @@ pub const ComdatGroupSection = struct {
1527 const cg = elf_file.comdatGroup(cgs.cg_index);1527 const cg = elf_file.comdatGroup(cgs.cg_index);
1528 const object = cgs.file(elf_file).?.object;1528 const object = cgs.file(elf_file).?.object;
1529 const members = object.comdatGroupMembers(cg.shndx);1529 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);
1531 for (members) |shndx| {1531 for (members) |shndx| {
1532 const shdr = object.shdrs.items[shndx];1532 const shdr = object.shdrs.items[shndx];
1533 switch (shdr.sh_type) {1533 switch (shdr.sh_type) {
...@@ -1535,12 +1535,12 @@ pub const ComdatGroupSection = struct {...@@ -1535,12 +1535,12 @@ pub const ComdatGroupSection = struct {
1535 const atom_index = object.atoms.items[shdr.sh_info];1535 const atom_index = object.atoms.items[shdr.sh_info];
1536 const atom = elf_file.atom(atom_index).?;1536 const atom = elf_file.atom(atom_index).?;
1537 const rela = elf_file.output_rela_sections.get(atom.outputShndx().?).?;1537 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);
1539 },1539 },
1540 else => {1540 else => {
1541 const atom_index = object.atoms.items[shndx];1541 const atom_index = object.atoms.items[shndx];
1542 const atom = elf_file.atom(atom_index).?;1542 const atom = elf_file.atom(atom_index).?;
1543 try writeInt(atom.outputShndx().?, elf_file, writer);1543 try writer.writeInt(u32, atom.outputShndx().?, .little);
1544 },1544 },
1545 }1545 }
1546 }1546 }