From: Joel Brobecker <brobecker@gnat.com>
To: gdb-patches@sources.redhat.com
Subject: [RFA] GDB/622 - clear current breakpoint in commands causes trouble
Date: Wed, 31 Jul 2002 13:09:00 -0000 [thread overview]
Message-ID: <20020731195012.GK683@gnat.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 1875 bytes --]
As described in PR GDB/622:
Using the program in the gdb.base/commands.exp testcase, the following
session shows that clearing the current breakpoint inside its commands
list causes a memory-corruption problem:
(gdb) b factorial
Breakpoint 1 at 0x8048582: file ./gdb.base/run.c, line 77.
(gdb) commands
Type commands for when breakpoint 1 is hit, one per line.
End with a line saying just "end".
>silent
>printf "factorial command-list executed\n"
>clear factorial
>cont
>end
(gdb) run 1
Starting program: [...]/gdb.base/commands 1
factorial command-list executed
warning: Invalid control type in command structure. <<<--- (1)
(gdb)
(1) shows that the command-list becomes corrupted, and as a consequence,
the execution is not resumed. Instead, the expected output from the run
command is:
Starting program: [...]/gdb.base/run 1
factorial command-list executed
1
Program exited normally.
(gdb)
The fix consists into executing a copy of the commands list, to protect
this execution from using a list that has been freed. The attached patch
introduces no regression. A new test has also been added to commands.exp.
Ok to apply?
2002-07-31 Joel Brobecker <brobecker@gnat.com>
* cli/cli-scripts.c (copy_command_lines): New function.
(make_cleanup_free_command_lines): Make this function non static.
* defs.h (copy_command_lines): Add definition.
(make_cleanup_free_command_lines): Add definition.
* breakpoint.c (bpstat_do_actions): Execute a temporary copy of
the command-list associated to each breakpoint hit, in order to
avoid accessing a dangling pointer, in case one of the commands
in the list causes the breakpoint to be deleted.
Thanks,
--
Joel
[-- Attachment #2: clear_in_commands.diff --]
[-- Type: text/plain, Size: 6914 bytes --]
Index: cli/cli-script.c
===================================================================
RCS file: /cvs/src/src/gdb/cli/cli-script.c,v
retrieving revision 1.13
diff -c -3 -p -r1.13 cli-script.c
*** cli/cli-script.c 30 Jul 2002 13:45:14 -0000 1.13
--- cli/cli-script.c 31 Jul 2002 19:49:40 -0000
*************** extern void do_restore_instream_cleanup
*** 42,49 ****
/* Prototypes for local functions */
! static struct cleanup *
! make_cleanup_free_command_lines (struct command_line **arg);
static enum command_control_type
recurse_read_control_structure (struct command_line *current_cmd);
--- 42,48 ----
/* Prototypes for local functions */
! struct cleanup *make_cleanup_free_command_lines (struct command_line **arg);
static enum command_control_type
recurse_read_control_structure (struct command_line *current_cmd);
*************** do_free_command_lines_cleanup (void *arg
*** 1007,1016 ****
free_command_lines (arg);
}
! static struct cleanup *
make_cleanup_free_command_lines (struct command_line **arg)
{
return make_cleanup (do_free_command_lines_cleanup, arg);
}
\f
static void
--- 1006,1045 ----
free_command_lines (arg);
}
! struct cleanup *
make_cleanup_free_command_lines (struct command_line **arg)
{
return make_cleanup (do_free_command_lines_cleanup, arg);
+ }
+
+ struct command_line *
+ copy_command_lines (struct command_line *cmds)
+ {
+ struct command_line *result = NULL;
+
+ if (cmds)
+ {
+ result = (struct command_line *) xmalloc (sizeof (struct command_line));
+
+ result->next = copy_command_lines (cmds->next);
+ result->line = strdup (cmds->line);
+ result->control_type = cmds->control_type;
+ result->body_count = cmds->body_count;
+ if (cmds->body_count > 0)
+ {
+ int i;
+
+ result->body_list = (struct command_line **)
+ xmalloc (sizeof (struct command_line *) * cmds->body_count);
+
+ for (i = 0; i < cmds->body_count; i++)
+ result->body_list[i] = copy_command_lines (cmds->body_list[i]);
+ }
+ else
+ result->body_list = NULL;
+ }
+
+ return result;
}
\f
static void
Index: defs.h
===================================================================
RCS file: /cvs/src/src/gdb/defs.h,v
retrieving revision 1.93
diff -c -3 -p -r1.93 defs.h
*** defs.h 24 Jul 2002 22:46:48 -0000 1.93
--- defs.h 31 Jul 2002 19:49:40 -0000
*************** struct command_line
*** 653,658 ****
--- 653,661 ----
extern struct command_line *read_command_lines (char *, int);
extern void free_command_lines (struct command_line **);
+ extern struct cleanup *
+ make_cleanup_free_command_lines (struct command_line **arg);
+ extern struct command_line *copy_command_lines (struct command_line *);
/* To continue the execution commands when running gdb asynchronously.
A continuation structure contains a pointer to a function to be called
Index: breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.78
diff -c -3 -p -r1.78 breakpoint.c
*** breakpoint.c 26 Jun 2002 05:20:04 -0000 1.78
--- breakpoint.c 31 Jul 2002 19:49:45 -0000
*************** top:
*** 1882,1888 ****
breakpoint_proceeded = 0;
for (; bs != NULL; bs = bs->next)
{
! cmd = bs->commands;
while (cmd != NULL)
{
execute_control_command (cmd);
--- 1882,1892 ----
breakpoint_proceeded = 0;
for (; bs != NULL; bs = bs->next)
{
! /* Use a temporary copy of the commands, as one command in the list
! may cause this breakpoint and its commands to be deleted. */
! cmd = copy_command_lines (bs->commands);
! make_cleanup_free_command_lines (&cmd);
!
while (cmd != NULL)
{
execute_control_command (cmd);
Index: testsuite/gdb.base/commands.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/commands.exp,v
retrieving revision 1.10
diff -c -3 -p -r1.10 commands.exp
*** testsuite/gdb.base/commands.exp 13 Dec 2001 22:42:23 -0000 1.10
--- testsuite/gdb.base/commands.exp 31 Jul 2002 19:49:45 -0000
*************** proc deprecated_command_test {} {
*** 440,445 ****
--- 440,503 ----
"deprecate with no arguments"
}
+ proc bp_deleted_in_command_test {} {
+ global gdb_prompt
+
+ gdb_test "set args 1" "" "set args in bp_deleted_in_command_test"
+ delete_breakpoints
+
+ # Create a breakpoint, and associate a command-list to it, with
+ # one command that deletes this breakpoint.
+ gdb_test "break factorial" \
+ "Breakpoint \[0-9\]+ at .*: file .*/run.c, line \[0-9\]+\." \
+ "breakpoint in bp_deleted_in_command_test"
+
+ send_gdb "commands\n"
+ gdb_expect {
+ -re "Type commands for when breakpoint .* is hit, one per line.*>" {
+ pass "begin commands in bp_deleted_in_command_test"
+ }
+ -re "$gdb_prompt $" {fail "begin commands in bp_deleted_in_command_test"}
+ timeout {fail "(timeout) begin commands bp_deleted_in_command_test"}
+ }
+ send_gdb "silent\n"
+ gdb_expect {
+ -re ">" {pass "add silent command"}
+ -re "$gdb_prompt $" {fail "add silent command"}
+ timeout {fail "(timeout) add silent command"}
+ }
+ send_gdb "printf \"factorial command-list executed\\n\"\n"
+ gdb_expect {
+ -re ">" {pass "add printf command"}
+ -re "$gdb_prompt $" {fail "add printf command"}
+ timeout {fail "(timeout) add printf command"}
+ }
+ send_gdb "clear factorial\n"
+ gdb_expect {
+ -re ">" {pass "add clear command"}
+ -re "$gdb_prompt $" {fail "add clear command"}
+ timeout {fail "(timeout) add clear command"} }
+ send_gdb "cont\n"
+ gdb_expect {
+ -re ">" {pass "add cont command"}
+ -re "$gdb_prompt $" {fail "add cont command"}
+ timeout {fail "(timeout) add cont command"} }
+ send_gdb "end\n"
+ gdb_expect {
+ -re "$gdb_prompt $" {pass "end commands"}
+ timeout {fail "(timeout) end commands"}
+ }
+
+ gdb_run_cmd
+ gdb_expect {
+ -re ".*factorial command-list executed.*1.*Program exited normally.*" {
+ pass "run factorial until breakpoint"
+ }
+ timeout { fail "(timeout) run factorial until breakpoint" }
+ }
+
+ }
+
gdbvar_simple_if_test
gdbvar_simple_while_test
*************** user_defined_command_test
*** 454,456 ****
--- 512,515 ----
watchpoint_command_test
test_command_prompt_position
deprecated_command_test
+ bp_deleted_in_command_test
next reply other threads:[~2002-07-31 19:50 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-07-31 13:09 Joel Brobecker [this message]
2002-08-20 6:27 ` Joel Brobecker
2002-08-22 15:01 ` Michael Snyder
2002-08-23 11:12 ` Don Howard
2002-08-24 2:17 ` [RFA] GDB/622 - clear current breakpoint in commands causestrouble Michael Snyder
2002-08-26 15:31 ` [RFA] GDB/622 - clear current breakpoint in commands causes trouble Kevin Buettner
2002-08-27 15:28 ` Andrew Cagney
2002-08-22 18:53 ` Michael Snyder
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20020731195012.GK683@gnat.com \
--to=brobecker@gnat.com \
--cc=gdb-patches@sources.redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox