mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-05 23:23:09 +00:00
libdep plugin: fix bugs in parser and drop escaping
PR ld/31906 * libdep_plugin.c (str2vec): Fix bug where null byte was not copied on memmove during quote handling and escaping, causing repeat of the last character in the last argument. Fix buffer overflow in **res when arguments were separated by `\t` instead of ` `. Remove handling of the escape character `\`, as it made it impossible to specify paths containing `\` -- the implementation merely dropped `\`, and was affected by the memmove bug, so this should not be breaking; just single and double quotes are sufficient to deal with white space and quote characters, there is no need for escaping. Handle syntax errors on unterminated quotes. Make the parser linear time instead of quadratic.
This commit is contained in:
committed by
Nick Clifton
parent
e13c4e5890
commit
3af54857cd
@@ -132,88 +132,68 @@ get_libdeps (int fd)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Turn a string into an argvec. */
|
/* Parse arguments in-place as contiguous C-strings
|
||||||
static char **
|
and return the number of arguments. */
|
||||||
str2vec (char *in)
|
|
||||||
|
static int
|
||||||
|
parse_libdep (char *str)
|
||||||
{
|
{
|
||||||
char **res;
|
char *src, *dst;
|
||||||
char *s, *first, *end;
|
char quote;
|
||||||
char *sq, *dq;
|
int narg;
|
||||||
int i;
|
|
||||||
|
|
||||||
end = in + strlen (in);
|
src = dst = str;
|
||||||
s = in;
|
|
||||||
while (isspace ((unsigned char) *s)) s++;
|
|
||||||
first = s;
|
|
||||||
|
|
||||||
i = 1;
|
for (; isspace ((unsigned char) *src); ++src)
|
||||||
while ((s = strchr (s, ' ')))
|
;
|
||||||
|
|
||||||
|
if (*src == '\0')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
narg = 1;
|
||||||
|
quote = 0;
|
||||||
|
|
||||||
|
while (*src)
|
||||||
{
|
{
|
||||||
s++;
|
if (*src == '\'' || *src == '\"')
|
||||||
i++;
|
|
||||||
}
|
|
||||||
res = (char **)malloc ((i+1) * sizeof (char *));
|
|
||||||
if (!res)
|
|
||||||
return res;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
sq = NULL;
|
|
||||||
dq = NULL;
|
|
||||||
res[0] = first;
|
|
||||||
for (s = first; *s; s++)
|
|
||||||
{
|
|
||||||
if (*s == '\\')
|
|
||||||
{
|
{
|
||||||
memmove (s, s+1, end-s-1);
|
if (!quote)
|
||||||
end--;
|
quote = *src++;
|
||||||
}
|
else if (*src == quote)
|
||||||
if (isspace ((unsigned char) *s))
|
|
||||||
{
|
|
||||||
if (sq || dq)
|
|
||||||
continue;
|
|
||||||
*s++ = '\0';
|
|
||||||
while (isspace ((unsigned char) *s)) s++;
|
|
||||||
if (*s)
|
|
||||||
res[++i] = s;
|
|
||||||
}
|
|
||||||
if (*s == '\'' && !dq)
|
|
||||||
{
|
|
||||||
if (sq)
|
|
||||||
{
|
{
|
||||||
memmove (sq, sq+1, s-sq-1);
|
++src;
|
||||||
memmove (s-2, s+1, end-s-1);
|
quote = 0;
|
||||||
end -= 2;
|
|
||||||
s--;
|
|
||||||
sq = NULL;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
*dst++ = *src++;
|
||||||
sq = s;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (*s == '"' && !sq)
|
else if (!quote && isspace ((unsigned char) *src))
|
||||||
{
|
{
|
||||||
if (dq)
|
++narg;
|
||||||
{
|
++src;
|
||||||
memmove (dq, dq+1, s-dq-1);
|
*dst++ = '\0';
|
||||||
memmove (s-2, s+1, end-s-1);
|
for (; isspace ((unsigned char) *src); ++src);
|
||||||
end -= 2;
|
|
||||||
s--;
|
|
||||||
dq = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dq = s;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
*dst++ = *src++;
|
||||||
}
|
}
|
||||||
res[++i] = NULL;
|
|
||||||
return res;
|
*dst = '\0';
|
||||||
|
|
||||||
|
if (quote)
|
||||||
|
{
|
||||||
|
TV_MESSAGE (LDPL_WARNING,
|
||||||
|
"libdep syntax error: unterminated quoted string");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return narg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *prevfile;
|
static char *prevfile;
|
||||||
|
|
||||||
/* Standard plugin API registerable hook. */
|
/* Standard plugin API registerable hook. */
|
||||||
|
|
||||||
static enum ld_plugin_status
|
static enum ld_plugin_status
|
||||||
onclaim_file (const struct ld_plugin_input_file *file, int *claimed)
|
onclaim_file (const struct ld_plugin_input_file *file, int *claimed)
|
||||||
{
|
{
|
||||||
@@ -237,8 +217,8 @@ onclaim_file (const struct ld_plugin_input_file *file, int *claimed)
|
|||||||
return LDPS_ERR;
|
return LDPS_ERR;
|
||||||
|
|
||||||
/* This hook only gets called on actual object files.
|
/* This hook only gets called on actual object files.
|
||||||
* We have to examine the archive ourselves, to find
|
We have to examine the archive ourselves, to find
|
||||||
* our LIBDEPS member. */
|
our LIBDEPS member. */
|
||||||
rv = get_libdeps (file->fd);
|
rv = get_libdeps (file->fd);
|
||||||
if (rv == LDPS_ERR)
|
if (rv == LDPS_ERR)
|
||||||
return rv;
|
return rv;
|
||||||
@@ -256,51 +236,51 @@ onclaim_file (const struct ld_plugin_input_file *file, int *claimed)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Standard plugin API registerable hook. */
|
/* Standard plugin API registerable hook. */
|
||||||
|
|
||||||
static enum ld_plugin_status
|
static enum ld_plugin_status
|
||||||
onall_symbols_read (void)
|
onall_symbols_read (void)
|
||||||
{
|
{
|
||||||
linerec *lr;
|
linerec *lr;
|
||||||
char **vec;
|
int nargs;
|
||||||
|
char const *arg;
|
||||||
enum ld_plugin_status rv = LDPS_OK;
|
enum ld_plugin_status rv = LDPS_OK;
|
||||||
|
|
||||||
while ((lr = line_head))
|
while ((lr = line_head))
|
||||||
{
|
{
|
||||||
line_head = lr->next;
|
line_head = lr->next;
|
||||||
vec = str2vec (lr->line);
|
nargs = parse_libdep (lr->line);
|
||||||
if (vec)
|
arg = lr->line;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < nargs; i++, arg = strchr (arg, '\0') + 1)
|
||||||
{
|
{
|
||||||
int i;
|
if (arg[0] != '-')
|
||||||
for (i = 0; vec[i]; i++)
|
|
||||||
{
|
{
|
||||||
if (vec[i][0] != '-')
|
TV_MESSAGE (LDPL_WARNING, "ignoring libdep argument %s", arg);
|
||||||
{
|
fflush (NULL);
|
||||||
TV_MESSAGE (LDPL_WARNING, "ignoring libdep argument %s",
|
continue;
|
||||||
vec[i]);
|
|
||||||
fflush (NULL);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (vec[i][1] == 'l')
|
|
||||||
rv = tv_add_input_library (vec[i]+2);
|
|
||||||
else if (vec[i][1] == 'L')
|
|
||||||
rv = tv_set_extra_library_path (vec[i]+2);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TV_MESSAGE (LDPL_WARNING, "ignoring libdep argument %s",
|
|
||||||
vec[i]);
|
|
||||||
fflush (NULL);
|
|
||||||
}
|
|
||||||
if (rv != LDPS_OK)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
free (vec);
|
if (arg[1] == 'l')
|
||||||
|
rv = tv_add_input_library (arg + 2);
|
||||||
|
else if (arg[1] == 'L')
|
||||||
|
rv = tv_set_extra_library_path (arg + 2);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TV_MESSAGE (LDPL_WARNING, "ignoring libdep argument %s", arg);
|
||||||
|
fflush (NULL);
|
||||||
|
}
|
||||||
|
if (rv != LDPS_OK)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
free (lr);
|
free (lr);
|
||||||
}
|
}
|
||||||
|
|
||||||
line_tail = NULL;
|
line_tail = NULL;
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Standard plugin API registerable hook. */
|
/* Standard plugin API registerable hook. */
|
||||||
|
|
||||||
static enum ld_plugin_status
|
static enum ld_plugin_status
|
||||||
oncleanup (void)
|
oncleanup (void)
|
||||||
{
|
{
|
||||||
@@ -309,20 +289,25 @@ oncleanup (void)
|
|||||||
free (prevfile);
|
free (prevfile);
|
||||||
prevfile = NULL;
|
prevfile = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line_head)
|
if (line_head)
|
||||||
{
|
{
|
||||||
linerec *lr;
|
linerec *lr;
|
||||||
|
|
||||||
while ((lr = line_head))
|
while ((lr = line_head))
|
||||||
{
|
{
|
||||||
line_head = lr->next;
|
line_head = lr->next;
|
||||||
free (lr);
|
free (lr);
|
||||||
}
|
}
|
||||||
|
|
||||||
line_tail = NULL;
|
line_tail = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return LDPS_OK;
|
return LDPS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Standard plugin API entry point. */
|
/* Standard plugin API entry point. */
|
||||||
|
|
||||||
enum ld_plugin_status
|
enum ld_plugin_status
|
||||||
onload (struct ld_plugin_tv *tv)
|
onload (struct ld_plugin_tv *tv)
|
||||||
{
|
{
|
||||||
@@ -351,6 +336,7 @@ onload (struct ld_plugin_tv *tv)
|
|||||||
(*tv_register_all_symbols_read) (onall_symbols_read);
|
(*tv_register_all_symbols_read) (onall_symbols_read);
|
||||||
(*tv_register_cleanup) (oncleanup);
|
(*tv_register_cleanup) (oncleanup);
|
||||||
}
|
}
|
||||||
|
|
||||||
fflush (NULL);
|
fflush (NULL);
|
||||||
return LDPS_OK;
|
return LDPS_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user