Fix crash and memory leak in $aliasctl(COMMAND MATCH)

glob_commands() would run off the end of the irc_command array if given a match that matched
the last command.  It also leaked memory because it used m_s3cat() to construct the string,
then passed that to m_strdup().

This fixes these problems by reworking glob_commands(), and at the same time removes the use
of alloca() and wild_match() by using strncmp() instead to match the start of a string.  Move
glob_commands() to alias.c and make it static since it's only used for aliasctl().

Change the 'name' argument of find_command() and find_dll_command() to const char * at the same
time, so that glob_commands()'s prefix argument can be const char * too.
This commit is contained in:
Kevin Easton
2016-10-15 00:41:34 +11:00
parent dec7caafd0
commit 9a2792345f
5 changed files with 32 additions and 28 deletions

View File

@@ -1,5 +1,7 @@
[Changes 1.2.2]
* Fix crash and memory leak in $aliasctl(COMMAND MATCH). (caf)
* Fix memory leaks in /CDCC PLIST and /CDCC NOTICE. (caf)
* Rename reserved identifiers from irc_std.h to fix building on under

View File

@@ -258,8 +258,7 @@ extern void ame (char *, char *, char *, char *);
extern void unload_dll (char *, char *, char *, char *);
#endif
IrcCommand *BX_find_command (char *, int *);
char *glob_commands(char *, int *, int);
IrcCommand *BX_find_command (const char *, int *);
#define AWAY_ONE 0
#define AWAY_ALL 1

View File

@@ -627,7 +627,7 @@ extern Function_ptr *global;
#define io (*(void (*)(const char *))global[IRC_IO_FUNC])
/* commands.c */
#define find_command (*(IrcCommand *(*)(char *, int *))global[FIND_COMMAND_FUNC])
#define find_command (*(IrcCommand *(*)(const char *, int *))global[FIND_COMMAND_FUNC])
#define lock_stack_frame (*(void (*)(void ))global[LOCK_STACK_FRAME])
#define unlock_stack_frame (*(void (*)(void ))global[UNLOCK_STACK_FRAME])

View File

@@ -2227,14 +2227,36 @@ char *lookup_member(char *varname, char *var_args, char *ptr, char *args)
/****************************** ALIASCTL ************************************/
#define EMPTY empty_string
#define RETURN_EMPTY return m_strdup(EMPTY)
#define EMPTY_STRING m_strdup(EMPTY)
#define RETURN_EMPTY return EMPTY_STRING
#define RETURN_IF_EMPTY(x) if (empty( x )) RETURN_EMPTY
#define GET_INT_ARG(x, y) {RETURN_IF_EMPTY(y); x = my_atol(safe_new_next_arg(y, &y));}
#define GET_FLOAT_ARG(x, y) {RETURN_IF_EMPTY(y); x = atof(safe_new_next_arg(y, &y));}
#define GET_STR_ARG(x, y) {RETURN_IF_EMPTY(y); x = new_next_arg(y, &y);RETURN_IF_EMPTY(x);}
#define RETURN_STR(x) return m_strdup(x ? x : EMPTY)
#define RETURN_MSTR(x) return ((x) ? (x) : EMPTY_STRING)
#define RETURN_INT(x) return m_strdup(ltoa(x));
/* glob_commands()
* Returns a space-separated list of commands beginning with 'prefix'.
*/
static char *glob_commands(const char *prefix, int *cnt)
{
IrcCommand *var;
char *mylist = NULL;
const size_t prefix_len = strlen(prefix);
*cnt = 0;
/* let's do a command completion here */
for (var = find_command(prefix, cnt);
var && var->name && !strncmp(prefix, var->name, prefix_len);
var++)
{
m_s3cat(&mylist, space, var->name);
}
RETURN_MSTR(mylist);
}
/* Used by function_aliasctl */
/* MUST BE FIXED */
BUILT_IN_FUNCTION(aliasctl)
@@ -2321,7 +2343,7 @@ BUILT_IN_FUNCTION(aliasctl)
else if (list == VAR_ALIAS)
mlist = glob_assign_alias(listc, &num);
else if (list == -1)
return glob_commands(listc, &num, 0);
return glob_commands(listc, &num);
for (ctr = 0; ctr < num; ctr++)
{
@@ -2345,7 +2367,7 @@ BUILT_IN_FUNCTION(aliasctl)
else if (list == VAR_ALIAS)
mlist = pmatch_assign_alias(listc, &num);
else if (list == -1)
return glob_commands(listc, &num, 1);
return glob_commands(listc, &num);
for (ctr = 0; ctr < num; ctr++)
{

View File

@@ -153,7 +153,7 @@ char lame_wait_nick[] = "***LW***";
char wait_nick[] = "***W***";
#ifdef WANT_DLL
IrcCommandDll *find_dll_command (char *, int *);
IrcCommandDll *find_dll_command (const char *, int *);
IrcCommandDll *dll_commands = NULL;
#endif
@@ -904,25 +904,6 @@ BUILT_IN_COMMAND(init_ftp)
}
#endif
char *glob_commands(char *name, int *cnt, int pmatch)
{
IrcCommand *var = NULL;
char *loc_match;
char *mylist = NULL;
*cnt = 0;
/* let's do a command completion here */
if (!(var = find_command(name, cnt)))
return m_strdup(empty_string);
loc_match = alloca(strlen(name)+2);
sprintf(loc_match, "%s*", (name && *name) ? name : empty_string);
while (wild_match(loc_match, var->name))
{
m_s3cat(&mylist, space, var->name);
var++;
}
return m_strdup(mylist ? mylist : empty_string);
}
/*
* find_command: looks for the given name in the command list, returning a
* pointer to the first match and the number of matches in cnt. If no
@@ -932,7 +913,7 @@ char *mylist = NULL;
* returned and cnt is set to the number of matches * -1. Thus is 4 commands
* matched, but the first was as exact match, cnt is -4.
*/
IrcCommand *BX_find_command(char *com, int *cnt)
IrcCommand *BX_find_command(const char *com, int *cnt)
{
IrcCommand *retval;
int loc;
@@ -951,7 +932,7 @@ IrcCommand *BX_find_command(char *com, int *cnt)
}
#ifdef WANT_DLL
IrcCommandDll * find_dll_command(char *com, int *cnt)
IrcCommandDll *find_dll_command(const char *com, int *cnt)
{
int len = 0;