bug-readline
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug-readline] heap-buffer-overflow in update_line


From: Tom de Vries
Subject: [Bug-readline] heap-buffer-overflow in update_line
Date: Wed, 8 May 2019 22:10:32 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.5.1

Hi,

when:
- building trunk gdb (using the readline sources in the binutils-gdb.git
  repo) on openSUSE 15.0 x86_64-linux with -fsanitize=address, and:
- running gdb tests with "export ASAN_OPTIONS=detect_leaks=0",
I run into a heap-buffer-overflow failure for
gdb.base/utf8-identifiers.exp, reported as PR gdb/24514 -
"heap-buffer-overflow in update_line for utf8-identifiers.exp"  at
https://sourceware.org/bugzilla/show_bug.cgi?id=24514 .

In more detail, the libasan error report looks like this:
...
=================================================================
==22340==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x619000054a80 at pc 0x7fcd0306b4c9 bp 0x7fffb1a8d880 sp 0x7fffb1a8d030
READ of size 32766 at 0x619000054a80 thread T0
    #0 0x7fcd0306b4c8  (/usr/lib64/libasan.so.4+0xae4c8)
    #1 0x15f12a1 in update_line
/data/gdb_versions/devel/src/readline/display.c:1377
    #2 0x15f03cb in rl_redisplay
/data/gdb_versions/devel/src/readline/display.c:1204
    #3 0x15bf932 in readline_internal_setup
/data/gdb_versions/devel/src/readline/readline.c:394
    #4 0x15fe723 in _rl_callback_newline
/data/gdb_versions/devel/src/readline/callback.c:89
    #5 0x15fe7ef in rl_callback_handler_install
/data/gdb_versions/devel/src/readline/callback.c:102
    #6 0xd7bce6 in gdb_rl_callback_handler_install(char const*)
/data/gdb_versions/devel/src/gdb/event-top.c:319
    #7 0xd7c0c6 in display_gdb_prompt(char const*)
/data/gdb_versions/devel/src/gdb/event-top.c:409
    #8 0xd7d6c1 in command_line_handler(std::unique_ptr<char,
gdb::xfree_deleter<char> >&&)
/data/gdb_versions/devel/src/gdb/event-top.c:776
    #9 0xd7b92a in gdb_rl_callback_handler
/data/gdb_versions/devel/src/gdb/event-top.c:217
    #10 0x15ff479 in rl_callback_read_char
/data/gdb_versions/devel/src/readline/callback.c:220
    #11 0xd7b4d5 in gdb_rl_callback_read_char_wrapper_noexcept
/data/gdb_versions/devel/src/gdb/event-top.c:175
    #12 0xd7b6b5 in gdb_rl_callback_read_char_wrapper
/data/gdb_versions/devel/src/gdb/event-top.c:192
    #13 0xd7c8aa in stdin_event_handler(int, void*)
/data/gdb_versions/devel/src/gdb/event-top.c:514
    #14 0xd76ca7 in handle_file_event
/data/gdb_versions/devel/src/gdb/event-loop.c:731
    #15 0xd7751f in gdb_wait_for_event
/data/gdb_versions/devel/src/gdb/event-loop.c:857
    #16 0xd7547e in gdb_do_one_event()
/data/gdb_versions/devel/src/gdb/event-loop.c:321
    #17 0xd75526 in start_event_loop()
/data/gdb_versions/devel/src/gdb/event-loop.c:370
    #18 0x101b04c in captured_command_loop
/data/gdb_versions/devel/src/gdb/main.c:331
    #19 0x101de73 in captured_main
/data/gdb_versions/devel/src/gdb/main.c:1173
    #20 0x101df03 in gdb_main(captured_main_args*)
/data/gdb_versions/devel/src/gdb/main.c:1188
    #21 0x872dba in main /data/gdb_versions/devel/src/gdb/gdb.c:32
    #22 0x7fcd00f2ff49 in __libc_start_main (/lib64/libc.so.6+0x20f49)
    #23 0x872bc9 in _start (/data/gdb_versions/devel/build/gdb/gdb+0x872bc9)

0x619000054a80 is located 0 bytes to the right of 1024-byte region
[0x619000054680,0x619000054a80)
allocated by thread T0 here:
    #0 0x7fcd03099510 in malloc (/usr/lib64/libasan.so.4+0xdc510)
    #1 0xae0078 in xmalloc
/data/gdb_versions/devel/src/gdb/common/common-utils.c:44
    #2 0x15eaccb in init_line_structures
/data/gdb_versions/devel/src/readline/display.c:458
    #3 0x15eb4d8 in rl_redisplay
/data/gdb_versions/devel/src/readline/display.c:526
    #4 0x15bf932 in readline_internal_setup
/data/gdb_versions/devel/src/readline/readline.c:394
    #5 0x15fe723 in _rl_callback_newline
/data/gdb_versions/devel/src/readline/callback.c:89
    #6 0x15fe7ef in rl_callback_handler_install
/data/gdb_versions/devel/src/readline/callback.c:102
    #7 0xd7bce6 in gdb_rl_callback_handler_install(char const*)
/data/gdb_versions/devel/src/gdb/event-top.c:319
    #8 0xd7c0c6 in display_gdb_prompt(char const*)
/data/gdb_versions/devel/src/gdb/event-top.c:409
    #9 0xaa041b in cli_interp_base::pre_command_loop()
/data/gdb_versions/devel/src/gdb/cli/cli-interp.c:286
    #10 0xf5342a in interp_pre_command_loop(interp*)
/data/gdb_versions/devel/src/gdb/interps.c:320
    #11 0x101b047 in captured_command_loop
/data/gdb_versions/devel/src/gdb/main.c:328
    #12 0x101de73 in captured_main
/data/gdb_versions/devel/src/gdb/main.c:1173
    #13 0x101df03 in gdb_main(captured_main_args*)
/data/gdb_versions/devel/src/gdb/main.c:1188
    #14 0x872dba in main /data/gdb_versions/devel/src/gdb/gdb.c:32
    #15 0x7fcd00f2ff49 in __libc_start_main (/lib64/libc.so.6+0x20f49)

SUMMARY: AddressSanitizer: heap-buffer-overflow
(/usr/lib64/libasan.so.4+0xae4c8)
Shadow bytes around the buggy address:
  0x0c3280002900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c3280002910: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c3280002920: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c3280002930: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c3280002940: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c3280002950:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c3280002960: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c3280002970: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c3280002980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c3280002990: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c32800029a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  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
==22340==ABORTING
...

I managed to reproduce the same error by using trunk from git readline
repo (where HEAD happens to be at readline-8, 8e6ccd0), by building
readline using CFLAGS=-fsanitize=address, and building gdb using
--with-system-readline and:
...
readline=<readline-install-dir>
FLAGS="-O0 -g -I$readline/include/"
LDFLAGS="-lasan -L$readline/lib64/ -lncurses -Wl,-rpath=$readline/lib64"
cflagsenv=(CFLAGS="$FLAGS" CXXFLAGS="$FLAGS" LDFLAGS="$LDFLAGS")
...
and using ASAN_OPTIONS="detect_leaks=0:alloc_dealloc_mismatch=0" for
running the test.

I've written an assert that AFAIU formulates the error condition:
...
diff --git a/display.c b/display.c
index 4c6cc00..a67ced4 100644
--- a/display.c
+++ b/display.c
@@ -59,6 +59,8 @@
 #include "rlprivate.h"
 #include "xmalloc.h"

+#include "assert.h"
+
 #if !defined (strchr) && !defined (__STDC__)
 extern char *strchr (), *strrchr ();
 #endif /* !strchr && !__STDC__ */
@@ -1387,6 +1389,10 @@ rl_redisplay (void)
          forced_display = 0;
          o_cpos = _rl_last_c_pos;
          cpos_adjusted = 0;
+         assert (last_lmargin + (_rl_screenwidth + visible_wrap_offset)
+                 <= line_size);
+         assert (lmargin + (_rl_screenwidth + (lmargin ? 0 : wrap_offset))
+                 <= line_size);
          update_line (&visible_line[last_lmargin],
                       &invisible_line[lmargin],
                       0,
                       _rl_screenwidth + visible_wrap_offset,
                       _rl_screenwidth + (lmargin ? 0 : wrap_offset),
                       0);
...
which triggers without needing the address sanitizer, like this:
...
$ TERM=dumb gdb -q -ex "set width 0"
gdb: /home/vries/readline/src/display.c:1393: rl_redisplay: Assertion
`last_lmargin + (_rl_screenwidth + visible_wrap_offset) <= line_size'
failed.
Aborted (core dumped)
...

Is the assert correct?

Thanks,
- Tom



reply via email to

[Prev in Thread] Current Thread [Next in Thread]