Merge pull request #1238 from hashaam1217/fix/windows-overlapping-load-segments

fix(relinker): reject overlapping PT_LOAD segments before sizing the Windows image
This commit is contained in:
Adrià 2026-10-08 11:14:58 +02:00 committed by GitHub
commit 296d68a31d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 16 additions and 5 deletions

View File

@ -28,15 +28,16 @@ WindowsLoadImage::WindowsLoadImage(const std::vector<std::uint8_t>& source, cons
throw Domain::RelinkerException("No PT_LOAD segments found");
std::sort(segments.begin(), segments.end(), [](const auto& left, const auto& right) { return left.MappedAddress < right.MappedAddress; });
firstAddress = segments.front().MappedAddress & ~static_cast<std::uint64_t>(SectionAlignment - 1);
const auto end = segments.back().MappedAddress + segments.back().MemorySize;
std::uint64_t end = firstAddress;
for (const auto& segment : segments) {
if (segment.MappedAddress < end)
throw Domain::RelinkerException("Overlapping PT_LOAD memory ranges", segment.MappedAddress);
end = segment.MappedAddress + segment.MemorySize;
}
data.resize(AlignRva(end - firstAddress));
CheckedRva(LoadRva + static_cast<std::uint64_t>(data.size()));
pageFlags.resize(data.size() / SectionAlignment);
std::uint64_t previousEnd = firstAddress;
for (const auto& segment : segments) {
if (segment.MappedAddress < previousEnd)
throw Domain::RelinkerException("Overlapping PT_LOAD memory ranges", segment.MappedAddress);
previousEnd = segment.MappedAddress + segment.MemorySize;
const auto offset = static_cast<std::size_t>(segment.MappedAddress - firstAddress);
std::copy_n(source.begin() + static_cast<std::ptrdiff_t>(segment.Offset), static_cast<std::size_t>(segment.FileSize), data.begin() + static_cast<std::ptrdiff_t>(offset));
std::uint32_t flags = 0;

View File

@ -77,6 +77,16 @@ def main():
result, output = run_case(relinker, work, "strict", ["unused-filter=2"], b"\x90\xc3")
assert result.returncode == 2 and "multiple executable segments" in result.stderr and not output.exists(), result
for name, memory_size in (("overlap-past-end", 0x10000000000000), ("overlap-next", 0x1300)):
image = fixture(b"\x90\xc3")
struct.pack_into("<Q", image, 64 + 40, memory_size)
source = work / (name + ".elf")
output = work / (name + ".exe")
source.write_bytes(image)
result = subprocess.run([str(relinker), "--skip-sce-module", "--windows", str(source), str(output)],
capture_output=True, text=True, timeout=20)
assert result.returncode == 2 and "Overlapping PT_LOAD memory ranges" in result.stderr and not output.exists(), (name, result)
print("Executable segment tests passed")