zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit c9601664c6914a8bdbf778f494a0a4fe6d84fa53 (tree)
parent e2c587ae54cba1d2b13b5cbef8530e13fab04c7f
Author: kcbanner <kcbanner@gmail.com>
Date:   Sat, 13 Jun 2026 23:40:30 -0400

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

Diffstat:
Msrc/link/Coff.zig | 54+++++++++++++++++++++++++++++-------------------------
Msrc/link/MappedFile.zig | 15+++++++++++----
2 files changed, 40 insertions(+), 29 deletions(-)

diff --git a/src/link/Coff.zig b/src/link/Coff.zig @@ -3730,33 +3730,37 @@ fn addRelocAssumeCapacity( break :sti .none; } else .none; - const section = loc_sn.section(coff); - const header = loc_sn.header(coff); - const old_num_relocations = coff.targetLoad(&header.number_of_relocations); - const new_num_relocations = old_num_relocations + 1; - const new_size = new_num_relocations * std.coff.Relocation.sizeOf(); - if (section.relocation_table_ni == .none) { - section.relocation_table_ni = try coff.mf.addLastChildNode( - gpa, - coff.sectionParent(), - .{ - .size = new_size, - .alignment = .@"2", - .moved = true, - .resized = true, - }, - ); - coff.nodes.appendAssumeCapacity(.{ .relocation_table = loc_sn }); - } else { - try section.relocation_table_ni.resize(&coff.mf, gpa, new_size); - } + const sri: Section.RelocationIndex = blk: { + const section = loc_sn.section(coff); + const header = loc_sn.header(coff); + const old_num_relocations = coff.targetLoad(&header.number_of_relocations); + const new_num_relocations = old_num_relocations + 1; + const new_size = new_num_relocations * std.coff.Relocation.sizeOf(); + + coff.targetStore(&header.number_of_relocations, new_num_relocations); + if (coff.symbolTableSectionAuxEntryPtr(loc_sn.symbol(coff).sti(coff))) |aux_ptr| + coff.targetStore(&aux_ptr.number_of_relocations, new_num_relocations); + + if (section.relocation_table_ni == .none) { + section.relocation_table_ni = try coff.mf.addLastChildNode( + gpa, + coff.sectionParent(), + .{ + .size = new_size, + .alignment = .@"2", + .moved = true, + .resized = true, + }, + ); + coff.nodes.appendAssumeCapacity(.{ .relocation_table = loc_sn }); + } else { + try section.relocation_table_ni.resize(&coff.mf, gpa, new_size); + } - coff.targetStore(&header.number_of_relocations, new_num_relocations); - if (coff.symbolTableSectionAuxEntryPtr(loc_sn.symbol(coff).sti(coff))) |aux_ptr| - coff.targetStore(&aux_ptr.number_of_relocations, new_num_relocations); + // TODO: These need to allocate from a free list, once deleting relocs from the table is supported + break :blk .wrap(old_num_relocations); + }; - // TODO: These need to allocate from a free list, once deleting relocs is supported - const sri: Section.RelocationIndex = .wrap(old_num_relocations); const entry = sri.entry(coff, loc_sn).?; if (sti.unwrap()) |index| coff.targetStore(&entry.symbol_table_index, index); diff --git a/src/link/MappedFile.zig b/src/link/MappedFile.zig @@ -799,6 +799,17 @@ fn resizeNode( if (is_linux and !mf.flags.fallocate_insert_range_unsupported and node.flags.alignment.order(mf.flags.block_size).compare(.gte)) insert_range: { + const range_file_offset = ni.fileLocation(mf, false).offset + old_size; + const range_size = node.flags.alignment.forward( + @intCast(requested_size +| requested_size / growth_factor), + ) - old_size; + + // If this node is being realigned, its current state might not + // meet the requirements for fallocate + if (!mf.flags.block_size.check(@intCast(range_file_offset)) or + !mf.flags.block_size.check(@intCast(range_size))) + break :insert_range; + mf.memory_map.write(io) catch |err| switch (err) { error.WouldBlock => return error.Unexpected, // file was not opened as non-blocking error.NotOpenForWriting => return error.Unexpected, // we definitely opened the file for writing @@ -808,10 +819,6 @@ fn resizeNode( const last_offset, const last_size = parent.last.location(mf).resolve(mf); const last_end = last_offset + last_size; assert(last_end <= old_parent_size); - const range_file_offset = ni.fileLocation(mf, false).offset + old_size; - const range_size = node.flags.alignment.forward( - @intCast(requested_size +| requested_size / growth_factor), - ) - old_size; _, const file_size = Node.Index.root.location(mf).resolve(mf); while (true) switch (linux.errno(switch (std.math.order(range_file_offset, file_size)) { .lt => linux.fallocate(