Bug 28063 - ASan crash in value_primitive_field / value_contents_copy_raw when printing std::tuple
Summary: ASan crash in value_primitive_field / value_contents_copy_raw when printing s...
Status: NEW
Alias: None
Product: gdb
Classification: Unclassified
Component: gdb (show other bugs)
Version: HEAD
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-07-07 16:27 UTC by Simon Marchi
Modified: 2021-07-25 16:41 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Simon Marchi 2021-07-07 16:27:31 UTC
I hit this while debugging GDB itself.  I don't have a small reproducer at the moment, but I have a self-contained easy reproducer using the GDB binary and a core file of it I created.  It's a bit too big to attach here so I'll post a link in a follow-up comment.

Steps to reproduce:

1. Extract the archive to /tmp/repro
2. Compile GDB with AddressSanitizer
2. Run:

  $ ./gdb -q -nx --data-directory=data-directory  -iex "set sysroot /tmp/repro" /tmp/repro/gdb  /tmp/repro/core.3164744 -ex 'p current_inferior_.m_obj.thread_list.m_front.priv' -batch


The error I get:

==2087857==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200009b10f at pc 0x7f7575b843a7 bp 0x7fffbac99b10 sp 0x7fffbac992b8                                                                                                                                               
READ of size 1 at 0x60200009b10f thread T0                                                                                                                                                                                                                                                
    #0 0x7f7575b843a6 in __interceptor_memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827                                                                                                                                                         
    #1 0x124aa6c in memcpy /usr/include/x86_64-linux-gnu/bits/string_fortified.h:34                                                                                                                                                                                                       
    #2 0x124aa6c in value_contents_copy_raw /home/smarchi/src/binutils-gdb/gdb/value.c:1332                                                                                                                                                                                               
    #3 0x1251b95 in value_primitive_field(value*, long, int, type*) /home/smarchi/src/binutils-gdb/gdb/value.c:3096                                                                                                                                                                       
    #4 0x7f4c87 in cp_print_value_fields(value*, ui_file*, int, value_print_options const*, type**, int) /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:333                                                                                                                             
    #5 0x7f5f75 in cp_print_value /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:513                                                                                                                                                                                                    
    #6 0x7f5f75 in cp_print_value_fields(value*, ui_file*, int, value_print_options const*, type**, int) /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:159                                                                                                                             
    #7 0x7f5f75 in cp_print_value /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:513                                                                                                                                                                                                    
    #8 0x7f5f75 in cp_print_value_fields(value*, ui_file*, int, value_print_options const*, type**, int) /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:159                                                                                                                             
    #9 0x7f5f75 in cp_print_value /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:513                                                                                                                                                                                                    
    #10 0x7f5f75 in cp_print_value_fields(value*, ui_file*, int, value_print_options const*, type**, int) /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:159                                                                                                                            
    #11 0x6faa66 in c_value_print_struct /home/smarchi/src/binutils-gdb/gdb/c-valprint.c:383                                                                                                                                                                                              
    #12 0x6faa66 in c_value_print_inner(value*, ui_file*, int, value_print_options const*) /home/smarchi/src/binutils-gdb/gdb/c-valprint.c:438                                                                                                                                            
    #13 0x1235c77 in do_val_print /home/smarchi/src/binutils-gdb/gdb/valprint.c:1046                                                                                                                                                                                                      
    #14 0x7f4cea in cp_print_value_fields(value*, ui_file*, int, value_print_options const*, type**, int) /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:335                                                                                                                            
    #15 0x7f5f75 in cp_print_value /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:513                                                                                                                                                                                                   
    #16 0x7f5f75 in cp_print_value_fields(value*, ui_file*, int, value_print_options const*, type**, int) /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:159                                                                                                                            
    #17 0x6faa66 in c_value_print_struct /home/smarchi/src/binutils-gdb/gdb/c-valprint.c:383
    #18 0x6faa66 in c_value_print_inner(value*, ui_file*, int, value_print_options const*) /home/smarchi/src/binutils-gdb/gdb/c-valprint.c:438
    #19 0x1235c77 in do_val_print /home/smarchi/src/binutils-gdb/gdb/valprint.c:1046
    #20 0x7f4cea in cp_print_value_fields(value*, ui_file*, int, value_print_options const*, type**, int) /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:335
    #21 0x6faa66 in c_value_print_struct /home/smarchi/src/binutils-gdb/gdb/c-valprint.c:383
    #22 0x6faa66 in c_value_print_inner(value*, ui_file*, int, value_print_options const*) /home/smarchi/src/binutils-gdb/gdb/c-valprint.c:438
    #23 0x1235c77 in do_val_print /home/smarchi/src/binutils-gdb/gdb/valprint.c:1046
    #24 0x6fb4d5 in c_value_print(value*, ui_file*, value_print_options const*) /home/smarchi/src/binutils-gdb/gdb/c-valprint.c:587
    #25 0x1236a37 in value_print(value*, ui_file*, value_print_options const*) /home/smarchi/src/binutils-gdb/gdb/valprint.c:1187
    #26 0xd7eafe in print_value(value*, value_print_options const&) /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1258
    #27 0xd7f00f in print_command_1 /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1344
    #28 0x72ad29 in cmd_func(cmd_list_element*, char const*, int) /home/smarchi/src/binutils-gdb/gdb/cli/cli-decode.c:2160
    #29 0x10e7464 in execute_command(char const*, int) /home/smarchi/src/binutils-gdb/gdb/top.c:674                                          
    #30 0xc4af30 in catch_command_errors /home/smarchi/src/binutils-gdb/gdb/main.c:523
    #31 0xc4b204 in execute_cmdargs /home/smarchi/src/binutils-gdb/gdb/main.c:618
    #32 0xc503af in captured_main_1 /home/smarchi/src/binutils-gdb/gdb/main.c:1322
    #33 0xc5153b in captured_main /home/smarchi/src/binutils-gdb/gdb/main.c:1343
    #34 0xc5153b in gdb_main(captured_main_args*) /home/smarchi/src/binutils-gdb/gdb/main.c:1368
    #35 0x487ffd in main /home/smarchi/src/binutils-gdb/gdb/gdb.c:32
    #36 0x7f7574bac0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
    #37 0x4acdfd in _start (/home/smarchi/build/binutils-gdb-opt/gdb/gdb+0x4acdfd)

0x60200009b10f is located 1 bytes to the left of 8-byte region [0x60200009b110,0x60200009b118)
allocated by thread T0 here:
    #0 0x7f7575bfee17 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154                                    
    #1 0x56b0a0 in xcalloc /home/smarchi/src/binutils-gdb/gdb/alloc.c:100
Comment 1 Simon Marchi 2021-07-07 16:30:47 UTC
The archive: https://files.efficios.com/s/ReLYZCHKen7jkBs
Comment 2 Simon Marchi 2021-07-07 16:33:51 UTC
For the record:

 - libstdc++.so comes from Arch Linux package gcc-libs 11.1.0-1
 - libc-2.33.so comes from Arch Linux package glibc 2.33-5

libstdc++.so contains debug info.
Comment 3 Simon Marchi 2021-07-07 17:18:59 UTC
And the gcc version:

$ gcc --version
gcc (GCC) 11.1.0

If we look at the value_primitive_field frame, I see:

  (top-gdb) p offset
  $5 = -1

which comes from:

(top-gdb) p arg_type.main_type.name
$6 = 0x621001a80ae0 "std::_Head_base<1, std::default_delete<private_thread_info>, true>"
(top-gdb) p arg_type.main_type.flds_bnds.fields[0].loc.bitpos 
$7 = -8

And indeed, in the DWARF, in the gdb file, I have:

0x000cbdf5:       DW_TAG_member
                    DW_AT_name [DW_FORM_strp]   ("_M_head_impl")
                    DW_AT_decl_file [DW_FORM_implicit_const]    ("/usr/include/c++/11.1.0/tuple")
                    DW_AT_decl_line [DW_FORM_implicit_const]    (125)
                    DW_AT_decl_column [DW_FORM_implicit_const]  (39)
                    DW_AT_type [DW_FORM_ref4]   (0x000cbaff "default_delete<private_thread_info>")
                    DW_AT_data_member_location [DW_FORM_implicit_const] (-1)

I don't know if the DW_AT_data_member_location value of -1 is right or not.
Comment 4 Simon Marchi 2021-07-08 00:26:43 UTC
Here's a simpler reproducer:

---
#include <memory>

int main() {
  std::unique_ptr<int> p(new int);
  return 0;
}
---

$ g++ --version
g++ (GCC) 11.1.0
$ g++ -g3 -O0 test.cpp
$ readelf --debug-dump a.out
...
 <3><968>: Abbrev Number: 79 (DW_TAG_member)
    <969>   DW_AT_name        : (strp) (offset: 0xc42a): _M_head_impl
    <96d>   DW_AT_decl_file   : (data1) 4
    <96e>   DW_AT_decl_line   : (data1) 125
    <96f>   DW_AT_decl_column : (data1) 39
    <970>   DW_AT_type        : (ref4) <0x67e>, default_delete<int>
    <974>   DW_AT_data_member_location: (sdata) -1
...
$ ./gdb -q -nx --data-directory=data-directory ./a.out -ex "b 5" -ex r -ex "p p"
<ASan crash like above>
Comment 5 Simon Marchi 2021-07-08 15:05:16 UTC
File gcc bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101378

The question now (if this is confirmed to be a gcc bug) is how do we do handle this bad debug info.  When getting a negative DW_AT_data_member_location, do we just ignore the field, as if it didn't exist?  Do we add it, but with an unknown location (a new FIELD_LOC_KIND_UNKNOWN)?

So far I have only seen this bug manifest when using std::unique_ptr (the reproducer above), and the DW_AT_data_member_location should have always been 0 instead of -1.  So we could have a special case to detect DW_AT_data_member_location, and make it 0 instead.  But I don't know if it will always be right.