gdb: make gdbpy_parse_command_name return a unique_xmalloc_ptr
This avoids some manual memory management. cmdpy_init correctly transfers ownership of the name to the cmd_list_element, as it sets the name_allocated flag. However, cmdpy_init (and add_setshow_generic) doesn't, it looks like the name is just leaked. This is a bit tricky, because it actually creates two commands (one set and one show), it would take a bit of refactoring of the command code to give each their own allocated copy. For now, just keep doing what the current code does but in a more explicit fashion, with an explicit release. gdb/ChangeLog: * python/python-internal.h (gdbpy_parse_command_name): Return gdb::unique_xmalloc_ptr. * python/py-cmd.c (gdbpy_parse_command_name): Likewise. (cmdpy_init): Adjust. * python/py-param.c (parmpy_init): Adjust. (add_setshow_generic): Take gdb::unique_xmalloc_ptr, release it when done. Change-Id: Iae5bc21fe2b22f12d5f954057b0aca7ca4cd3f0d
This commit is contained in:
parent
3db19b2d72
commit
4b8cb9dd9e
4 changed files with 61 additions and 54 deletions
|
@ -342,10 +342,10 @@ cmdpy_completer (struct cmd_list_element *command,
|
|||
|
||||
START_LIST is the list in which the search starts.
|
||||
|
||||
This function returns the xmalloc()d name of the new command. On
|
||||
error sets the Python error and returns NULL. */
|
||||
This function returns the name of the new command. On error sets the Python
|
||||
error and returns NULL. */
|
||||
|
||||
char *
|
||||
gdb::unique_xmalloc_ptr<char>
|
||||
gdbpy_parse_command_name (const char *name,
|
||||
struct cmd_list_element ***base_list,
|
||||
struct cmd_list_element **start_list)
|
||||
|
@ -354,7 +354,6 @@ gdbpy_parse_command_name (const char *name,
|
|||
int len = strlen (name);
|
||||
int i, lastchar;
|
||||
const char *prefix_text2;
|
||||
char *result;
|
||||
|
||||
/* Skip trailing whitespace. */
|
||||
for (i = len - 1; i >= 0 && (name[i] == ' ' || name[i] == '\t'); --i)
|
||||
|
@ -369,9 +368,10 @@ gdbpy_parse_command_name (const char *name,
|
|||
/* Find first character of the final word. */
|
||||
for (; i > 0 && valid_cmd_char_p (name[i - 1]); --i)
|
||||
;
|
||||
result = (char *) xmalloc (lastchar - i + 2);
|
||||
memcpy (result, &name[i], lastchar - i + 1);
|
||||
result[lastchar - i + 1] = '\0';
|
||||
|
||||
gdb::unique_xmalloc_ptr<char> result ((char *) xmalloc (lastchar - i + 2));
|
||||
memcpy (result.get (), &name[i], lastchar - i + 1);
|
||||
result.get ()[lastchar - i + 1] = '\0';
|
||||
|
||||
/* Skip whitespace again. */
|
||||
for (--i; i >= 0 && (name[i] == ' ' || name[i] == '\t'); --i)
|
||||
|
@ -390,7 +390,6 @@ gdbpy_parse_command_name (const char *name,
|
|||
{
|
||||
PyErr_Format (PyExc_RuntimeError, _("Could not find command prefix %s."),
|
||||
prefix_text.c_str ());
|
||||
xfree (result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -402,7 +401,6 @@ gdbpy_parse_command_name (const char *name,
|
|||
|
||||
PyErr_Format (PyExc_RuntimeError, _("'%s' is not a prefix command."),
|
||||
prefix_text.c_str ());
|
||||
xfree (result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -435,7 +433,6 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
|
|||
int completetype = -1;
|
||||
char *docstring = NULL;
|
||||
struct cmd_list_element **cmd_list;
|
||||
char *cmd_name;
|
||||
static const char *keywords[] = { "name", "command_class", "completer_class",
|
||||
"prefix", NULL };
|
||||
PyObject *is_prefix_obj = NULL;
|
||||
|
@ -474,19 +471,18 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
|
|||
return -1;
|
||||
}
|
||||
|
||||
cmd_name = gdbpy_parse_command_name (name, &cmd_list, &cmdlist);
|
||||
if (! cmd_name)
|
||||
gdb::unique_xmalloc_ptr<char> cmd_name
|
||||
= gdbpy_parse_command_name (name, &cmd_list, &cmdlist);
|
||||
if (cmd_name == nullptr)
|
||||
return -1;
|
||||
|
||||
if (is_prefix_obj != NULL)
|
||||
{
|
||||
int cmp = PyObject_IsTrue (is_prefix_obj);
|
||||
if (cmp < 0)
|
||||
{
|
||||
xfree (cmd_name);
|
||||
return -1;
|
||||
}
|
||||
is_prefix = cmp > 0;
|
||||
if (cmp < 0)
|
||||
return -1;
|
||||
|
||||
is_prefix = cmp > 0;
|
||||
}
|
||||
|
||||
if (PyObject_HasAttr (self, gdbpy_doc_cst))
|
||||
|
@ -497,10 +493,7 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
|
|||
{
|
||||
docstring = python_string_to_host_string (ds_obj.get ()).release ();
|
||||
if (docstring == NULL)
|
||||
{
|
||||
xfree (cmd_name);
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (! docstring)
|
||||
|
@ -519,14 +512,19 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
|
|||
/* If we have our own "invoke" method, then allow unknown
|
||||
sub-commands. */
|
||||
allow_unknown = PyObject_HasAttr (self, invoke_cst);
|
||||
cmd = add_prefix_cmd (cmd_name, (enum command_class) cmdtype,
|
||||
cmd = add_prefix_cmd (cmd_name.get (),
|
||||
(enum command_class) cmdtype,
|
||||
NULL, docstring, &obj->sub_list,
|
||||
allow_unknown, cmd_list);
|
||||
}
|
||||
else
|
||||
cmd = add_cmd (cmd_name, (enum command_class) cmdtype,
|
||||
cmd = add_cmd (cmd_name.get (), (enum command_class) cmdtype,
|
||||
docstring, cmd_list);
|
||||
|
||||
/* If successful, the above takes ownership of the name, since we set
|
||||
name_allocated, so release it. */
|
||||
cmd_name.release ();
|
||||
|
||||
/* There appears to be no API to set this. */
|
||||
cmd->func = cmdpy_function;
|
||||
cmd->destroyer = cmdpy_destroyer;
|
||||
|
@ -543,7 +541,6 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
|
|||
}
|
||||
catch (const gdb_exception &except)
|
||||
{
|
||||
xfree (cmd_name);
|
||||
xfree (docstring);
|
||||
gdbpy_convert_exception (except);
|
||||
return -1;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue