Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1162,6 +1162,40 @@ } } +template 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 CheckedType operator+(T2 R) { + if (R > getMax() || (this->Val > getMax() - R)) + fatal(Err + "checked type operation overflow"); + return {this->Val + R, Err}; + } + + template 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::max(); } +}; + +template CheckedType makeChecked(T Val, StringRef S) { + return CheckedType(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 @@ -1194,7 +1229,7 @@ Off = getFileAlignment(Off, Sec); Sec->setFileOffset(Off); - Off += Sec->getSize(); + Off = makeChecked(Off, "setOffset failed: ") + Sec->getSize(); } template void Writer::assignFileOffsetsBinary() { 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