[LLD][COFF] Fix out-of-bounds write when filling gaps with INT3 in code sections (#180411)
When merging `.bss` into a code section (e.g., `/MERGE:.bss=.text`), the INT3 gap-filling loop in `writeSections()` would write past the output buffer. This happens because `.bss` chunks have `hasData=false`, so they contribute to `VirtualSize` but not `SizeOfRawData`. The loop was using chunk RVAs without checking if they exceeded the raw data region. This caused a crash on Windows with `/FILEALIGN:1` (access violation 0xC0000005). The tight alignment leaves no slack in the mapped buffer, so the overflow immediately hits unmapped memory. The fix bounds all memset operations to `rawSize` and exits early when encountering chunks beyond the raw data boundary. Fixes #180406
This commit is contained in:
parent
b46d6dcac1
commit
6558595ca3
@ -2619,12 +2619,17 @@ void Writer::writeSections() {
|
||||
if ((sec->header.Characteristics & IMAGE_SCN_CNT_CODE) &&
|
||||
(ctx.config.machine == AMD64 || ctx.config.machine == I386)) {
|
||||
uint32_t prevEnd = 0;
|
||||
uint32_t rawSize = sec->getRawSize();
|
||||
for (Chunk *c : sec->chunks) {
|
||||
uint32_t off = c->getRVA() - sec->getRVA();
|
||||
// Chunks without data (e.g., .bss) have virtual addresses beyond
|
||||
// rawSize; stop filling when we reach the end of raw data.
|
||||
if (off >= rawSize)
|
||||
break;
|
||||
memset(secBuf + prevEnd, 0xCC, off - prevEnd);
|
||||
prevEnd = off + c->getSize();
|
||||
prevEnd = std::min(off + static_cast<uint32_t>(c->getSize()), rawSize);
|
||||
}
|
||||
memset(secBuf + prevEnd, 0xCC, sec->getRawSize() - prevEnd);
|
||||
memset(secBuf + prevEnd, 0xCC, rawSize - prevEnd);
|
||||
}
|
||||
|
||||
parallelForEach(sec->chunks, [&](Chunk *c) {
|
||||
|
||||
60
lld/test/COFF/merge-bss-text-filealign1.test
Normal file
60
lld/test/COFF/merge-bss-text-filealign1.test
Normal file
@ -0,0 +1,60 @@
|
||||
# REQUIRES: x86
|
||||
# Test that merging .bss into .text with /FILEALIGN:1 doesn't crash.
|
||||
#
|
||||
# RUN: yaml2obj %s -o %t.obj
|
||||
# RUN: lld-link /out:%t.exe /entry:main /subsystem:console \
|
||||
# RUN: /merge:.bss=.text /filealign:1 %t.obj
|
||||
# RUN: llvm-readobj --sections %t.exe | FileCheck %s
|
||||
|
||||
# CHECK: Name: .text
|
||||
# CHECK-NEXT: VirtualSize: 0x104
|
||||
# CHECK: RawDataSize:
|
||||
# CHECK-NOT: Name: .bss
|
||||
|
||||
--- !COFF
|
||||
header:
|
||||
Machine: IMAGE_FILE_MACHINE_AMD64
|
||||
Characteristics: [ ]
|
||||
sections:
|
||||
- Name: .text
|
||||
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 4
|
||||
SectionData: 'C3'
|
||||
SizeOfRawData: 1
|
||||
- Name: .bss
|
||||
Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
|
||||
Alignment: 4
|
||||
SectionData: ''
|
||||
SizeOfRawData: 256
|
||||
symbols:
|
||||
- Name: .text
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 1
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 1
|
||||
- Name: .bss
|
||||
Value: 0
|
||||
SectionNumber: 2
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 256
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 2
|
||||
- Name: main
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
...
|
||||
Loading…
x
Reference in New Issue
Block a user