Index: llvm/test/Object/invalid.test =================================================================== --- llvm/test/Object/invalid.test +++ llvm/test/Object/invalid.test @@ -489,7 +489,7 @@ # RUN: yaml2obj %s --docnum=22 -o %t22 # RUN: llvm-readobj --dyn-relocations %t22 2>&1 | FileCheck -DFILE=%t22 --check-prefix=DYN-TABLE-PHDR %s -# DYN-TABLE-PHDR: warning: '[[FILE]]': PT_DYNAMIC segment offset + size exceeds the size of the file +# DYN-TABLE-PHDR: warning: '[[FILE]]': PT_DYNAMIC segment offset (0xffff0000) + file size (0x0) exceeds the size of the file (0x150) --- !ELF FileHeader: @@ -506,7 +506,9 @@ # RUN: yaml2obj %s --docnum=23 -o %t23 # RUN: llvm-readobj --dyn-relocations %t23 2>&1 \ -# RUN: | FileCheck -DFILE=%t23 --check-prefix=DYN-TABLE-PHDR %s +# RUN: | FileCheck -DFILE=%t23 --check-prefix=DYN-TABLE-PHDR2 %s + +# DYN-TABLE-PHDR2: warning: '[[FILE]]': PT_DYNAMIC segment offset (0x78) + file size (0xffff0000) exceeds the size of the file (0x1a8) --- !ELF FileHeader: Index: llvm/test/tools/llvm-readobj/ELF/malformed-pt-dynamic.test =================================================================== --- llvm/test/tools/llvm-readobj/ELF/malformed-pt-dynamic.test +++ llvm/test/tools/llvm-readobj/ELF/malformed-pt-dynamic.test @@ -1,47 +1,69 @@ -# If the offset and/or size fields of the PT_DYNAMIC field become corrupted, -# we should report a sensible message. +## If the offset and/or size fields of the PT_DYNAMIC field become corrupted, +## we should report a sensible message. -# Creating such a malformed file is hard. The easiest way to simulate it is to -# truncate the file. Note that the section headers must first be stripped or -# llvm-readobj will fail to parse the file due to the section header table -# offset pointing outside the file. +## Case A: Test case where the size is too large to fit in the file, but the start is +## within the file. +# RUN: yaml2obj %s -DFILESIZE=0x119 -o %t1 +# RUN: llvm-readobj %t1 --dynamic-table 2>&1 | FileCheck -DFILE=%t1 %s --check-prefix=WARN1 +# RUN: llvm-readelf %t1 --dynamic-table 2>&1 | FileCheck -DFILE=%t1 %s --check-prefix=WARN1 -# RUN: yaml2obj %s -o %t.base -# RUN: llvm-objcopy --strip-sections %t.base %t.stripped +# WARN1: warning: '[[FILE]]': PT_DYNAMIC segment offset (0x1000) + file size (0x119) exceeds the size of the file (0x1118) -# Test case where the size is too large to fit in the file, but the start is -# within the file. -# RUN: cp %t.stripped %t.truncated1 -# RUN: %python -c "with open(r'%t.truncated1', 'r+') as f: f.truncate(0x1001)" -# RUN: llvm-readobj %t.truncated1 --dynamic-table 2>&1 | FileCheck -DFILE=%t.truncated1 %s +## Case B: Test case where the offset is too large to be in the file. +# RUN: yaml2obj %s -DOFFSET=0x1119 -o %t2 +# RUN: llvm-readobj %t2 --dynamic-table 2>&1 | FileCheck -DFILE=%t2 %s --check-prefix=WARN2 +# RUN: llvm-readelf %t2 --dynamic-table 2>&1 | FileCheck -DFILE=%t2 %s --check-prefix=WARN2 -# Test case where the offset is too large to be in the file. -# RUN: cp %t.stripped %t.truncated2 -# RUN: %python -c "with open(r'%t.truncated2', 'r+') as f: f.truncate(0xFFF)" -# RUN: llvm-readobj %t.truncated2 --dynamic-table 2>&1 | FileCheck -DFILE=%t.truncated2 %s +# WARN2: warning: '[[FILE]]': PT_DYNAMIC segment offset (0x1119) + file size (0x10) exceeds the size of the file (0x1118) -# CHECK: warning: '[[FILE]]': PT_DYNAMIC segment offset + size exceeds the size of the file +## Case C: test we report a warning when the offset + the file size of the PT_DYNAMIC is so large a +## value that it overflows the platform address size type. + +# RUN: yaml2obj %s -DOFFSET=0xffffffffffffffff -o %t3 +# RUN: llvm-readobj %t3 --dynamic-table 2>&1 | FileCheck -DFILE=%t3 %s --check-prefix=WARN3 +# RUN: llvm-readelf %t3 --dynamic-table 2>&1 | FileCheck -DFILE=%t3 %s --check-prefix=WARN3 + +# WARN3: warning: '[[FILE]]': PT_DYNAMIC segment offset (0xffffffffffffffff) + file size (0x10) exceeds the size of the file (0x1118) + +# RUN: yaml2obj %s -DFILESIZE=0xffffffffffffffff -o %t4 +# RUN: llvm-readobj %t4 --dynamic-table 2>&1 | FileCheck -DFILE=%t4 %s --check-prefix=WARN4 +# RUN: llvm-readelf %t4 --dynamic-table 2>&1 | FileCheck -DFILE=%t4 %s --check-prefix=WARN4 + +# WARN4: warning: '[[FILE]]': PT_DYNAMIC segment offset (0x1000) + file size (0xffffffffffffffff) exceeds the size of the file (0x1118) + +## Case D: the same as "Case C", but for a 32-bit object. + +# RUN: yaml2obj %s -DBITS=32 -DOFFSET=0xffffffff -o %t5 +# RUN: llvm-readobj %t5 --dynamic-table 2>&1 | FileCheck -DFILE=%t5 %s --check-prefix=WARN5 +# RUN: llvm-readelf %t5 --dynamic-table 2>&1 | FileCheck -DFILE=%t5 %s --check-prefix=WARN5 + +# WARN5: warning: '[[FILE]]': PT_DYNAMIC segment offset (0xffffffff) + file size (0x8) exceeds the size of the file (0x10ac) + +# RUN: yaml2obj %s -DBITS=32 -DFILESIZE=0xffffffff -o %t6 +# RUN: llvm-readobj %t6 --dynamic-table 2>&1 | FileCheck -DFILE=%t6 %s --check-prefix=WARN6 +# RUN: llvm-readelf %t6 --dynamic-table 2>&1 | FileCheck -DFILE=%t6 %s --check-prefix=WARN6 + +# WARN6: warning: '[[FILE]]': PT_DYNAMIC segment offset (0x1000) + file size (0xffffffff) exceeds the size of the file (0x10ac) --- !ELF FileHeader: - Class: ELFCLASS64 + Class: ELFCLASS[[BITS=64]] Data: ELFDATA2LSB Type: ET_EXEC - Machine: EM_X86_64 + Machine: EM_NONE Sections: - - Name: .dynamic - Type: SHT_DYNAMIC - Address: 0x1000 - AddressAlign: 0x1000 + - Name: .dynamic + Type: SHT_DYNAMIC + Address: 0x1000 + Offset: 0x1000 + ShOffset: [[OFFSET=]] Entries: - Tag: DT_NULL Value: 0 ProgramHeaders: - - Type: PT_LOAD - VAddr: 0x1000 - Sections: - - Section: .dynamic - - Type: PT_DYNAMIC - VAddr: 0x1000 + - Type: PT_DYNAMIC + FileSize: [[FILESIZE=]] Sections: - Section: .dynamic +SectionHeaderTable: + NoHeaders: true Index: llvm/tools/llvm-readobj/ELFDumper.cpp =================================================================== --- llvm/tools/llvm-readobj/ELFDumper.cpp +++ llvm/tools/llvm-readobj/ELFDumper.cpp @@ -1919,12 +1919,16 @@ break; } - if (DynamicPhdr && DynamicPhdr->p_offset + DynamicPhdr->p_filesz > - ObjF->getMemoryBufferRef().getBufferSize()) { - reportWarning( - createError( - "PT_DYNAMIC segment offset + size exceeds the size of the file"), - ObjF->getFileName()); + if (DynamicPhdr && ((DynamicPhdr->p_offset + DynamicPhdr->p_filesz > + ObjF->getMemoryBufferRef().getBufferSize()) || + (DynamicPhdr->p_offset + DynamicPhdr->p_filesz < + DynamicPhdr->p_offset))) { + reportUniqueWarning(createError( + "PT_DYNAMIC segment offset (0x" + + Twine::utohexstr(DynamicPhdr->p_offset) + ") + file size (0x" + + Twine::utohexstr(DynamicPhdr->p_filesz) + + ") exceeds the size of the file (0x" + + Twine::utohexstr(ObjF->getMemoryBufferRef().getBufferSize()) + ")")); // Don't use the broken dynamic header. DynamicPhdr = nullptr; }