This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[patch] Fix memory corruption on aborted object print
- From: Jan Kratochvil <jan dot kratochvil at redhat dot com>
- To: gdb-patches at sourceware dot org
- Cc: Chris Moller <cmoller at redhat dot com>
- Date: Mon, 28 Jun 2010 16:06:25 +0200
- Subject: [patch] Fix memory corruption on aborted object print
Hi,
obstack_free (obstack, NULL) frees the whole obstack, not just its content.
$ valgrind ./gdb -q -nx 1.o -ex 'set width 80' -ex 'set height 2'
==30259== Memcheck, a memory error detector
==30259== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==30259== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==30259== Command: ./gdb -q -nx 1.o -ex set\ width\ 80 -ex set\ height\ 2
==30259==
Reading symbols from 1.o...done.
(gdb) p c
$1 = {loooooooooooooooooooooooooooooooooooooooooooooong = 0, static field = {
---Type <return> to continue, or q <return> to quit---q
looQuit
(gdb) p c
$2 = {==30259== Invalid read of size 8
==30259== at 0x6E5F7F: cp_print_static_field (cp-valprint.c:588)
==30259== by 0x6E5165: cp_print_value_fields (cp-valprint.c:314)
==30259== by 0x6E55D0: cp_print_value_fields_rtti (cp-valprint.c:414)
==30259== by 0x6E3511: c_val_print (c-valprint.c:400)
==30259== by 0x5EF27D: val_print (valprint.c:347)
==30259== by 0x6E44FB: c_value_print (c-valprint.c:722)
==30259== by 0x5EF567: value_print (valprint.c:442)
==30259== by 0x5F1CFA: print_formatted (printcmd.c:325)
==30259== by 0x5F32ED: print_command_1 (printcmd.c:998)
==30259== by 0x5F3367: print_command (printcmd.c:1017)
==30259== by 0x5769DC: do_cfunc (cli-decode.c:67)
==30259== by 0x579AA3: cmd_func (cli-decode.c:1771)
==30259== Address 0x4ea9980 is 16 bytes inside a block of size 256 free'd
==30259== at 0x4A04D72: free (vg_replace_malloc.c:325)
==30259== by 0x416BF5: xfree (utils.c:1449)
==30259== by 0x3DECC7E3A4: obstack_free (obstack.c:367)
==30259== by 0x6E47A4: cp_print_value_fields (cp-valprint.c:168)
==30259== by 0x6E55D0: cp_print_value_fields_rtti (cp-valprint.c:414)
==30259== by 0x6E3511: c_val_print (c-valprint.c:400)
==30259== by 0x5EF27D: val_print (valprint.c:347)
==30259== by 0x6E44FB: c_value_print (c-valprint.c:722)
==30259== by 0x5EF567: value_print (valprint.c:442)
==30259== by 0x5F1CFA: print_formatted (printcmd.c:325)
==30259== by 0x5F32ED: print_command_1 (printcmd.c:998)
==30259== by 0x5F3367: print_command (printcmd.c:1017)
==30259==
loooooooooooooooooooooooooooooooooooooooooooooong = 0,
---Type <return> to continue, or q <return> to quit---
The testcase crashes on unpatched GDB on Fedora-13.x86_64 but I understand the
memory corruption crash may not be reproducible on different systems.
The bug exists already in gdb-7.1 but this testcase does not reproduce it there
as due to some different bug it just prints <optimized out>:
(gdb) p c
$4 = {loooooooooooooooooooooooooooooooooooooooooooooong = 0, static field = <optimized out>}
It is a regression since:
Re: Revised pr 9067 patch
http://sourceware.org/ml/gdb-patches/2010-02/msg00110.html
93a1fa4f1853fca63cb20e433d7c5df83fa140d8
2010-02-08 Chris Moller <cmoller@redhat.com>
PR gdb/9067
* cp-valprint.c (cp_print_value_fields) Fix use of obstacks.
cp_print_static_field) Fix use of obstacks.
No regressions on {x86_64,x86_64-m32,i686}-fedora13-linux-gnu.
Thanks,
Jan
gdb/
2010-06-28 Jan Kratochvil <jan.kratochvil@redhat.com>
* cp-valprint.c (cp_print_value_fields) <recurse == 0>: Call
obstack_begin after each obstack_free.
gdb/testsuite/
2010-06-28 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.cp/static-print-quit.exp, gdb.cp/static-print-quit.cc: New.
--- a/gdb/cp-valprint.c
+++ b/gdb/cp-valprint.c
@@ -164,10 +164,19 @@ cp_print_value_fields (struct type *type, struct type *real_type,
if (recurse == 0)
{
+ /* Any object can be left on obstacks only during an unexpected error. */
+
if (obstack_object_size (&dont_print_statmem_obstack) > 0)
- obstack_free (&dont_print_statmem_obstack, NULL);
+ {
+ obstack_free (&dont_print_statmem_obstack, NULL);
+ obstack_begin (&dont_print_statmem_obstack, 32 * sizeof (CORE_ADDR));
+ }
if (obstack_object_size (&dont_print_stat_array_obstack) > 0)
- obstack_free (&dont_print_stat_array_obstack, NULL);
+ {
+ obstack_free (&dont_print_stat_array_obstack, NULL);
+ obstack_begin (&dont_print_stat_array_obstack,
+ 32 * sizeof (struct type *));
+ }
}
fprintf_filtered (stream, "{");
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/static-print-quit.cc
@@ -0,0 +1,32 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2010 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 <http://www.gnu.org/licenses/>. */
+
+class D
+ {
+ public:
+ int loooooooooooooooooooooooooooooooooooooooooooooong;
+ };
+
+class C
+ {
+ public:
+ int loooooooooooooooooooooooooooooooooooooooooooooong;
+ static D field;
+ };
+
+D C::field;
+C c;
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/static-print-quit.exp
@@ -0,0 +1,50 @@
+# Copyright 2010 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 <http://www.gnu.org/licenses/>.
+
+if { [skip_cplus_tests] } { continue }
+
+set testfile static-print-quit
+set srcfile ${testfile}.cc
+set executable $testfile.o
+set objfile ${objdir}/${subdir}/${executable}
+
+if { [gdb_compile $srcdir/$subdir/$srcfile $objfile object {debug c++}] != ""} {
+ untested ${testfile}.exp
+ return -1
+}
+
+clean_restart $executable
+
+gdb_test_no_output "set width 80"
+gdb_test_no_output "set height 2"
+
+set test "print c"
+gdb_test_multiple $test $test {
+ -re " = \{loooooooooooooooooooooooooooooooooooooooooooooong = 0, static field = \{\r\n---Type <return> to continue, or q <return> to quit---$" {
+ pass $test
+ }
+ -re " to quit---$" {
+ fail $test
+ return -1
+ }
+}
+
+gdb_test "q" ".*"
+
+# Now the obstack is uninitialized. Excercise it.
+
+gdb_test_no_output "set pagination off"
+gdb_test "print c" ".*" "first print"
+gdb_test "print c" ".*" "second print"