aboutsummaryrefslogtreecommitdiff
path: root/libiberty/cp-demangle.c
diff options
context:
space:
mode:
authorMikhail Maltsev <maltsevm@gmail.com>2015-11-28 16:39:29 +0000
committerPedro Alves <palves@redhat.com>2015-11-28 16:39:29 +0000
commitd81bf7ddc2ad497037fbfde5d15cfa8d81a9e959 (patch)
tree926b0c2c076cb449874747186878d3da93564104 /libiberty/cp-demangle.c
parent6a8796db3691b9a53dc5475eaec5388bc1af115d (diff)
downloadfsf-binutils-gdb-d81bf7ddc2ad497037fbfde5d15cfa8d81a9e959.zip
fsf-binutils-gdb-d81bf7ddc2ad497037fbfde5d15cfa8d81a9e959.tar.gz
fsf-binutils-gdb-d81bf7ddc2ad497037fbfde5d15cfa8d81a9e959.tar.bz2
Fix several crashes of C++ demangler on fuzzed input.
libiberty/ * cp-demangle.c (d_dump): Fix syntax error. (d_identifier): Adjust type of len to match d_source_name. (d_expression_1): Fix out-of-bounds access. Check code variable for NULL before dereferencing it. (d_find_pack): Do not recurse for FIXED_TYPE, DEFAULT_ARG and NUMBER. (d_print_comp_inner): Add NULL pointer check. * cp-demangle.h (d_peek_next_char): Define as inline function when CHECK_DEMANGLER is defined. (d_advance): Likewise. * testsuite/demangle-expected: Add new testcases. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@225727 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libiberty/cp-demangle.c')
-rw-r--r--libiberty/cp-demangle.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index fb1c4e5..c587895 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -93,7 +93,11 @@
CP_DEMANGLE_DEBUG
If defined, turns on debugging mode, which prints information on
stdout about the mangled string. This is not generally useful.
-*/
+
+ CHECK_DEMANGLER
+ If defined, additional sanity checks will be performed. It will
+ cause some slowdown, but will allow to catch out-of-bound access
+ errors earlier. This macro is intended for testing and debugging. */
#if defined (_AIX) && !defined (__GNUC__)
#pragma alloca
@@ -419,7 +423,7 @@ static struct demangle_component *d_source_name (struct d_info *);
static long d_number (struct d_info *);
-static struct demangle_component *d_identifier (struct d_info *, int);
+static struct demangle_component *d_identifier (struct d_info *, long);
static struct demangle_component *d_operator_name (struct d_info *);
@@ -715,7 +719,7 @@ d_dump (struct demangle_component *dc, int indent)
case DEMANGLE_COMPONENT_FIXED_TYPE:
printf ("fixed-point type, accum? %d, sat? %d\n",
dc->u.s_fixed.accum, dc->u.s_fixed.sat);
- d_dump (dc->u.s_fixed.length, indent + 2)
+ d_dump (dc->u.s_fixed.length, indent + 2);
break;
case DEMANGLE_COMPONENT_ARGLIST:
printf ("argument list\n");
@@ -1664,7 +1668,7 @@ d_number_component (struct d_info *di)
/* identifier ::= <(unqualified source code identifier)> */
static struct demangle_component *
-d_identifier (struct d_info *di, int len)
+d_identifier (struct d_info *di, long len)
{
const char *name;
@@ -1685,7 +1689,7 @@ d_identifier (struct d_info *di, int len)
/* Look for something which looks like a gcc encoding of an
anonymous namespace, and replace it with a more user friendly
name. */
- if (len >= (int) ANONYMOUS_NAMESPACE_PREFIX_LEN + 2
+ if (len >= (long) ANONYMOUS_NAMESPACE_PREFIX_LEN + 2
&& memcmp (name, ANONYMOUS_NAMESPACE_PREFIX,
ANONYMOUS_NAMESPACE_PREFIX_LEN) == 0)
{
@@ -3174,6 +3178,8 @@ d_expression_1 (struct d_info *di)
struct demangle_component *type = NULL;
if (peek == 't')
type = cplus_demangle_type (di);
+ if (!d_peek_next_char (di))
+ return NULL;
d_advance (di, 2);
return d_make_comp (di, DEMANGLE_COMPONENT_INITIALIZER_LIST,
type, d_exprlist (di, 'E'));
@@ -3248,6 +3254,8 @@ d_expression_1 (struct d_info *di)
struct demangle_component *left;
struct demangle_component *right;
+ if (code == NULL)
+ return NULL;
if (op_is_new_cast (op))
left = cplus_demangle_type (di);
else
@@ -3275,7 +3283,9 @@ d_expression_1 (struct d_info *di)
struct demangle_component *second;
struct demangle_component *third;
- if (!strcmp (code, "qu"))
+ if (code == NULL)
+ return NULL;
+ else if (!strcmp (code, "qu"))
{
/* ?: expression. */
first = d_expression_1 (di);
@@ -4204,6 +4214,9 @@ d_find_pack (struct d_print_info *dpi,
case DEMANGLE_COMPONENT_CHARACTER:
case DEMANGLE_COMPONENT_FUNCTION_PARAM:
case DEMANGLE_COMPONENT_UNNAMED_TYPE:
+ case DEMANGLE_COMPONENT_FIXED_TYPE:
+ case DEMANGLE_COMPONENT_DEFAULT_ARG:
+ case DEMANGLE_COMPONENT_NUMBER:
return NULL;
case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
@@ -4439,6 +4452,11 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
local_name = d_right (typed_name);
if (local_name->type == DEMANGLE_COMPONENT_DEFAULT_ARG)
local_name = local_name->u.s_unary_num.sub;
+ if (local_name == NULL)
+ {
+ d_print_error (dpi);
+ return;
+ }
while (local_name->type == DEMANGLE_COMPONENT_RESTRICT_THIS
|| local_name->type == DEMANGLE_COMPONENT_VOLATILE_THIS
|| local_name->type == DEMANGLE_COMPONENT_CONST_THIS