Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1174,6 +1174,22 @@ } } +template +static T1 checkedAdd(T1 Val1, T2 Val2, StringRef Msg) { + const T1 Max = std::numeric_limits::max(); + if (Val2 > Max || Val1 > Max - Val2) + fatal(Msg); + return Val1 + Val2; +} + +template +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(Alignment, Config->MaxPageSize); - Off = alignTo(Off, Alignment); + Off = checkedAlignTo(Off, Alignment, 0, + "getFileAlignment failed: operation overflow"); OutputSectionBase *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 @@ -1206,7 +1225,7 @@ Off = getFileAlignment(Off, Sec); Sec->setFileOffset(Off); - Off += Sec->getSize(); + Off = checkedAdd(Off, Sec->getSize(), "setOffset failed: operation overflow"); } 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: getFileAlignment failed: operation overflow