Index: llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp @@ -59,11 +59,26 @@ // the segment selectors are omitted from all tuples, including // the terminating tuple. + static const unsigned DWARF32HeaderLength = 4 + 2 + 4 + 1 + 1; + static const unsigned DWARF64HeaderLength = 12 + 2 + 8 + 1 + 1; + + if (!data.isValidOffsetForDataOfSize(Offset, DWARF32HeaderLength)) + return createStringError(errc::invalid_argument, + "section is not large enough to contain " + "an address range table at offset 0x%" PRIx64, + Offset); + // We do not call FormParams::getRefAddrByteSize(), // so 4 for Version and 4 for AddrSize are taken arbitrary. dwarf::FormParams params = {4, 4, dwarf::DWARF32}; HeaderData.Length = data.getU32(offset_ptr); if (HeaderData.Length == dwarf::DW_LENGTH_DWARF64) { + if (!data.isValidOffsetForDataOfSize(Offset, DWARF64HeaderLength)) + return createStringError( + errc::invalid_argument, + "section is not large enough to contain a DWARF64 " + "address range table at offset 0x%" PRIx64, + Offset); HeaderData.Length = data.getU64(offset_ptr); params.Format = dwarf::DWARF64; } else if (HeaderData.Length >= dwarf::DW_LENGTH_lo_reserved) { @@ -92,6 +107,11 @@ "address range table at offset 0x%" PRIx64 " has invalid address size", Offset); + if (HeaderData.SegSize != 0) + return createStringError(errc::not_supported, + "non-zero segment selector size in address range " + "table at offset 0x%" PRIx64 " is not supported", + Offset); // The first tuple following the header in each set begins at an offset // that is a multiple of the size of a single tuple (that is, twice the @@ -103,6 +123,15 @@ while (first_tuple_offset < header_size) first_tuple_offset += tuple_size; + // There should be space for at least one tuple. + // As each tuple begins at an offset that is a multiple of the tuple size, + // the full length should also be a multiple of that. + if (full_length <= first_tuple_offset || full_length % tuple_size != 0) + return createStringError(errc::invalid_argument, + "address range table at offset 0x%" PRIx64 + " has invalid length", + Offset); + *offset_ptr = Offset + first_tuple_offset; Descriptor arangeDescriptor; @@ -112,14 +141,23 @@ "Different datatypes for addresses and sizes!"); assert(sizeof(arangeDescriptor.Address) >= HeaderData.AddrSize); - while (data.isValidOffset(*offset_ptr)) { + uint64_t end_offset = Offset + full_length; + while (*offset_ptr < end_offset) { arangeDescriptor.Address = data.getUnsigned(offset_ptr, HeaderData.AddrSize); arangeDescriptor.Length = data.getUnsigned(offset_ptr, HeaderData.AddrSize); - // Each set of tuples is terminated by a 0 for the address and 0 - // for the length. - if (arangeDescriptor.Address == 0 && arangeDescriptor.Length == 0) - return ErrorSuccess(); + if (arangeDescriptor.Length == 0) { + // Each set of tuples is terminated by a 0 for the address and 0 + // for the length. + if (arangeDescriptor.Address == 0 && *offset_ptr == end_offset) + return ErrorSuccess(); + return createStringError( + errc::invalid_argument, + "address range table at offset 0x%" PRIx64 + " has an invalid tuple (length = 0) at offset 0x%" PRIx64, + Offset, *offset_ptr - tuple_size); + } + ArangeDescriptors.push_back(arangeDescriptor); } Index: llvm/test/DebugInfo/X86/dwarfdump-debug-aranges-error-cases.s =================================================================== --- llvm/test/DebugInfo/X86/dwarfdump-debug-aranges-error-cases.s +++ llvm/test/DebugInfo/X86/dwarfdump-debug-aranges-error-cases.s @@ -18,6 +18,30 @@ # RUN: llvm-dwarfdump -debug-aranges - 2>&1 | \ # RUN: FileCheck %s --check-prefix=CHECK5 +# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj --defsym CASE6=0 -o - | \ +# RUN: llvm-dwarfdump -debug-aranges - 2>&1 | \ +# RUN: FileCheck %s --check-prefix=CHECK6 + +# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj --defsym CASE7=0 -o - | \ +# RUN: llvm-dwarfdump -debug-aranges - 2>&1 | \ +# RUN: FileCheck %s --check-prefix=CHECK7 + +# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj --defsym CASE8=0 -o - | \ +# RUN: llvm-dwarfdump -debug-aranges - 2>&1 | \ +# RUN: FileCheck %s --check-prefix=CHECK8 + +# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj --defsym CASE9=0 -o - | \ +# RUN: llvm-dwarfdump -debug-aranges - 2>&1 | \ +# RUN: FileCheck %s --check-prefix=CHECK9 + +# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj --defsym CASE10=0 -o - | \ +# RUN: llvm-dwarfdump -debug-aranges - 2>&1 | \ +# RUN: FileCheck %s --check-prefix=CHECK10 + +# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj --defsym CASE11=0 -o - | \ +# RUN: llvm-dwarfdump -debug-aranges - 2>&1 | \ +# RUN: FileCheck %s --check-prefix=CHECK11 + .section .debug_aranges,"",@progbits .ifdef CASE1 # CHECK1: address range table at offset 0x0 has invalid length @@ -88,4 +112,78 @@ .ifdef CASE5 # CHECK5: address range table at offset 0x0 has unsupported reserved unit length of value 0xfffffff0 .long 0xfffffff0 # Reserved unit length value + .space 40 # Add some space to pass the basic check for the section size .endif # CASE5 + +.ifdef CASE6 +# CHECK6: section is not large enough to contain an address range table at offset 0x0 + .space 11 +.endif # CASE6 + +.ifdef CASE7 +# CHECK7: section is not large enough to contain a DWARF64 address range table at offset 0x0 + .long 0xffffffff # DWARF64 mark + .space 19 +.endif # CASE7 + +.ifdef CASE8 +# CHECK8: non-zero segment selector size in address range table at offset 0x0 is not supported +.Llen: + .long .Lend - .Lversion # Length +.Lversion: + .short 2 # Version + .long 0 # Debug Info Offset + .byte 4 # Address Size + .byte 4 # Segment Selector Size (not supported) + .space 11 - (. - .Llen + 11) % 12 # Padding +.Ltuples: + .long 0, 0, 1 # Segment selector, address and length + .long 0, 0, 0 # Termination tuple +.Lend: +.endif # CASE8 + +.ifdef CASE9 +# CHECK9: address range table at offset 0x0 has invalid length +.Llen: + .long .Lend - .Lversion # Length (too short) +.Lversion: + .short 2 # Version + .long 0 # Debug Info Offset + .byte 4 # Address Size + .byte 0 # Segment Selector Size + .space 7 - (. - .Llen + 7) % 8 # Padding +.Lend: +.endif # CASE9 + +.ifdef CASE10 +# CHECK10: address range table at offset 0x0 has invalid length +.Llen: + .long .Lend - .Lversion - 1 # Length (not a multiple of tuple size) +.Lversion: + .short 2 # Version + .long 0 # Debug Info Offset + .byte 4 # Address Size + .byte 0 # Segment Selector Size + .space 7 - (. - .Llen + 7) % 8 # Padding +.Ltuples: + .long 0, 1 # Address and length + .long 0, 0 # Termination tuple +.Lend: +.endif # CASE10 + +.ifdef CASE11 +# CHECK11: address range table at offset 0x0 has an invalid tuple (length = 0) at offset 0x18 +.Llen: + .long .Lend - .Lversion # Length +.Lversion: + .short 2 # Version + .long 0 # Debug Info Offset + .byte 4 # Address Size + .byte 0 # Segment Selector Size + .space 7 - (. - .Llen + 7) % 8 # Padding +.Ltuples: + .long 0, 1 # Address and length + .long 1, 0 # Address and invalid length + .long 0, 0 # Termination tuple +.Lend: +.endif # CASE11