[PATCH] D25467: [ELF] - Alternative fix to prevent possible crash on large output.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 11 04:30:05 PDT 2016


grimar created this revision.
grimar added reviewers: ruiu, rafael, davide.
grimar added subscribers: llvm-commits, grimar, evgeny777.

This is alternative solution for https://reviews.llvm.org/D25279.

Initial problem was that because of overflow in calculations wierd thinks could happen.
Most heavy is a crash in writeTo because of overflow in FileSize calculation.

This patch does not introduce new class and uses 2 check-methods.


https://reviews.llvm.org/D25467

Files:
  ELF/Writer.cpp
  test/ELF/invalid/Inputs/too-large-output-i386.elf
  test/ELF/invalid/too-large-output-i386.s


Index: test/ELF/invalid/too-large-output-i386.s
===================================================================
--- test/ELF/invalid/too-large-output-i386.s
+++ test/ELF/invalid/too-large-output-i386.s
@@ -0,0 +1,7 @@
+# REQUIRES: x86
+
+## too-large-output-i386.elf contains section with address align.
+## of 0xFFFFFFFF. Total file size calculation overflows because of that.
+# RUN: not ld.lld -shared %S/Inputs/too-large-output-i386.elf -o %t 2>&1 \
+# RUN:  | FileCheck %s
+# CHECK: getFileAlignment failed: operation overflow
Index: ELF/Writer.cpp
===================================================================
--- ELF/Writer.cpp
+++ ELF/Writer.cpp
@@ -1174,6 +1174,22 @@
   }
 }
 
+template <class T1, class T2>
+static T1 checkedAdd(T1 Val1, T2 Val2, StringRef Msg) {
+  const T1 Max = std::numeric_limits<T1>::max();
+  if (Val2 > Max || Val1 > Max - Val2)
+    fatal(Msg);
+  return Val1 + Val2;
+}
+
+template <class T>
+static T checkedAlignTo(T Value, uint64_t Align, uint64_t Skew, StringRef Msg) {
+  const T Ret = alignTo(Value, Align, Skew);
+  if (Ret < Value)
+    fatal(Msg);
+  return Ret;
+}
+
 // Adjusts the file alignment for a given output section and returns
 // its new file offset. The file offset must be the same with its
 // virtual address (modulo the page size) so that the loader can load
@@ -1183,7 +1199,8 @@
   uintX_t Alignment = Sec->getAlignment();
   if (Sec->PageAlign)
     Alignment = std::max<uintX_t>(Alignment, Config->MaxPageSize);
-  Off = alignTo(Off, Alignment);
+  Off = checkedAlignTo(Off, Alignment, 0,
+                       "getFileAlignment failed: operation overflow");
 
   OutputSectionBase<ELFT> *First = Sec->FirstInPtLoad;
   // If the section is not in a PT_LOAD, we have no other constraint.
@@ -1193,8 +1210,10 @@
   // If two sections share the same PT_LOAD the file offset is calculated using
   // this formula: Off2 = Off1 + (VA2 - VA1).
   if (Sec == First)
-    return alignTo(Off, Target->MaxPageSize, Sec->getVA());
-  return First->getFileOffset() + Sec->getVA() - First->getVA();
+    return checkedAlignTo(Off, Target->MaxPageSize, Sec->getVA(),
+                          "getFileAlignment failed: operation overflow");
+  return checkedAdd(First->getFileOffset(), Sec->getVA() - First->getVA(),
+                    "getFileAlignment failed: operation overflow");
 }
 
 template <class ELFT, class uintX_t>
@@ -1206,7 +1225,7 @@
 
   Off = getFileAlignment<ELFT>(Off, Sec);
   Sec->setFileOffset(Off);
-  Off += Sec->getSize();
+  Off = checkedAdd(Off, Sec->getSize(), "setOffset failed: operation overflow");
 }
 
 template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D25467.74233.patch
Type: text/x-patch
Size: 2675 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20161011/991db232/attachment.bin>


More information about the llvm-commits mailing list