[PATCH][lldb] Fix dereference of null pointer.
authorCaroline Tice <cmtice@google.com>
Mon, 10 Apr 2023 21:45:59 +0000 (14:45 -0700)
committerCaroline Tice <cmtice@google.com>
Tue, 11 Apr 2023 20:33:03 +0000 (13:33 -0700)
The function DWARFASTParserClang::ParsePointerToMemberType attempts to make
two pointers and then immediately tries to dereference them, without
verifying that the pointesr were successfully created. Sometimes the pointer
creation fails, and the dereference then causes a segfault. This add a check
that the pointers are non-null before attempting to dereference them.

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
lldb/test/Shell/SymbolFile/DWARF/x86/class-type-nullptr-deref.s [new file with mode: 0644]

index cf79485..e6921ca 100644 (file)
@@ -1351,6 +1351,11 @@ TypeSP DWARFASTParserClang::ParsePointerToMemberType(
   Type *class_type =
       dwarf->ResolveTypeUID(attrs.containing_type.Reference(), true);
 
+  // Check to make sure pointers are not NULL before attempting to
+  // dereference them.
+  if ((class_type == nullptr) || (pointee_type == nullptr))
+    return nullptr;
+
   CompilerType pointee_clang_type = pointee_type->GetForwardCompilerType();
   CompilerType class_clang_type = class_type->GetForwardCompilerType();
 
diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/class-type-nullptr-deref.s b/lldb/test/Shell/SymbolFile/DWARF/x86/class-type-nullptr-deref.s
new file mode 100644 (file)
index 0000000..610b458
--- /dev/null
@@ -0,0 +1,66 @@
+# Test to verify that, if a class type pointer creation fails (pointer is
+# null), LLDB does not try to dereference the null pointer.
+
+# RUN: llvm-mc --triple x86_64-pc-linux %s --filetype=obj -o %t
+# RUN: %lldb %t -o "target variable x" -o exit 2>&1
+
+# This tests a fix for a crash. If things are working we don't get a segfault.
+
+        .type   x,@object                       # @x
+        .bss
+        .globl  x
+x:
+        .quad   0                               # 0x0
+        .size   x, 8
+
+        .section        .debug_abbrev,"",@progbits
+        .byte   1                               # Abbreviation Code
+        .byte   17                              # DW_TAG_compile_unit
+        .byte   1                               # DW_CHILDREN_yes
+        .byte   37                              # DW_AT_producer
+        .byte   8                               # DW_FORM_string
+        .byte   0                               # EOM(1)
+        .byte   0                               # EOM(2)
+        .byte   2                               # Abbreviation Code
+        .byte   52                              # DW_TAG_variable
+        .byte   0                               # DW_CHILDREN_no
+        .byte   3                               # DW_AT_name
+        .byte   8                               # DW_FORM_string
+        .byte   73                              # DW_AT_type
+        .byte   19                              # DW_FORM_ref4
+        .byte   2                               # DW_AT_location
+        .byte   24                              # DW_FORM_exprloc
+        .byte   0                               # EOM(1)
+        .byte   0                               # EOM(2)
+        .byte   3                               # Abbreviation Code
+        .byte   31                              # DW_TAG_ptr_to_member_type
+        .byte   0                               # DW_CHILDREN_no
+        .byte   73                              # DW_AT_type
+        .byte   19                              # DW_FORM_ref4
+        .byte   29                              # DW_AT_containing_type
+        .byte   19                              # DW_FORM_ref4
+        .byte   0                               # EOM(1)
+        .byte   0                               # EOM(2)
+        .byte   0                               # EOM(3)
+        .section        .debug_info,"",@progbits
+.Lcu_begin0:
+        .long   .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+        .short  5                               # DWARF version number
+        .byte   1                               # DWARF Unit Type
+        .byte   8                               # Address Size (in bytes)
+        .long   .debug_abbrev                   # Offset Into Abbrev. Section
+        .byte   1                               # Abbrev [1] DW_TAG_compile_unit
+        .asciz  "Hand-written DWARF"            # DW_AT_producer
+        .byte   2                               # Abbrev [2] DW_TAG_variable
+        .asciz  "x"                             # DW_AT_name
+        .long   .Ltype-.Lcu_begin0              # DW_AT_type
+        .byte   9                               # DW_AT_location
+        .byte   3
+        .quad   x
+.Ltype:
+        .byte   3                               # Abbrev [3] DW_TAG_ptr_to_member_type
+        .long   0xdeadbeef                      # DW_AT_type
+        .long   0xdeadbeef                      # DW_AT_containing_type
+        .byte   0                               # End Of Children Mark
+.Ldebug_info_end0: