This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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"


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]