Index: lib/DebugInfo/DWARF/DWARFExpression.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFExpression.cpp +++ lib/DebugInfo/DWARF/DWARFExpression.cpp @@ -104,7 +104,9 @@ static DWARFExpression::Operation::Description getOpDesc(unsigned OpCode) { // FIXME: Make this constexpr once all compilers are smart enough to do it. static DescVector Descriptions = getDescriptions(); - assert(OpCode < Descriptions.size()); + // Handle possible corrupted or unsupported operation. + if (OpCode >= Descriptions.size()) + return DWARFExpression::Operation::Description(); return Descriptions[OpCode]; } @@ -117,8 +119,10 @@ Opcode = Data.getU8(&Offset); Desc = getOpDesc(Opcode); - if (Desc.Version == Operation::DwarfNA) + if (Desc.Version == Operation::DwarfNA) { + EndOffset = Offset; return false; + } for (unsigned Operand = 0; Operand < 2; ++Operand) { unsigned Size = Desc.Op[Operand]; Index: lib/DebugInfo/DWARF/DWARFVerifier.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -13,6 +13,7 @@ #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" +#include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFSection.h" #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" @@ -377,25 +378,24 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die, DWARFAttribute &AttrValue) { - const DWARFObject &DObj = DCtx.getDWARFObj(); unsigned NumErrors = 0; + auto ReportError = [&](const Twine &TitleMsg) { + ++NumErrors; + error() << TitleMsg; + Die.dump(OS, 0, DumpOpts); + OS << "\n"; + }; + + const DWARFObject &DObj = DCtx.getDWARFObj(); const auto Attr = AttrValue.Attr; switch (Attr) { case DW_AT_ranges: // Make sure the offset in the DW_AT_ranges attribute is valid. if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) { - if (*SectionOffset >= DObj.getRangeSection().Data.size()) { - ++NumErrors; - error() << "DW_AT_ranges offset is beyond .debug_ranges " - "bounds:\n"; - Die.dump(OS, 0, DumpOpts); - OS << "\n"; - } + if (*SectionOffset >= DObj.getRangeSection().Data.size()) + ReportError("DW_AT_ranges offset is beyond .debug_ranges bounds:\n"); } else { - ++NumErrors; - error() << "DIE has invalid DW_AT_ranges encoding:\n"; - Die.dump(OS, 0, DumpOpts); - OS << "\n"; + ReportError("DIE has invalid DW_AT_ranges encoding:\n"); } break; case DW_AT_stmt_list: @@ -410,12 +410,27 @@ OS << "\n"; } } else { - ++NumErrors; - error() << "DIE has invalid DW_AT_stmt_list encoding:\n"; - Die.dump(OS, 0, DumpOpts); - OS << "\n"; + ReportError("DIE has invalid DW_AT_stmt_list encoding:\n"); } break; + case DW_AT_location: { + Optional> Expr = AttrValue.Value.getAsBlock(); + if (!Expr) { + ReportError("DIE has invalid DW_AT_location encoding:\n"); + break; + } + + DWARFUnit *U = Die.getDwarfUnit(); + DataExtractor Data(StringRef((const char *)Expr->data(), Expr->size()), + DCtx.isLittleEndian(), 0); + DWARFExpression Expression(Data, U->getVersion(), U->getAddressByteSize()); + bool Error = llvm::any_of(Expression, [](DWARFExpression::Operation &Op) { + return Op.isError(); + }); + if (Error) + ReportError("DIE contains invalid DWARF expression:\n"); + break; + } default: break; Index: test/tools/llvm-dwarfdump/X86/verify_broken_exprloc.s =================================================================== --- test/tools/llvm-dwarfdump/X86/verify_broken_exprloc.s +++ test/tools/llvm-dwarfdump/X86/verify_broken_exprloc.s @@ -0,0 +1,52 @@ +# RUN: llvm-mc %s -filetype obj -triple i686-pc-linux -o %t + +## Check we don't crash when parsing invalid expression opcode. +# RUN: llvm-dwarfdump %t | FileCheck %s +# CHECK: DW_TAG_GNU_call_site_parameter +# CHECK-NEXT: DW_AT_location (decoding error.) + +## Check verifier reports an error. +# RUN: not llvm-dwarfdump -verify %t 2>&1 | FileCheck %s --check-prefix=VERIFY +# VERIFY: DIE contains invalid DWARF expression: +# VERIFY: DW_TAG_GNU_call_site_parameter +# VERIFY-NEXT: DW_AT_location (decoding error.) + +.section .debug_info,"",@progbits + .long 0x12 + .value 0x4 + .long 0 + .byte 0x4 + + .uleb128 0x1 # DW_TAG_compile_unit [1] + .long 0 + .byte 0x0 + + .uleb128 0x2 # DW_TAG_GNU_call_site_parameter [2] + .uleb128 0x1 # Expression size. + .byte 0xff # Broken expression. + + .byte 0 # End mark. + .byte 0 # End mark. + +.section .debug_abbrev,"",@progbits + .uleb128 0x1 # ID [1] + .uleb128 0x11 # DW_TAG_compile_unit, DW_CHILDREN_yes + .byte 0x1 + .uleb128 0x25 # DW_AT_producer, DW_FORM_strp + .uleb128 0xe + .uleb128 0x13 # DW_AT_language, DW_FORM_data1 + .uleb128 0xb + .byte 0 + .byte 0 + + .uleb128 0x2 # ID [2] + .uleb128 0x410a # DW_TAG_GNU_call_site_parameter, DW_CHILDREN_no + .byte 0 + .uleb128 0x2 # DW_AT_location, DW_FORM_exprloc + .uleb128 0x18 + .byte 0 + .byte 0 + .byte 0 + +.section .debug_str,"MS",@progbits,1 +.string "test"