Skip to content

Commit 01a4035

Browse files
lu4nxEli-Zaretskii
authored andcommitted
Fix etags local command injection vulnerability
* lib-src/etags.c: (escape_shell_arg_string): New function. (process_file_name): Use it to quote file names passed to the shell. (Bug#59817)
1 parent ed47344 commit 01a4035

File tree

1 file changed

+58
-5
lines changed

1 file changed

+58
-5
lines changed

lib-src/etags.c

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@ static void invalidate_nodes (fdesc *, node **);
401401
static void put_entries (node *);
402402
static void cleanup_tags_file (char const * const, char const * const);
403403

404+
static char *escape_shell_arg_string (char *);
404405
static void do_move_file (const char *, const char *);
405406
static char *concat (const char *, const char *, const char *);
406407
static char *skip_spaces (char *);
@@ -1713,13 +1714,16 @@ process_file_name (char *file, language *lang)
17131714
else
17141715
{
17151716
#if MSDOS || defined (DOS_NT)
1716-
char *cmd1 = concat (compr->command, " \"", real_name);
1717-
char *cmd = concat (cmd1, "\" > ", tmp_name);
1717+
int buf_len = strlen (compr->command) + strlen (" \"\" > \"\"") + strlen (real_name) + strlen (tmp_name) + 1;
1718+
char *cmd = xmalloc (buf_len);
1719+
snprintf (cmd, buf_len, "%s \"%s\" > \"%s\"", compr->command, real_name, tmp_name);
17181720
#else
1719-
char *cmd1 = concat (compr->command, " '", real_name);
1720-
char *cmd = concat (cmd1, "' > ", tmp_name);
1721+
char *new_real_name = escape_shell_arg_string (real_name);
1722+
char *new_tmp_name = escape_shell_arg_string (tmp_name);
1723+
int buf_len = strlen (compr->command) + strlen (" > ") + strlen (new_real_name) + strlen (new_tmp_name) + 1;
1724+
char *cmd = xmalloc (buf_len);
1725+
snprintf (cmd, buf_len, "%s %s > %s", compr->command, new_real_name, new_tmp_name);
17211726
#endif
1722-
free (cmd1);
17231727
inf = (system (cmd) == -1
17241728
? NULL
17251729
: fopen (tmp_name, "r" FOPEN_BINARY));
@@ -7707,6 +7711,55 @@ etags_mktmp (void)
77077711
return templt;
77087712
}
77097713

7714+
/*
7715+
* Adds single quotes around a string, if found single quotes, escaped it.
7716+
* Return a newly-allocated string.
7717+
*
7718+
* For example:
7719+
* escape_shell_arg_string("test.txt") => 'test.txt'
7720+
* escape_shell_arg_string("'test.txt") => ''\''test.txt'
7721+
*/
7722+
static char *
7723+
escape_shell_arg_string (char *str)
7724+
{
7725+
char *p = str;
7726+
int need_space = 2; /* ' at begin and end */
7727+
7728+
while (*p != '\0')
7729+
{
7730+
if (*p == '\'')
7731+
need_space += 4; /* ' to '\'', length is 4 */
7732+
else
7733+
need_space++;
7734+
7735+
p++;
7736+
}
7737+
7738+
char *new_str = xnew (need_space + 1, char);
7739+
new_str[0] = '\'';
7740+
new_str[need_space-1] = '\'';
7741+
7742+
int i = 1; /* skip first byte */
7743+
p = str;
7744+
while (*p != '\0')
7745+
{
7746+
new_str[i] = *p;
7747+
if (*p == '\'')
7748+
{
7749+
new_str[i+1] = '\\';
7750+
new_str[i+2] = '\'';
7751+
new_str[i+3] = '\'';
7752+
i += 3;
7753+
}
7754+
7755+
i++;
7756+
p++;
7757+
}
7758+
7759+
new_str[need_space] = '\0';
7760+
return new_str;
7761+
}
7762+
77107763
static void
77117764
do_move_file(const char *src_file, const char *dst_file)
77127765
{

0 commit comments

Comments
 (0)