[PATCH] D25279: [ELF] - Do not crash on large output.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 7 04:11:28 PDT 2016


grimar updated this revision to Diff 73908.
grimar added a comment.

- Restored testcase missing in latest diff.
- Improved error diagnostic messages.


https://reviews.llvm.org/D25279

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: checked type operation overflow
Index: ELF/Writer.cpp
===================================================================
--- ELF/Writer.cpp
+++ ELF/Writer.cpp
@@ -1162,6 +1162,40 @@
   }
 }
 
+template <class T> class CheckedType {
+  T Val;
+  StringRef Err;
+
+public:
+  CheckedType(T Val, StringRef Err) : Val(Val), Err(Err){};
+
+  operator uint64_t() { return Val; }
+  operator uint32_t() {
+    if (Val > UINT32_MAX)
+      fatal(Err + "checked type operation overflow");
+    return Val;
+  }
+
+  template <class T2> CheckedType operator+(T2 R) {
+    if (R > getMax() || (this->Val > getMax() - R))
+      fatal(Err + "checked type operation overflow");
+    return {this->Val + R, Err};
+  }
+
+  template <class T2> CheckedType operator-(T2 R) {
+    if (R > this->Val)
+      fatal(Err + "checked type operation overflow");
+    return {this->Val - R, Err};
+  }
+
+private:
+  T getMax() { return std::numeric_limits<typename T>::max(); }
+};
+
+template <class T> CheckedType<T> makeChecked(T Val, StringRef S) {
+  return CheckedType<T>(Val, S);
+}
+
 // 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
@@ -1182,7 +1216,8 @@
   // this formula: Off2 = Off1 + (VA2 - VA1).
   if (Sec == First)
     return alignTo(Off, Target->MaxPageSize, Sec->getVA());
-  return First->getFileOffset() + Sec->getVA() - First->getVA();
+  return makeChecked(First->getFileOffset(), "getFileAlignment failed: ") +
+         Sec->getVA() - First->getVA();
 }
 
 template <class ELFT, class uintX_t>
@@ -1194,7 +1229,7 @@
 
   Off = getFileAlignment<ELFT>(Off, Sec);
   Sec->setFileOffset(Off);
-  Off += Sec->getSize();
+  Off = makeChecked(Off, "setOffset failed: ") + Sec->getSize();
 }
 
 template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D25279.73908.patch
Type: text/x-patch
Size: 2473 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20161007/ec522855/attachment.bin>


More information about the llvm-commits mailing list