cplus-dem.c: Attempt to handle overflows in counts with some semblance of grace.

1999-04-01  Jim Blandy  <jimb@zwingli.cygnus.com>
	* cplus-dem.c: Attempt to handle overflows in counts with some
	semblance of grace.
	(consume_count): Detect overflows.  Return -1 to indicate errors,
	instead of zero.
	(demangle_template_value_parm, demangle_template): Handle change
	to consume_count's return convention.

From-SVN: r26309
This commit is contained in:
Jim Blandy 1999-04-09 09:01:35 +00:00 committed by Tom Tromey
parent d330fd93a9
commit 9d22998936
2 changed files with 125 additions and 42 deletions

View File

@ -1,3 +1,12 @@
1999-04-01 Jim Blandy <jimb@zwingli.cygnus.com>
* cplus-dem.c: Attempt to handle overflows in counts with some
semblance of grace.
(consume_count): Detect overflows. Return -1 to indicate errors,
instead of zero.
(demangle_template_value_parm, demangle_template): Handle change
to consume_count's return convention.
1999-04-05 Tom Tromey <tromey@cygnus.com>
* testsuite/regress-demangle: New file.

View File

@ -420,33 +420,43 @@ qualifier_string PARAMS ((int));
static const char*
demangle_qualifier PARAMS ((int));
/* Translate count to integer, consuming tokens in the process.
Conversion terminates on the first non-digit character.
Trying to consume something that isn't a count results in
no consumption of input and a return of 0. */
/* Translate count to integer, consuming tokens in the process.
Conversion terminates on the first non-digit character.
Trying to consume something that isn't a count results in no
consumption of input and a return of -1.
Overflow consumes the rest of the digits, and returns -1. */
static int
consume_count (type)
const char **type;
{
unsigned int count = 0;
char *save = *type;
int count = 0;
if (! isdigit ((unsigned char)**type))
return -1;
while (isdigit ((unsigned char)**type))
{
count *= 10;
count += **type - '0';
/* A sanity check. Otherwise a symbol like
`_Utf390_1__1_9223372036854775807__9223372036854775'
can cause this function to return a negative value.
In this case we just consume until the end of the string. */
if (count > strlen (*type))
/* Check for overflow.
We assume that count is represented using two's-complement;
no power of two is divisible by ten, so if an overflow occurs
when multiplying by ten, the result will not be a multiple of
ten. */
if ((count % 10) != 0)
{
*type = save;
return 0;
while (isdigit ((unsigned char) **type))
(*type)++;
return -1;
}
count += **type - '0';
(*type)++;
}
return (count);
}
@ -1440,12 +1450,15 @@ demangle_template_value_parm (work, mangled, s, tk)
}
string_appendn (s, "'", 1);
val = consume_count(mangled);
if (val == 0)
return -1;
tmp[0] = (char)val;
tmp[1] = '\0';
string_appendn (s, &tmp[0], 1);
string_appendn (s, "'", 1);
if (val <= 0)
success = 0;
else
{
tmp[0] = (char)val;
tmp[1] = '\0';
string_appendn (s, &tmp[0], 1);
string_appendn (s, "'", 1);
}
}
else if (tk == tk_bool)
{
@ -1493,7 +1506,7 @@ demangle_template_value_parm (work, mangled, s, tk)
else if (tk == tk_pointer || tk == tk_reference)
{
int symbol_len = consume_count (mangled);
if (symbol_len == 0)
if (symbol_len == -1)
return -1;
if (symbol_len == 0)
string_appendn (s, "0", 1);
@ -1589,7 +1602,7 @@ demangle_template (work, mangled, tname, trawname, is_type, remember)
}
else
{
if ((r = consume_count (mangled)) == 0
if ((r = consume_count (mangled)) <= 0
|| (int) strlen (*mangled) < r)
{
return (0);
@ -1768,6 +1781,8 @@ arm_pt (work, mangled, n, anchor, args)
int len;
*args = *anchor + 6;
len = consume_count (args);
if (len == -1)
return 0;
if (*args + len == mangled + n && **args == '_')
{
++*args;
@ -1783,6 +1798,8 @@ arm_pt (work, mangled, n, anchor, args)
int len;
*args = *anchor + 6;
len = consume_count (args);
if (len == -1)
return 0;
if (*args + len == mangled + n && **args == '_')
{
++*args;
@ -1794,6 +1811,8 @@ arm_pt (work, mangled, n, anchor, args)
int len;
*args = *anchor + 3;
len = consume_count (args);
if (len == -1)
return 0;
if (*args + len == mangled + n && **args == '_')
{
++*args;
@ -1969,7 +1988,9 @@ demangle_class_name (work, mangled, declp)
int success = 0;
n = consume_count (mangled);
if (n > 0)
if (n == -1)
return 0;
if ((int) strlen (*mangled) >= n)
{
demangle_arm_hp_template (work, mangled, n, declp);
success = 1;
@ -2417,6 +2438,11 @@ gnu_special (work, mangled, declp)
break;
default:
n = consume_count (mangled);
if (n < 0 || n > strlen (*mangled))
{
success = 0;
break;
}
string_appendn (declp, *mangled, n);
(*mangled) += n;
}
@ -2437,21 +2463,30 @@ gnu_special (work, mangled, declp)
}
else if (strncmp (*mangled, "__thunk_", 8) == 0)
{
int delta = ((*mangled) += 8, consume_count (mangled));
char *method = internal_cplus_demangle (work, ++*mangled);
if (method)
{
char buf[50];
sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
string_append (declp, buf);
string_append (declp, method);
free (method);
n = strlen (*mangled);
(*mangled) += n;
}
int delta;
(*mangled) += 8;
delta = consume_count (mangled);
if (delta == -1)
success = 0;
else
{
success = 0;
char *method = internal_cplus_demangle (work, ++*mangled);
if (method)
{
char buf[50];
sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
string_append (declp, buf);
string_append (declp, method);
free (method);
n = strlen (*mangled);
(*mangled) += n;
}
else
{
success = 0;
}
}
}
else if (strncmp (*mangled, "__t", 3) == 0
@ -2555,7 +2590,7 @@ arm_special (mangled, declp)
while (*scan != '\0') /* first check it can be demangled */
{
n = consume_count (&scan);
if (n==0)
if (n == -1)
{
return (0); /* no good */
}
@ -2569,6 +2604,9 @@ arm_special (mangled, declp)
while (**mangled != '\0')
{
n = consume_count (mangled);
if (n == -1
|| n > strlen (*mangled))
return 0;
string_prependn (declp, *mangled, n);
(*mangled) += n;
if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
@ -2753,6 +2791,11 @@ demangle_qualified (work, mangled, result, isfuncname, append)
* This is necessary to deal with templates in
* mangling styles like EDG */
namelength = consume_count (mangled);
if (namelength == -1)
{
success = 0;
break;
}
recursively_demangle(work, mangled, &temp, namelength);
}
else
@ -2816,7 +2859,37 @@ SYNOPSIS
DESCRIPTION
Return 0 if no conversion is performed, 1 if a string is converted.
Assume that *type points at a count in a mangled name; set
*count to its value, and set *type to the next character after
the count. There are some weird rules in effect here.
If *type does not point at a string of digits, return zero.
If *type points at a string of digits followed by an
underscore, set *count to their value as an integer, advance
*type to point *after the underscore, and return 1.
If *type points at a string of digits not followed by an
underscore, consume only the first digit. Set *count to its
value as an integer, leave *type pointing after that digit,
and return 1.
The excuse for this odd behavior: in the ARM and HP demangling
styles, a type can be followed by a repeat count of the form
`Nxy', where:
`x' is a single digit specifying how many additional copies
of the type to append to the argument list, and
`y' is one or more digits, specifying the zero-based index of
the first repeated argument in the list. Yes, as you're
unmangling the name you can figure this out yourself, but
it's there anyway.
So, for example, in `bar__3fooFPiN51', the first argument is a
pointer to an integer (`Pi'), and then the next five arguments
are the same (`N5'), and the first repeat is the function's
second argument (`1').
*/
static int
@ -2978,7 +3051,8 @@ do_type (work, mangled, result)
if (isdigit ((unsigned char)**mangled))
{
n = consume_count (mangled);
if ((int) strlen (*mangled) < n)
if (n == -1
|| (int) strlen (*mangled) < n)
{
success = 0;
break;
@ -3423,7 +3497,7 @@ do_hpacc_template_literal (work, mangled, result)
literal_len = consume_count (mangled);
if (!literal_len)
if (literal_len <= 0)
return 0;
/* Literal parameters are names of arrays, functions, etc. and the
@ -3513,7 +3587,7 @@ do_arg (work, mangled, result)
(*mangled)++;
work->nrepeats = consume_count(mangled);
if (work->nrepeats == 0)
if (work->nrepeats <= 0)
/* This was not a repeat count after all. */
return 0;
@ -3800,7 +3874,7 @@ demangle_args (work, mangled, declp)
count but it's impossible to demangle that case properly
anyway. Eg if we already have 12 types is T12Pc "(..., type1,
Pc, ...)" or "(..., type12, char *, ...)" */
if ((t = consume_count(mangled)) == 0)
if ((t = consume_count(mangled)) <= 0)
{
return (0);
}