Discussion:
[Bug c++/22860] New: heap buffer overflow in value_contents_copy_raw
ppluzhnikov at google dot com
2018-02-18 21:08:41 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=22860

Bug ID: 22860
Summary: heap buffer overflow in value_contents_copy_raw
Product: gdb
Version: unknown
Status: NEW
Severity: normal
Priority: P2
Component: c++
Assignee: unassigned at sourceware dot org
Reporter: ppluzhnikov at google dot com
Target Milestone: ---

Using current head (e64676d21c373877e93f83ba3fc9a0b55aedb40c) built with
CFLAGS='-g -fsanitize=address' CXXFLAGS='-g -fsanitize=address':

$ gdb/gdb -ex 'break virtbase.cc:22' -ex run -ex 'print *this'
/usr/local/binutils-gdb/build/gdb/testsuite/outputs/gdb.cp/virtbase/virtbase
GNU gdb (GDB) 8.1.50.20180218-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from
/usr/local/binutils-gdb/build/gdb/testsuite/outputs/gdb.cp/virtbase/virtbase...done.
Breakpoint 1 at 0x400868: file
/usr/local/binutils-gdb/build/gdb/testsuite/../../../gdb/testsuite/gdb.cp/virtbase.cc,
line 22.
Starting program:
/usr/local/binutils-gdb/build/gdb/testsuite/outputs/gdb.cp/virtbase/virtbase

Breakpoint 1, ph::Middle::get_y (this=0x7fffffffdaf0) at
/usr/local/google/home/ppluzhnikov/Archive/binutils-gdb/build/gdb/testsuite/../../../gdb/testsuite/gdb.cp/virtbase.cc:22
22 return y; // breakpoint 1
=================================================================
==11670==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x6030000369f0 at pc 0x7f54dd6d8f7f bp 0x7ffcbd3ed960 sp 0x7ffcbd3ed110
READ of size 16 at 0x6030000369f0 thread T0
#0 0x7f54dd6d8f7e (/usr/lib/x86_64-linux-gnu/libasan.so.3+0x5cf7e)
#1 0x558366b737f7 in value_contents_copy_raw(value*, long, value*, long,
long) ../../gdb/value.c:1350
#2 0x558366b738ea in value_contents_copy(value*, long, value*, long, long)
../../gdb/value.c:1379
#3 0x558366b7d712 in value_from_component(value*, type*, long)
../../gdb/value.c:3704
#4 0x5583663b4167 in gdbpy_apply_val_pretty_printer(extension_language_defn
const*, type*, long, unsigned long, ui_file*, int, value*, value_print_options
const*, language_defn const*) ../../gdb/python/py-prettyprint.c:677
#5 0x55836679d56f in apply_ext_lang_val_pretty_printer(type*, long,
unsigned long, ui_file*, int, value*, value_print_options const*, language_defn
const*) ../../gdb/extension.c:518
#6 0x558366b6408e in value_print(value*, ui_file*, value_print_options
const*) ../../gdb/valprint.c:1173
#7 0x55836693a978 in print_formatted ../../gdb/printcmd.c:318
#8 0x55836693eb45 in print_value(value*, format_data const*)
../../gdb/printcmd.c:1185
#9 0x55836693ede1 in print_command_1 ../../gdb/printcmd.c:1213
#10 0x55836693ee89 in print_command ../../gdb/printcmd.c:1219
#11 0x55836630599c in do_const_cfunc ../../gdb/cli/cli-decode.c:106
#12 0x55836630ca48 in cmd_func(cmd_list_element*, char const*, int)
../../gdb/cli/cli-decode.c:1886
#13 0x558366ae4559 in execute_command(char const*, int) ../../gdb/top.c:630
#14 0x5583668b514e in catch_command_errors ../../gdb/main.c:378
#15 0x5583668b7668 in captured_main_1 ../../gdb/main.c:1125
#16 0x5583668b791d in captured_main ../../gdb/main.c:1146
#17 0x5583668b7ad0 in gdb_main(captured_main_args*) ../../gdb/main.c:1172
#18 0x558365fa1c2e in main ../../gdb/gdb.c:32
#19 0x7f54db93d2b0 in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x202b0)
#20 0x558365fa1a59 in _start
(/usr/local/binutils-gdb/build/gdb/gdb+0x114ea59)

0x6030000369f0 is located 0 bytes to the right of 32-byte region
[0x6030000369d0,0x6030000369f0)
allocated by thread T0 here:
#0 0x7f54dd73ded0 in calloc
(/usr/lib/x86_64-linux-gnu/libasan.so.3+0xc1ed0)
#1 0x5583664abb19 in xcalloc ../../gdb/common/common-utils.c:84
#2 0x5583664abb65 in xzalloc(unsigned long)
../../gdb/common/common-utils.c:94
#3 0x558366b7240e in allocate_value_contents ../../gdb/value.c:1029
#4 0x558366b7e2be in value_fetch_lazy(value*) ../../gdb/value.c:3857
#5 0x558366b75fd1 in record_latest_value(value*) ../../gdb/value.c:1893
#6 0x55836693e9d6 in print_value(value*, format_data const*)
../../gdb/printcmd.c:1174
#7 0x55836693ede1 in print_command_1 ../../gdb/printcmd.c:1213
#8 0x55836693ee89 in print_command ../../gdb/printcmd.c:1219
#9 0x55836630599c in do_const_cfunc ../../gdb/cli/cli-decode.c:106
#10 0x55836630ca48 in cmd_func(cmd_list_element*, char const*, int)
../../gdb/cli/cli-decode.c:1886
#11 0x558366ae4559 in execute_command(char const*, int) ../../gdb/top.c:630
#12 0x5583668b514e in catch_command_errors ../../gdb/main.c:378
#13 0x5583668b7668 in captured_main_1 ../../gdb/main.c:1125
#14 0x5583668b791d in captured_main ../../gdb/main.c:1146
#15 0x5583668b7ad0 in gdb_main(captured_main_args*) ../../gdb/main.c:1172
#16 0x558365fa1c2e in main ../../gdb/gdb.c:32
#17 0x7f54db93d2b0 in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x202b0)

SUMMARY: AddressSanitizer: heap-buffer-overflow
(/usr/lib/x86_64-linux-gnu/libasan.so.3+0x5cf7e)
Shadow bytes around the buggy address:
0x0c067fffece0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c067fffecf0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c067fffed00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c067fffed10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c067fffed20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c067fffed30: fa fa fa fa 00 00 00 fa fa fa 00 00 00 00[fa]fa
0x0c067fffed40: fd fd fd fd fa fa fd fd fd fd fa fa 00 00 00 00
0x0c067fffed50: fa fa 00 00 00 00 fa fa fd fd fd fd fa fa fd fd
0x0c067fffed60: fd fa fa fa fd fd fd fd fa fa 00 00 00 00 fa fa
0x0c067fffed70: 00 00 00 00 fa fa fd fd fd fd fa fa fd fd fd fd
0x0c067fffed80: fa fa fd fd fd fa fa fa 00 00 00 00 fa fa fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Heap right redzone: fb
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==11670==ABORTING

The same bug also happens in gdb.cp/inherit
--
You are receiving this mail because:
You are on the CC list for the bug.
simon.marchi at ericsson dot com
2018-02-19 14:47:51 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=22860

Simon Marchi <simon.marchi at ericsson dot com> changed:

What |Removed |Added
----------------------------------------------------------------------------
CC| |simon.marchi at ericsson dot com

--- Comment #1 from Simon Marchi <simon.marchi at ericsson dot com> ---
I debugged GDB a little bit, and this is due to virtual inheritance I think.
The layout of the vC structure (when used standalone) is:

0 vtable
4 vtable
8 vc
C vx
10 vA::va
14 vA::vx

And the layout of the vD structure is

0 vtable?
4 vtable?
8 vd
C vx
10 vtable?
14 vtable?
18 vB::vb
1C vB::vx
20 vA::va
24 vA::vx
28 vtable?
2C vtable?
30 vC::vc
34 vC::vx

Because of virtual inheritance, the vA base of vC is share with the vA base of
vD. Because of that, the vC object is not contiguous in memory. In
value_from_component, we are trying to extract the vC object from vD as a 24
bytes contiguous object from its location in vD. Asan warns when we try to
read the bytes just passed vD.
--
You are receiving this mail because:
You are on the CC list for the bug.
tromey at sourceware dot org
2018-07-28 15:32:25 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=22860

Tom Tromey <tromey at sourceware dot org> changed:

What |Removed |Added
----------------------------------------------------------------------------
CC| |qiyao at gcc dot gnu.org

--- Comment #2 from Tom Tromey <tromey at sourceware dot org> ---
*** Bug 21194 has been marked as a duplicate of this bug. ***
--
You are receiving this mail because:
You are on the CC list for the bug.
tromey at sourceware dot org
2018-07-29 10:47:39 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=22860

Tom Tromey <tromey at sourceware dot org> changed:

What |Removed |Added
----------------------------------------------------------------------------
CC| |tromey at sourceware dot org

--- Comment #3 from Tom Tromey <tromey at sourceware dot org> ---
I think the bug may be that value_from_component adds in the embedded
offset, but that's also passed in. So, it is added twice.

Changing this shows a new crash in virtbase.exp though.
--
You are receiving this mail because:
You are on the CC list for the bug.
tromey at sourceware dot org
2018-07-29 18:24:41 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=22860

--- Comment #4 from Tom Tromey <tromey at sourceware dot org> ---
I should have been more clear - comment #3 just refers to the
"print *this" test from virtbase.exp.

This bug reminds me that val_print should be removed entirely.
If it were gone, there wouldn't be a need for the python code
to reconstruct a value from a component. Of course, that's a
pretty big task.

Maybe value_from_component just needs to be smarter about
reconstructing a value when the given type has virtual base classes,
and when it is a base class of the whole object's type.
--
You are receiving this mail because:
You are on the CC list for the bug.
tromey at sourceware dot org
2018-07-29 13:19:52 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=22860

--- Comment #5 from Tom Tromey <tromey at sourceware dot org> ---
Just "print *virtual_middle_b" will crash, and I think this case
shows that either struct value has to be able to hold discontiguous
regions of memory, or that the full object always has to be fetched
under the hood.
--
You are receiving this mail because:
You are on the CC list for the bug.
Loading...