Synchronize libiberty with gcc and add --no-recruse-limit option to tools that support name demangling.

This patch addresses the multitude of bug reports about resource exhaustion
in libiberty's name demangling code.  It adds a limit to the amount of
recursion that is allowed, before an error is triggered.  It also adds a
new demangling option to disable this limit.  (The limit is enabled by
default).

	PR 87681
	PR 87675
	PR 87636
	PR 87335
libiberty * cp-demangle.h (struct d_info): Add recursion_limit field.
	* cp-demangle.c (d_function_type): If the recursion limit is
	enabled and reached, return with a failure result.
        (d_demangle_callback): If the recursion limit is enabled, check
	for a mangled string that is so long that there is not enough
	stack space for the local arrays.
        * cplus-dem.c (struct work): Add recursion_level field.
	(demangle_nested_args): If the recursion limit is enabled and
	reached, return with a failure result.

include	* demangle.h (DMGL_RECURSE_LIMIT): Define.
        (DEMANGLE_RECURSION_LIMIT): Prototype.

binutuils * addr2line.c (demangle_flags): New static variable.
        (long_options): Add --recurse-limit and --no-recurse-limit.
        (translate_address): Pass demangle_flags to bfd_demangle.
        (main): Handle --recurse-limit and --no-recurse-limit options.
        * cxxfilt.c (flags): Add DMGL_RECURSE_LIMIT.
        (long_options): Add --recurse-limit and --no-recurse-limit.
        (main): Handle new options.
        * dlltool.c (gen_def_file): Include DMGL_RECURSE_LIMIT in flags
        passed to cplus_demangle.
        * nm.c (demangle_flags): New static variable.
        (long_options): Add --recurse-limit and --no-recurse-limit.
        (main): Handle new options.
        * objdump.c (demangle_flags): New static variable.
        (usage): Add --recurse-limit and --no-recurse-limit.
        (long_options): Likewise.
        (objdump_print_symname): Pass demangle_flags to bfd_demangle.
        (disassemble_section): Likewise.
        (dump_dymbols): Likewise.
        (main): Handle new options.
        * prdbg.c (demangle_flags): New static variable.
        (tg_variable): Pass demangle_flags to demangler.
        (tg_start_function): Likewise.
        * stabs.c (demangle_flags): New static variable.
        (stab_demangle_template): Pass demangle_flags to demangler.
        (stab_demangle_v3_argtypes): Likewise.
        (stab_demangle_v3_arg): Likewise.
	* doc/binutuls.texi: Document new command line options.
	* NEWS: Mention the new feature.
        * testsuite/config/default.exp (CXXFILT): Define if not already
        defined.
        (CXXFILTFLAGS): Likewise.
        * testsuite/binutils-all/cxxfilt.exp: New file.  Runs a few
        simple tests of the cxxfilt program.
This commit is contained in:
Nick Clifton
2018-12-07 11:32:55 +00:00
parent 67bb16f345
commit af03af8f55
21 changed files with 603 additions and 145 deletions

View File

@ -146,6 +146,7 @@ struct work_stuff
int *proctypevec; /* Indices of currently processed remembered typevecs. */
int proctypevec_size;
int nproctypes;
unsigned int recursion_level;
};
#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
@ -1292,12 +1293,14 @@ squangle_mop_up (struct work_stuff *work)
free ((char *) work -> btypevec);
work->btypevec = NULL;
work->bsize = 0;
work->numb = 0;
}
if (work -> ktypevec != NULL)
{
free ((char *) work -> ktypevec);
work->ktypevec = NULL;
work->ksize = 0;
work->numk = 0;
}
}
@ -1331,8 +1334,15 @@ work_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from)
for (i = 0; i < from->numk; i++)
{
int len = strlen (from->ktypevec[i]) + 1;
int len;
if (from->ktypevec[i] == NULL)
{
to->ktypevec[i] = NULL;
continue;
}
len = strlen (from->ktypevec[i]) + 1;
to->ktypevec[i] = XNEWVEC (char, len);
memcpy (to->ktypevec[i], from->ktypevec[i], len);
}
@ -1342,8 +1352,15 @@ work_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from)
for (i = 0; i < from->numb; i++)
{
int len = strlen (from->btypevec[i]) + 1;
int len;
if (from->btypevec[i] == NULL)
{
to->btypevec[i] = NULL;
continue;
}
len = strlen (from->btypevec[i]) + 1;
to->btypevec[i] = XNEWVEC (char , len);
memcpy (to->btypevec[i], from->btypevec[i], len);
}
@ -1401,6 +1418,7 @@ delete_non_B_K_work_stuff (struct work_stuff *work)
free ((char*) work->tmpl_argvec);
work->tmpl_argvec = NULL;
work->ntmpl_args = 0;
}
if (work->previous_argument)
{
@ -4471,12 +4489,14 @@ remember_Btype (struct work_stuff *work, const char *start,
char *tem;
tem = XNEWVEC (char, len + 1);
memcpy (tem, start, len);
if (len > 0)
memcpy (tem, start, len);
tem[len] = '\0';
work -> btypevec[index] = tem;
}
/* Lose all the info related to B and K type codes. */
static void
forget_B_and_K_types (struct work_stuff *work)
{
@ -4502,6 +4522,7 @@ forget_B_and_K_types (struct work_stuff *work)
}
}
}
/* Forget the remembered types, but not the type vector itself. */
static void
@ -4696,6 +4717,16 @@ demangle_nested_args (struct work_stuff *work, const char **mangled,
int result;
int saved_nrepeats;
if ((work->options & DMGL_NO_RECURSE_LIMIT) == 0)
{
if (work->recursion_level > DEMANGLE_RECURSION_LIMIT)
/* FIXME: There ought to be a way to report
that the recursion limit has been reached. */
return 0;
work->recursion_level ++;
}
/* The G++ name-mangling algorithm does not remember types on nested
argument lists, unless -fsquangling is used, and in that case the
type vector updated by remember_type is not used. So, we turn
@ -4722,6 +4753,9 @@ demangle_nested_args (struct work_stuff *work, const char **mangled,
--work->forgetting_types;
work->nrepeats = saved_nrepeats;
if ((work->options & DMGL_NO_RECURSE_LIMIT) == 0)
--work->recursion_level;
return result;
}