[lld] Fix undefined behavior with misaligned SHT_GROUP section. (#180848)

read32() allows misaligned values, but a `uint32_t &` must be properly
aligned even if it isn't directly read. ubsan detects this. To fix the
issue, replace the `uint32_t &` with a value that doesn't require
alignment.

Also added an assertion to catch similar misuse of getDataAs().

(Alternatively, we could make the input validation more strict, and
reject files with a misaligned SHT_GROUP, but I don't see any obvious
reason to require that.)
This commit is contained in:
Eli Friedman 2026-02-12 14:07:57 -08:00 committed by GitHub
parent a00278632d
commit b7e1922ca1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 4 additions and 2 deletions

View File

@ -299,6 +299,7 @@ public:
template <typename T> llvm::ArrayRef<T> getDataAs() const {
size_t s = content().size();
assert(s % sizeof(T) == 0);
assert(reinterpret_cast<uintptr_t>(content().data()) % alignof(T) == 0);
return llvm::ArrayRef<T>((const T *)content().data(), s / sizeof(T));
}

View File

@ -625,7 +625,7 @@ static void finalizeShtGroup(Ctx &ctx, OutputSection *os,
// new size. The content will be rewritten in InputSection::copyShtGroup.
DenseSet<uint32_t> seen;
ArrayRef<InputSectionBase *> sections = section->file->getSections();
for (const uint32_t &idx : section->getDataAs<uint32_t>().slice(1))
for (auto &idx : section->getDataAs<std::array<char, 4>>().slice(1))
if (OutputSection *osec = sections[read32(ctx, &idx)]->getOutputSection())
seen.insert(osec->sectionIndex);
os->size = (1 + seen.size()) * sizeof(uint32_t);

View File

@ -31,7 +31,8 @@ Sections:
Type: SHT_GROUP
Link: .symtab
Info: foo
AddressAlign: 4
## Intentionally misaligned to check that lld works with unaligned SHT_GROUP
AddressAlign: 1
Members:
- SectionOrType: GRP_COMDAT
- SectionOrType: .bss