Attempt to fix ubsan.
authorRui Ueyama <ruiu@google.com>
Tue, 9 Oct 2018 21:41:53 +0000 (21:41 +0000)
committerRui Ueyama <ruiu@google.com>
Tue, 9 Oct 2018 21:41:53 +0000 (21:41 +0000)
Previously, we cast a pointer to Elf{32,64}_Chdr like this

  auto *Hdr = reinterpret_cast<const ELF64_Chdr>(Ptr);

and read from its members like this

  read32(&Hdr->ch_size);

I was thinking that this does not violate alignment requirement,
since &Hdr->ch_size doesn't really access memory, but seems like
it is a violation in terms of C++ spec (?)

In this patch, I use a different struct that allows unaligned access.

llvm-svn: 344083

lld/ELF/InputSection.cpp

index 605d55b..9da4af6 100644 (file)
@@ -206,6 +206,9 @@ OutputSection *SectionBase::getOutputSection() {
 // by zlib-compressed data. This function parses a header to initialize
 // `UncompressedSize` member and remove the header from `RawData`.
 void InputSectionBase::parseCompressedHeader() {
+  typedef typename ELF64LE::Chdr Chdr64;
+  typedef typename ELF32LE::Chdr Chdr32;
+
   // Old-style header
   if (Name.startswith(".zdebug")) {
     if (!toStringRef(RawData).startswith("ZLIB")) {
@@ -233,35 +236,35 @@ void InputSectionBase::parseCompressedHeader() {
 
   // New-style 64-bit header
   if (Config->Is64) {
-    if (RawData.size() < sizeof(Elf64_Chdr)) {
+    if (RawData.size() < sizeof(Chdr64)) {
       error(toString(this) + ": corrupted compressed section");
       return;
     }
 
-    auto *Hdr = reinterpret_cast<const Elf64_Chdr *>(RawData.data());
-    if (read32(&Hdr->ch_type) != ELFCOMPRESS_ZLIB) {
+    auto *Hdr = reinterpret_cast<const Chdr64 *>(RawData.data());
+    if (Hdr->ch_type != ELFCOMPRESS_ZLIB) {
       error(toString(this) + ": unsupported compression type");
       return;
     }
 
-    UncompressedSize = read64(&Hdr->ch_size);
+    UncompressedSize = Hdr->ch_size;
     RawData = RawData.slice(sizeof(*Hdr));
     return;
   }
 
   // New-style 32-bit header
-  if (RawData.size() < sizeof(Elf32_Chdr)) {
+  if (RawData.size() < sizeof(Chdr32)) {
     error(toString(this) + ": corrupted compressed section");
     return;
   }
 
-  auto *Hdr = reinterpret_cast<const Elf32_Chdr *>(RawData.data());
-  if (read32(&Hdr->ch_type) != ELFCOMPRESS_ZLIB) {
+  auto *Hdr = reinterpret_cast<const Chdr32 *>(RawData.data());
+  if (Hdr->ch_type != ELFCOMPRESS_ZLIB) {
     error(toString(this) + ": unsupported compression type");
     return;
   }
 
-  UncompressedSize = read32(&Hdr->ch_size);
+  UncompressedSize = Hdr->ch_size;
   RawData = RawData.slice(sizeof(*Hdr));
 }