From 044308e9ed5cb69076eca7156a694f4d2844cf74 Mon Sep 17 00:00:00 2001 From: Igor Kudrin Date: Wed, 26 Feb 2020 21:23:43 +0700 Subject: [PATCH] [DebugInfo] Avoid crashing when parsing an invalid unit header in DWP. The integrity checks for index entries in DWARFUnitHeader::extract() might cause the function to return before checking the state of an Error object, which leads to a crash in runtime. The patch fixes the issue by moving the checks in a safe place. Differential Revision: https://reviews.llvm.org/D75177 --- llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 19 ++++---- llvm/test/DebugInfo/X86/invalid-cu-length-dwp.s | 59 +++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 llvm/test/DebugInfo/X86/invalid-cu-length-dwp.s diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index bf51f0a..d3bbe20 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -285,6 +285,16 @@ bool DWARFUnitHeader::extract(DWARFContext &Context, else UnitType = DW_UT_compile; } + if (isTypeUnit()) { + TypeHash = debug_info.getU64(offset_ptr, &Err); + TypeOffset = debug_info.getUnsigned( + offset_ptr, FormParams.getDwarfOffsetByteSize(), &Err); + } else if (UnitType == DW_UT_split_compile || UnitType == DW_UT_skeleton) + DWOId = debug_info.getU64(offset_ptr, &Err); + + if (errorToBool(std::move(Err))) + return false; + if (IndexEntry) { if (AbbrOffset) return false; @@ -296,15 +306,6 @@ bool DWARFUnitHeader::extract(DWARFContext &Context, return false; AbbrOffset = AbbrEntry->Offset; } - if (isTypeUnit()) { - TypeHash = debug_info.getU64(offset_ptr, &Err); - TypeOffset = debug_info.getUnsigned( - offset_ptr, FormParams.getDwarfOffsetByteSize(), &Err); - } else if (UnitType == DW_UT_split_compile || UnitType == DW_UT_skeleton) - DWOId = debug_info.getU64(offset_ptr, &Err); - - if (errorToBool(std::move(Err))) - return false; // Header fields all parsed, capture the size of this unit header. assert(*offset_ptr - Offset <= 255 && "unexpected header size"); diff --git a/llvm/test/DebugInfo/X86/invalid-cu-length-dwp.s b/llvm/test/DebugInfo/X86/invalid-cu-length-dwp.s new file mode 100644 index 0000000..299bea1 --- /dev/null +++ b/llvm/test/DebugInfo/X86/invalid-cu-length-dwp.s @@ -0,0 +1,59 @@ +# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o - | \ +# RUN: llvm-dwarfdump -debug-info - + +## llvm-dwarfdump used to crash with this input because of an invalid size +## of the compilation unit contribution in the .debug_cu_index section. + + .section .debug_abbrev.dwo, "e", @progbits +.LAbbrBegin: + .uleb128 1 # Abbreviation Code + .uleb128 17 # DW_TAG_compile_unit + .byte 0 # DW_CHILDREN_no + .uleb128 3 # DW_AT_name + .uleb128 8 # DW_FORM_string + .uleb128 0x2131 # DW_AT_GNU_dwo_id + .uleb128 7 # DW_FORM_data8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) +.LAbbrEnd: + + .section .debug_info.dwo, "e", @progbits +.LCUBegin: + .long .LCUEnd-.LCUVersion # Length +.LCUVersion: + .short 4 # Version + .long 0 # Abbrev offset + .byte 4 # Address size + .uleb128 1 # Abbrev [1] DW_TAG_compile_unit + .asciz "a.c" # DW_AT_name + .quad 0x1100001122222222 # DW_AT_GNU_dwo_id +.LCUEnd: + + .section .debug_cu_index, "", @progbits +## Header: + .short 2 # Version + .space 2 # Padding + .long 2 # Section count + .long 1 # Unit count + .long 4 # Slot count +## Hash Table of Signatures: + .quad 0 + .quad 0 + .quad 0x1100001122222222 + .quad 0 +## Parallel Table of Indexes: + .long 0 + .long 0 + .long 1 + .long 0 +## Table of Section Offsets: +## Row 0: + .long 1 # DW_SECT_INFO + .long 3 # DW_SECT_ABBREV +## Row 1: + .long .LCUBegin-.debug_info.dwo # Offset in .debug_info.dwo + .long .LAbbrBegin-.debug_abbrev.dwo # Offset in .debug_abbrev.dwo +## Table of Section Sizes: + .long .LCUEnd-.LCUBegin-1 # Size of the contribution in .debug_info.dwo (invalid) + .long .LAbbrEnd-.LAbbrBegin -- 2.7.4