aboutsummaryrefslogtreecommitdiff
path: root/gdb/python
diff options
context:
space:
mode:
authorMarco Barisione <mbarisione@undo.io>2021-05-12 11:19:22 +0100
committerMarco Barisione <mbarisione@undo.io>2021-05-12 11:19:22 +0100
commit2f822da535ba9b159174d02d7114b4fc4f7c8818 (patch)
tree7014b48d9f7893385ed27091caa75c28964c3514 /gdb/python
parentf0bbe8bab84e9b9dc5367a5fe1d0b8d233bf213c (diff)
downloadgdb-2f822da535ba9b159174d02d7114b4fc4f7c8818.zip
gdb-2f822da535ba9b159174d02d7114b4fc4f7c8818.tar.gz
gdb-2f822da535ba9b159174d02d7114b4fc4f7c8818.tar.bz2
gdb: generate the prefix name for prefix commands on demand
Previously, the prefixname field of struct cmd_list_element was manually set for prefix commands. This seems verbose and error prone as it required every single call to functions adding prefix commands to specify the prefix name while the same information can be easily generated. Historically, this was not possible as the prefix field was null for many commands, but this was fixed in commit 3f4d92ebdf7f848b5ccc9e8d8e8514c64fde1183 by Philippe Waroquiers, so we can rely on the prefix field being set when generating the prefix name. This commit also fixes a use after free in this scenario: * A command gets created via Python (using the gdb.Command class). The prefix name member is dynamically allocated. * An alias to the new command is created. The alias's prefixname is set to point to the prefixname for the original command with a direct assignment. * A new command with the same name as the Python command is created. * The object for the original Python command gets freed and its prefixname gets freed as well. * The alias is updated to point to the new command, but its prefixname is not updated so it keeps pointing to the freed one. gdb/ChangeLog: * command.h (add_prefix_cmd): Remove the prefixname argument as it can now be generated automatically. Update all callers. (add_basic_prefix_cmd): Ditto. (add_show_prefix_cmd): Ditto. (add_prefix_cmd_suppress_notification): Ditto. (add_abbrev_prefix_cmd): Ditto. * cli/cli-decode.c (add_prefix_cmd): Ditto. (add_basic_prefix_cmd): Ditto. (add_show_prefix_cmd): Ditto. (add_prefix_cmd_suppress_notification): Ditto. (add_prefix_cmd_suppress_notification): Ditto. (add_abbrev_prefix_cmd): Ditto. * cli/cli-decode.h (struct cmd_list_element): Replace the prefixname member variable with a method which generates the prefix name at runtime. Update all code reading the prefix name to use the method, and remove all code setting it. * python/py-cmd.c (cmdpy_destroyer): Remove code to free the prefixname member as it's now a method. (cmdpy_function): Determine if the command is a prefix by looking at prefixlist, not prefixname.
Diffstat (limited to 'gdb/python')
-rw-r--r--gdb/python/py-cmd.c51
-rw-r--r--gdb/python/python.c6
2 files changed, 14 insertions, 43 deletions
diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
index f4d3dcc..9833bf8 100644
--- a/gdb/python/py-cmd.c
+++ b/gdb/python/py-cmd.c
@@ -95,9 +95,6 @@ cmdpy_destroyer (struct cmd_list_element *self, void *context)
/* Release our hold on the command object. */
gdbpy_ref<cmdpy_object> cmd ((cmdpy_object *) context);
cmd->command = NULL;
-
- /* We may have allocated the prefix name. */
- xfree ((char *) self->prefixname);
}
/* Called by gdb to invoke the command. */
@@ -114,7 +111,7 @@ cmdpy_function (struct cmd_list_element *command,
error (_("Invalid invocation of Python command object."));
if (! PyObject_HasAttr ((PyObject *) obj, invoke_cst))
{
- if (obj->command->prefixname)
+ if (obj->command->prefixlist != nullptr)
{
/* A prefix command does not need an invoke method. */
return;
@@ -438,11 +435,11 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
int completetype = -1;
char *docstring = NULL;
struct cmd_list_element **cmd_list;
- char *cmd_name, *pfx_name;
+ char *cmd_name;
static const char *keywords[] = { "name", "command_class", "completer_class",
"prefix", NULL };
- PyObject *is_prefix = NULL;
- int cmp;
+ PyObject *is_prefix_obj = NULL;
+ bool is_prefix = false;
if (obj->command)
{
@@ -455,7 +452,7 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "si|iO",
keywords, &name, &cmdtype,
- &completetype, &is_prefix))
+ &completetype, &is_prefix_obj))
return -1;
if (cmdtype != no_class && cmdtype != class_run
@@ -481,39 +478,17 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
if (! cmd_name)
return -1;
- pfx_name = NULL;
- if (is_prefix != NULL)
+ if (is_prefix_obj != NULL)
{
- cmp = PyObject_IsTrue (is_prefix);
- if (cmp == 1)
- {
- int i, out;
-
- /* Make a normalized form of the command name. */
- pfx_name = (char *) xmalloc (strlen (name) + 2);
-
- i = 0;
- out = 0;
- while (name[i])
- {
- /* Skip whitespace. */
- while (name[i] == ' ' || name[i] == '\t')
- ++i;
- /* Copy non-whitespace characters. */
- while (name[i] && name[i] != ' ' && name[i] != '\t')
- pfx_name[out++] = name[i++];
- /* Add a single space after each word -- including the final
- word. */
- pfx_name[out++] = ' ';
- }
- pfx_name[out] = '\0';
- }
- else if (cmp < 0)
+ int cmp = PyObject_IsTrue (is_prefix_obj);
+ if (cmp < 0)
{
xfree (cmd_name);
return -1;
}
+ is_prefix = cmp > 0;
}
+
if (PyObject_HasAttr (self, gdbpy_doc_cst))
{
gdbpy_ref<> ds_obj (PyObject_GetAttr (self, gdbpy_doc_cst));
@@ -524,7 +499,6 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
if (docstring == NULL)
{
xfree (cmd_name);
- xfree (pfx_name);
return -1;
}
}
@@ -538,7 +512,7 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
{
struct cmd_list_element *cmd;
- if (pfx_name)
+ if (is_prefix)
{
int allow_unknown;
@@ -547,7 +521,7 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
allow_unknown = PyObject_HasAttr (self, invoke_cst);
cmd = add_prefix_cmd (cmd_name, (enum command_class) cmdtype,
NULL, docstring, &obj->sub_list,
- pfx_name, allow_unknown, cmd_list);
+ allow_unknown, cmd_list);
}
else
cmd = add_cmd (cmd_name, (enum command_class) cmdtype,
@@ -571,7 +545,6 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
{
xfree (cmd_name);
xfree (docstring);
- xfree (pfx_name);
gdbpy_convert_exception (except);
return -1;
}
diff --git a/gdb/python/python.c b/gdb/python/python.c
index c46d68b..4cea83c 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -1936,13 +1936,11 @@ This command is only a placeholder.")
/* Add set/show python print-stack. */
add_basic_prefix_cmd ("python", no_class,
_("Prefix command for python preference settings."),
- &user_show_python_list, "show python ", 0,
- &showlist);
+ &user_show_python_list, 0, &showlist);
add_show_prefix_cmd ("python", no_class,
_("Prefix command for python preference settings."),
- &user_set_python_list, "set python ", 0,
- &setlist);
+ &user_set_python_list, 0, &setlist);
add_setshow_enum_cmd ("print-stack", no_class, python_excp_enums,
&gdbpy_should_print_stack, _("\