Re: [PATCH] Fix segfault on empty else

Andrew STUBBS
2006-07-06T16:19:06Z

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

Daniel Jacobowitz wrote:
> Works fine for me - very clever. This patch is OK. I'd recommend two
> changes, at your discretion:
>
>> +send_gdb "if 1\necho true\\n\nelse\necho false\\n\nend\n"
>
> Due to the patterns you're matching, this is safe, but in general it's
> bad style to use send_gdb without a matching gdb_expect. If you use
> gdb_test with the third argument empty, it will not be registered
> as a "test", and no pass message will be issued - unless the test
> fails, that is. So this is useful for tests which aren't part of the
> testcase, and are always assumed to pass.

I could certainly do this.

>> +# with true condition
>> +send_gdb "if 1\nelse\nend\necho got here\\n\n"
>> +gdb_expect {
>
> gdb_test_multiple is a little nicer here. You can still supply your
> own eof handler; the only difference is that it will pick
> up other quirky bits like internal error messages (and the default
> timeout handler should be fine for you here).

I have tried to do this, but have hit trouble. Please find my best
effort attached.

The problem is that it now calls perror which means that any test that
fails due to a crash is marked UNRESOLVED, not FAIL. It also prevents
any further tests in the file from running. So the result is that
failures are not flagged up as clearly as they should be - you just get
one unresolved test case instead of the proper handful of failures that
would set the alarm bells ringing.

It does do the right thing when everything passes.

Andrew

[-- Attachment #2: ifelse.exp --]
[-- Type: text/plain, Size: 2991 bytes --]

# 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
if {[gdb_test_multiple "if 1\nend\necho got here\\n" "if 1 with empty body" {
-re ".*got here.*$gdb_prompt $" {pass "if 1 with empty body"}
}] != 0} {
gdb_exit
gdb_start
}

# with false condition
if {[gdb_test_multiple "if 0\nend\necho got here\\n" "if 0 with empty body" {
-re ".*got here.*$gdb_prompt $" {pass "if 0 with empty body"}
}] != 0} {
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).

gdb_test "if 1\necho true\\n\nelse\necho false\\n\nend" "true" ""

# with true condition
if {[gdb_test_multiple "if 1\nelse\nend\necho got here\\n" \
"if 1 .. else with empty body" {
-re ".*got here.*$gdb_prompt $" {pass "if 1 .. else with empty body"}
}
] != 0} {
gdb_exit
gdb_start
}

# dirty memory
gdb_test "if 1\necho true\\n\nelse\necho false\\n\nend" "true" ""

# with false condition
if {[gdb_test_multiple "if 0\nelse\nend\necho got here\\n" \
"if 0 .. else with empty body" {
-re ".*got here.*$gdb_prompt $" {pass "if 0 .. else with empty body"}
}] != 0} {
gdb_exit
gdb_start
}

gdb_test "set confirm off" "" ""

# Test that a define with an empty else can be replaced.
# If there is memory corruption then free will fail.
# dirty memory
gdb_test "if 1\necho true\\n\nelse\necho false\\n\nend" "true" ""
# create
gdb_test "define abc\nif 1\nelse\nend\nend" "" "create define with empty else"
# call
gdb_test "abc" "" "call original define"
# replace
gdb_test "define abc\necho got here\\n\nend" "" \
"replace define with if .. else with empty body"
# call
gdb_test "abc" "got here" "call replacement define"