From: Andreas Arnez Date: Wed, 9 Nov 2016 12:02:12 +0000 (+0100) Subject: tui-disasm: Fix window content buffer overrun X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0bb65f1e7c9eed7338ef2e4a2f5b42d010409c39;p=binutils-gdb.git tui-disasm: Fix window content buffer overrun A user reported a GDB crash with TUI when trying to debug a function with a long demangled C++ method name. It turned out that the logic for displaying the TUI disassembly window has a bug that can cause a buffer overrun, possibly overwriting GDB-internal data structures. In particular, the logic performs an unguarded strcpy. Another (harmless) bug in tui_alloc_source_buffer causes the buffer to be two lines longer than needed. This may have made the crash appear less frequently. gdb/ChangeLog: * tui/tui-disasm.c (tui_set_disassem_content): Fix line buffer overrun due to unchecked strcpy. gdb/testsuite/ChangeLog: * gdb.base/tui-layout.c: New file. * gdb.base/tui-layout.exp: Use tui-layout.c, to ensure that the disassembly window contains very long lines. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 3b3fea15a24..b6bd2c1a9f4 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +2016-11-09 Andreas Arnez + + * tui/tui-disasm.c (tui_set_disassem_content): Fix line buffer + overrun due to unchecked strcpy. + 2016-11-09 Tristan Gingold * darwin-nat.c (find_inferior_task_it): Fix indentation. diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index b5319ae00d7..f3cb971478c 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2016-11-09 Andreas Arnez + + * gdb.base/tui-layout.c: New file. + * gdb.base/tui-layout.exp: Use tui-layout.c, to ensure that the + disassembly window contains very long lines. + 2016-11-08 Tom Tromey * gdb.python/py-value.exp (test_value_creation): Make "long" test diff --git a/gdb/testsuite/gdb.base/tui-layout.c b/gdb/testsuite/gdb.base/tui-layout.c new file mode 100644 index 00000000000..4049f9bb653 --- /dev/null +++ b/gdb/testsuite/gdb.base/tui-layout.c @@ -0,0 +1,47 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2016 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#define LONGER_NAME(x) x ## x +#define LONGER(x) LONGER_NAME(x) +#define LONGNAME1 d_this_identifier_of_32_chars_an +#define LONGNAME2 LONGER (LONGER (LONGER (LONGER (LONGER (LONGNAME1))))) + +/* Construct a long identifier name. If SHORT_IDENTIFIERS is set, limit + it to 1024 chars. */ + +#ifdef SHORT_IDENTIFIERS +#define LONGNAME3 LONGNAME2 +#else +#define LONGNAME3 LONGER (LONGER (LONGER (LONGER (LONGER (LONGNAME2))))) +#endif + +void LONGNAME3 (void); + +int +main () +{ + LONGNAME3 (); + return 0; +} + +/* Function with a long name. Placing it after main makes it more likely + to be shown in the disassembly window on startup. */ + +void +LONGNAME3 (void) +{ +} diff --git a/gdb/testsuite/gdb.base/tui-layout.exp b/gdb/testsuite/gdb.base/tui-layout.exp index 43b3a4fc57e..d8cd228fb54 100644 --- a/gdb/testsuite/gdb.base/tui-layout.exp +++ b/gdb/testsuite/gdb.base/tui-layout.exp @@ -13,12 +13,23 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -standard_testfile start.c +standard_testfile -if { [prepare_for_testing ${testfile}.exp ${testfile} $srcfile] } { - return -1 +set ccopts {debug quiet} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "$binfile" \ + executable $ccopts] != "" } { + # Maybe the compiler can't handle arbitrarily long identfier names. + # Try with a shorter version. + lappend ccopts "additional_flags=-DSHORT_IDENTIFIERS" + if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "$binfile" \ + executable $ccopts] != "" } { + untested "compile" + return -1 + } } +clean_restart "$binfile" + if {[skip_tui_tests]} { # TUI support is disabled. Check for error message. gdb_test "layout asm" "Undefined command: \"layout\". Try \"help\"." diff --git a/gdb/tui/tui-disasm.c b/gdb/tui/tui-disasm.c index 29c144336ea..5368aa4f47b 100644 --- a/gdb/tui/tui-disasm.c +++ b/gdb/tui/tui-disasm.c @@ -172,7 +172,7 @@ tui_set_disassem_content (struct gdbarch *gdbarch, CORE_ADDR pc) enum tui_status ret = TUI_FAILURE; int i; int offset = TUI_DISASM_WIN->detail.source_info.horizontal_offset; - int max_lines; + int max_lines, line_width; CORE_ADDR cur_pc; struct tui_gen_win_info *locator = tui_locator_win_info_ptr (); int tab_len = tui_default_tab_len (); @@ -193,8 +193,9 @@ tui_set_disassem_content (struct gdbarch *gdbarch, CORE_ADDR pc) TUI_DISASM_WIN->detail.source_info.start_line_or_addr.u.addr = pc; cur_pc = locator->content[0]->which_element.locator.addr; - max_lines = TUI_DISASM_WIN->generic.height - 2; /* Account for - hilite. */ + /* Window size, excluding highlight box. */ + max_lines = TUI_DISASM_WIN->generic.height - 2; + line_width = TUI_DISASM_WIN->generic.width - 2; /* Get temporary table that will hold all strings (addr & insn). */ asm_lines = XALLOCAVEC (struct tui_asm_line, max_lines); @@ -233,20 +234,15 @@ tui_set_disassem_content (struct gdbarch *gdbarch, CORE_ADDR pc) src = &element->which_element.source; strcpy (line, asm_lines[i].addr_string); cur_len = strlen (line); - - /* Add spaces to make the instructions start on the same - column. */ - while (cur_len < insn_pos) - { - strcat (line, " "); - cur_len++; - } - - strcat (line, asm_lines[i].insn); + memset (line + cur_len, ' ', insn_pos - cur_len); + strcpy (line + insn_pos, asm_lines[i].insn); /* Now copy the line taking the offset into account. */ if (strlen (line) > offset) - strcpy (src->line, &line[offset]); + { + strncpy (src->line, &line[offset], line_width); + src->line[line_width] = '\0'; + } else src->line[0] = '\0';