Re: [PATCH] Fix segfault on empty else

Andrew STUBBS
2006-06-21T10:50:50Z

[-- Attachment #1: Type: text/plain, Size: 889 bytes --]

Daniel Jacobowitz wrote:
> On Tue, Jun 20, 2006 at 03:33:37PM +0100, Andrew STUBBS wrote:
>> 2006-06-20 Andrew Stubbs <andrew.stubbs@st.com>
>>
>> * cli/cli-script.c (realloc_body_list): Zero new parts of body_list.
>
> OK, thanks!

Thanks, committed.

> Want to add a corresponding test? Though it likely wouldn't crash,
> unless you tried running the testsuite under valgrind.

How about the attached? It is somewhat tricky trying to reliably
reproduce the problem without valgrind, as you say.

I have put in a few commands that are intended to run through the same
code and will, most likely, allocate memory in the same place, in order
to ensure that the crash occurs. This is a little hopeful, but what else
can I do?

This works for me, but could you please confirm that it works in your
setup/host (without the patch to fix the problem of course).

Thanks

Andrew

[-- Attachment #2: empty-else-test.patch --]
[-- Type: text/plain, Size: 3985 bytes --]

2006-06-21 Andrew Stubbs <andrew.stubbs@st.com>

* gdb.base/ifelse.exp: New file.

Index: src/gdb/testsuite/gdb.base/ifelse.exp
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.base/ifelse.exp 2006-06-21 11:35:04.000000000 +0100
@@ -0,0 +1,138 @@
+# Copyright 2006 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# This test checks that the if .. else .. end construct works and may
+# contain empty bodies without crashing.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+gdb_exit
+gdb_start
+
+# First test that the if command works with an empty body
+# Test with different conditions because the body is ignored
+# if it is not executed.
+
+# with true condition
+send_gdb "if 1\nend\necho got here\\n\n"
+gdb_expect {
+ -re ".*got here.*$gdb_prompt $" {
+ pass "if 1 with empty body"
+ }
+ eof {
+ fail "if 1 with empty body (crash)"
+ gdb_exit
+ gdb_start
+ }
+ timeout {
+ fail "if 1 with empty body (timeout)"
+ gdb_exit
+ gdb_start
+ }
+}
+
+# with false condition
+send_gdb "if 0\nend\necho got here\\n\n"
+gdb_expect {
+ -re ".*got here.*$gdb_prompt $" {
+ pass "if 0 with empty body"
+ }
+ eof {
+ fail "if 0 with empty body (crash)"
+ gdb_exit
+ gdb_start
+ }
+ timeout {
+ fail "if 0 with empty body (timeout)"
+ gdb_exit
+ gdb_start
+ }
+}
+
+# Second, do the same tests with an empty else body.
+# This fails in GDB <=6.5
+
+# Unfortunately it was an uninitialised memory problem so
+# sometimes it just works. Preceed it with an if else end with
+# bodies and hopefully the memory with be dirty and the problem
+# will show itself (this works at time of writing).
+
+send_gdb "if 1\necho true\\n\nelse\necho false\\n\nend\n"
+
+# with true condition
+send_gdb "if 1\nelse\nend\necho got here\\n\n"
+gdb_expect {
+ -re ".*got here.*$gdb_prompt $" {
+ pass "if 1 .. else with empty body"
+ }
+ eof {
+ fail "if 1 .. else with empty body (crash)"
+ gdb_exit
+ gdb_start
+ }
+ timeout {
+ fail "if 1 .. else with empty body (timeout)"
+ gdb_exit
+ gdb_start
+ }
+}
+
+# dirty memory
+send_gdb "if 1\necho true\\n\nelse\necho false\\n\nend\n"
+
+# with false condition
+send_gdb "if 0\nelse\nend\necho got here\\n\n"
+gdb_expect {
+ -re ".*got here.*$gdb_prompt $" {
+ pass "if 0 .. else with empty body"
+ }
+ eof {
+ fail "if 0 .. else with empty body (crash)"
+ gdb_exit
+ gdb_start
+ }
+ timeout {
+ fail "if 0 .. else with empty body (timeout)"
+ gdb_exit
+ gdb_start
+ }
+}
+
+send_gdb "set confirm off\n"
+
+# Test that a define with an empty else can be replaced.
+# If there is memory corruption then free will fail.
+# dirty memory
+send_gdb "if 1\necho true\\n\nelse\necho false\\n\nend\n"
+# create
+send_gdb "define abc\nif 1\nelse\nend\nend\n"
+# replace
+send_gdb "define abc\necho got here\\n\nend\n"
+# call
+send_gdb "abc\n"
+gdb_expect {
+ -re ".*\[\r\n]got here\[\n\r].*$gdb_prompt $" {
+ pass "replace define with if .. else with empty body"
+ }
+ eof {
+ fail "replace define with if .. else with empty body (crash)"
+ }
+ timeout {
+ fail "replace define with if .. else with empty body (timeout)"
+ }
+}