authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-13 23:40:30-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-23 00:27:18-04:00
logc9601664c6914a8bdbf778f494a0a4fe6d84fa53
tree5fdb2bf3bad6e0492fc310f63200dc26e6c7208a
parente2c587ae54cba1d2b13b5cbef8530e13fab04c7f

Coff: fix use of stale header pointer (due to node resize) in addRelocAssumeCapacity

MappedFile: add check to prevent INVAL from fallocate() when realigning nodes that are not aligned to the block size

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

src/link/Coff.zig+29-25
......@@ -3730,33 +3730,37 @@ fn addRelocAssumeCapacity(
37303730 break :sti .none;
37313731 } else .none;
37323732
3733 const section = loc_sn.section(coff);
3734 const header = loc_sn.header(coff);
3735 const old_num_relocations = coff.targetLoad(&header.number_of_relocations);
3736 const new_num_relocations = old_num_relocations + 1;
3737 const new_size = new_num_relocations * std.coff.Relocation.sizeOf();
3738 if (section.relocation_table_ni == .none) {
3739 section.relocation_table_ni = try coff.mf.addLastChildNode(
3740 gpa,
3741 coff.sectionParent(),
3742 .{
3743 .size = new_size,
3744 .alignment = .@"2",
3745 .moved = true,
3746 .resized = true,
3747 },
3748 );
3749 coff.nodes.appendAssumeCapacity(.{ .relocation_table = loc_sn });
3750 } else {
3751 try section.relocation_table_ni.resize(&coff.mf, gpa, new_size);
3752 }
3733 const sri: Section.RelocationIndex = blk: {
3734 const section = loc_sn.section(coff);
3735 const header = loc_sn.header(coff);
3736 const old_num_relocations = coff.targetLoad(&header.number_of_relocations);
3737 const new_num_relocations = old_num_relocations + 1;
3738 const new_size = new_num_relocations * std.coff.Relocation.sizeOf();
3739
3740 coff.targetStore(&header.number_of_relocations, new_num_relocations);
3741 if (coff.symbolTableSectionAuxEntryPtr(loc_sn.symbol(coff).sti(coff))) |aux_ptr|
3742 coff.targetStore(&aux_ptr.number_of_relocations, new_num_relocations);
3743
3744 if (section.relocation_table_ni == .none) {
3745 section.relocation_table_ni = try coff.mf.addLastChildNode(
3746 gpa,
3747 coff.sectionParent(),
3748 .{
3749 .size = new_size,
3750 .alignment = .@"2",
3751 .moved = true,
3752 .resized = true,
3753 },
3754 );
3755 coff.nodes.appendAssumeCapacity(.{ .relocation_table = loc_sn });
3756 } else {
3757 try section.relocation_table_ni.resize(&coff.mf, gpa, new_size);
3758 }
37533759
3754 coff.targetStore(&header.number_of_relocations, new_num_relocations);
3755 if (coff.symbolTableSectionAuxEntryPtr(loc_sn.symbol(coff).sti(coff))) |aux_ptr|
3756 coff.targetStore(&aux_ptr.number_of_relocations, new_num_relocations);
3760 // TODO: These need to allocate from a free list, once deleting relocs from the table is supported
3761 break :blk .wrap(old_num_relocations);
3762 };
37573763
3758 // TODO: These need to allocate from a free list, once deleting relocs is supported
3759 const sri: Section.RelocationIndex = .wrap(old_num_relocations);
37603764 const entry = sri.entry(coff, loc_sn).?;
37613765 if (sti.unwrap()) |index| coff.targetStore(&entry.symbol_table_index, index);
37623766
src/link/MappedFile.zig+11-4
......@@ -799,6 +799,17 @@ fn resizeNode(
799799 if (is_linux and !mf.flags.fallocate_insert_range_unsupported and
800800 node.flags.alignment.order(mf.flags.block_size).compare(.gte))
801801 insert_range: {
802 const range_file_offset = ni.fileLocation(mf, false).offset + old_size;
803 const range_size = node.flags.alignment.forward(
804 @intCast(requested_size +| requested_size / growth_factor),
805 ) - old_size;
806
807 // If this node is being realigned, its current state might not
808 // meet the requirements for fallocate
809 if (!mf.flags.block_size.check(@intCast(range_file_offset)) or
810 !mf.flags.block_size.check(@intCast(range_size)))
811 break :insert_range;
812
802813 mf.memory_map.write(io) catch |err| switch (err) {
803814 error.WouldBlock => return error.Unexpected, // file was not opened as non-blocking
804815 error.NotOpenForWriting => return error.Unexpected, // we definitely opened the file for writing
......@@ -808,10 +819,6 @@ fn resizeNode(
808819 const last_offset, const last_size = parent.last.location(mf).resolve(mf);
809820 const last_end = last_offset + last_size;
810821 assert(last_end <= old_parent_size);
811 const range_file_offset = ni.fileLocation(mf, false).offset + old_size;
812 const range_size = node.flags.alignment.forward(
813 @intCast(requested_size +| requested_size / growth_factor),
814 ) - old_size;
815822 _, const file_size = Node.Index.root.location(mf).resolve(mf);
816823 while (true) switch (linux.errno(switch (std.math.order(range_file_offset, file_size)) {
817824 .lt => linux.fallocate(