From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4113 invoked by alias); 28 Jun 2010 14:06:37 -0000 Received: (qmail 3899 invoked by uid 22791); 28 Jun 2010 14:06:36 -0000 X-SWARE-Spam-Status: No, hits=-5.8 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,TW_BJ,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 28 Jun 2010 14:06:30 +0000 Received: from int-mx04.intmail.prod.int.phx2.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.17]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o5SE6S1Z020698 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 28 Jun 2010 10:06:28 -0400 Received: from host0.dyn.jankratochvil.net (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx04.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o5SE6QXl018883 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 28 Jun 2010 10:06:27 -0400 Received: from host0.dyn.jankratochvil.net (localhost [127.0.0.1]) by host0.dyn.jankratochvil.net (8.14.4/8.14.4) with ESMTP id o5SE6PTb031218; Mon, 28 Jun 2010 16:06:26 +0200 Received: (from jkratoch@localhost) by host0.dyn.jankratochvil.net (8.14.4/8.14.4/Submit) id o5SE6Pc1031217; Mon, 28 Jun 2010 16:06:25 +0200 Date: Mon, 28 Jun 2010 14:06:00 -0000 From: Jan Kratochvil To: gdb-patches@sourceware.org Cc: Chris Moller Subject: [patch] Fix memory corruption on aborted object print Message-ID: <20100628140625.GA24646@host0.dyn.jankratochvil.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-12-10) X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2010-06/txt/msg00632.txt.bz2 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 to continue, or q 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 to continue, or q 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 : (gdb) p c $4 = {loooooooooooooooooooooooooooooooooooooooooooooong = 0, static field = } 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 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 * cp-valprint.c (cp_print_value_fields) : Call obstack_begin after each obstack_free. gdb/testsuite/ 2010-06-28 Jan Kratochvil * 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 . */ + +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 . + +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 to continue, or q 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"