From 9e6edb946c0e9a2c530fbae3eeace148eca0de33 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 19 May 2016 14:05:41 +0200 Subject: [PATCH] Backport PRs 67394, 69687, 70481, 70492, 70498 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Backported from mainline 2016-05-19 Jakub Jelinek PR c++/70498 * cp-demangle.c (d_expression_1): Formatting fix. 2016-05-02 Marcel Böhme PR c++/70498 * cp-demangle.c: Parse numbers as integer instead of long to avoid overflow after sanity checks. Include if available. (INT_MAX): Define if necessary. (d_make_template_param): Takes integer argument instead of long. (d_make_function_param): Likewise. (d_append_num): Likewise. (d_identifier): Likewise. (d_number): Parse as and return integer. (d_compact_number): Handle overflow. (d_source_name): Change variable type to integer for parsed number. (d_java_resource): Likewise. (d_special_name): Likewise. (d_discriminator): Likewise. (d_unnamed_type): Likewise. * testsuite/demangle-expected: Add regression test cases. 2016-04-08 Marcel Böhme PR c++/69687 * cplus-dem.c: Include if available. (INT_MAX): Define if necessary. (remember_type, remember_Ktype, register_Btype, string_need): Abort if we detect cases where we the size of the allocation would overflow. PR c++/70492 * cplus-dem.c (gnu_special): Handle case where consume_count returns -1. 2016-03-31 Mikhail Maltsev Marcel Bohme PR c++/67394 PR c++/70481 * cplus-dem.c (squangle_mop_up): Zero bsize/ksize after freeing btypevec/ktypevec. * testsuite/demangle-expected: Add coverage tests. From-SVN: r236456 --- libiberty/ChangeLog | 46 ++++++++++++++++++++++++ libiberty/cp-demangle.c | 52 +++++++++++++++------------ libiberty/cplus-dem.c | 22 ++++++++++++ libiberty/testsuite/demangle-expected | 20 +++++++++++ 4 files changed, 118 insertions(+), 22 deletions(-) diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index a32a08f0211b..e29224eddb78 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,6 +1,52 @@ 2016-05-19 Jakub Jelinek Backported from mainline + 2016-05-19 Jakub Jelinek + + PR c++/70498 + * cp-demangle.c (d_expression_1): Formatting fix. + + 2016-05-02 Marcel Böhme + + PR c++/70498 + * cp-demangle.c: Parse numbers as integer instead of long to avoid + overflow after sanity checks. Include if available. + (INT_MAX): Define if necessary. + (d_make_template_param): Takes integer argument instead of long. + (d_make_function_param): Likewise. + (d_append_num): Likewise. + (d_identifier): Likewise. + (d_number): Parse as and return integer. + (d_compact_number): Handle overflow. + (d_source_name): Change variable type to integer for parsed number. + (d_java_resource): Likewise. + (d_special_name): Likewise. + (d_discriminator): Likewise. + (d_unnamed_type): Likewise. + * testsuite/demangle-expected: Add regression test cases. + + 2016-04-08 Marcel Böhme + + PR c++/69687 + * cplus-dem.c: Include if available. + (INT_MAX): Define if necessary. + (remember_type, remember_Ktype, register_Btype, string_need): + Abort if we detect cases where we the size of the allocation would + overflow. + + PR c++/70492 + * cplus-dem.c (gnu_special): Handle case where consume_count returns + -1. + + 2016-03-31 Mikhail Maltsev + Marcel Bohme + + PR c++/67394 + PR c++/70481 + * cplus-dem.c (squangle_mop_up): Zero bsize/ksize after freeing + btypevec/ktypevec. + * testsuite/demangle-expected: Add coverage tests. + 2015-11-27 Pedro Alves PR other/61321 diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index 3409fcda3237..3e3dd98bbe0d 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -124,6 +124,13 @@ extern char *alloca (); # endif /* alloca */ #endif /* HAVE_ALLOCA_H */ +#ifdef HAVE_LIMITS_H +#include +#endif +#ifndef INT_MAX +# define INT_MAX (int)(((unsigned int) ~0) >> 1) /* 0x7FFFFFFF */ +#endif + #include "ansidecl.h" #include "libiberty.h" #include "demangle.h" @@ -394,7 +401,7 @@ d_make_dtor (struct d_info *, enum gnu_v3_dtor_kinds, struct demangle_component *); static struct demangle_component * -d_make_template_param (struct d_info *, long); +d_make_template_param (struct d_info *, int); static struct demangle_component * d_make_sub (struct d_info *, const char *, int); @@ -417,9 +424,9 @@ static struct demangle_component *d_unqualified_name (struct d_info *); static struct demangle_component *d_source_name (struct d_info *); -static long d_number (struct d_info *); +static int d_number (struct d_info *); -static struct demangle_component *d_identifier (struct d_info *, long); +static struct demangle_component *d_identifier (struct d_info *, int); static struct demangle_component *d_operator_name (struct d_info *); @@ -1111,7 +1118,7 @@ d_make_dtor (struct d_info *di, enum gnu_v3_dtor_kinds kind, /* Add a new template parameter. */ static struct demangle_component * -d_make_template_param (struct d_info *di, long i) +d_make_template_param (struct d_info *di, int i) { struct demangle_component *p; @@ -1127,7 +1134,7 @@ d_make_template_param (struct d_info *di, long i) /* Add a new function parameter. */ static struct demangle_component * -d_make_function_param (struct d_info *di, long i) +d_make_function_param (struct d_info *di, int i) { struct demangle_component *p; @@ -1601,7 +1608,7 @@ d_unqualified_name (struct d_info *di) static struct demangle_component * d_source_name (struct d_info *di) { - long len; + int len; struct demangle_component *ret; len = d_number (di); @@ -1614,12 +1621,12 @@ d_source_name (struct d_info *di) /* number ::= [n] <(non-negative decimal integer)> */ -static long +static int d_number (struct d_info *di) { int negative; char peek; - long ret; + int ret; negative = 0; peek = d_peek_char (di); @@ -1662,7 +1669,7 @@ d_number_component (struct d_info *di) /* identifier ::= <(unqualified source code identifier)> */ static struct demangle_component * -d_identifier (struct d_info *di, long len) +d_identifier (struct d_info *di, int len) { const char *name; @@ -1683,7 +1690,7 @@ d_identifier (struct d_info *di, long 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 >= (long) ANONYMOUS_NAMESPACE_PREFIX_LEN + 2 + if (len >= (int) ANONYMOUS_NAMESPACE_PREFIX_LEN + 2 && memcmp (name, ANONYMOUS_NAMESPACE_PREFIX, ANONYMOUS_NAMESPACE_PREFIX_LEN) == 0) { @@ -1851,7 +1858,7 @@ d_java_resource (struct d_info *di) { struct demangle_component *p = NULL; struct demangle_component *next = NULL; - long len, i; + int len, i; char c; const char *str; @@ -1993,7 +2000,7 @@ d_special_name (struct d_info *di) case 'C': { struct demangle_component *derived_type; - long offset; + int offset; struct demangle_component *base_type; derived_type = cplus_demangle_type (di); @@ -2916,10 +2923,10 @@ d_pointer_to_member_type (struct d_info *di) /* _ */ -static long +static int d_compact_number (struct d_info *di) { - long num; + int num; if (d_peek_char (di) == '_') num = 0; else if (d_peek_char (di) == 'n') @@ -2927,7 +2934,7 @@ d_compact_number (struct d_info *di) else num = d_number (di) + 1; - if (! d_check_char (di, '_')) + if (num < 0 || ! d_check_char (di, '_')) return -1; return num; } @@ -2939,7 +2946,7 @@ d_compact_number (struct d_info *di) static struct demangle_component * d_template_param (struct d_info *di) { - long param; + int param; if (! d_check_char (di, 'T')) return NULL; @@ -3141,9 +3148,10 @@ d_expression_1 (struct d_info *di) } else { - index = d_compact_number (di) + 1; - if (index == 0) + index = d_compact_number (di); + if (index == INT_MAX || index == -1) return NULL; + index++; } return d_make_function_param (di, index); } @@ -3472,7 +3480,7 @@ d_local_name (struct d_info *di) static int d_discriminator (struct d_info *di) { - long discrim; + int discrim; if (d_peek_char (di) != '_') return 1; @@ -3528,7 +3536,7 @@ static struct demangle_component * d_unnamed_type (struct d_info *di) { struct demangle_component *ret; - long num; + int num; if (! d_check_char (di, 'U')) return NULL; @@ -4046,10 +4054,10 @@ d_append_string (struct d_print_info *dpi, const char *s) } static inline void -d_append_num (struct d_print_info *dpi, long l) +d_append_num (struct d_print_info *dpi, int l) { char buf[25]; - sprintf (buf,"%ld", l); + sprintf (buf,"%d", l); d_append_string (dpi, buf); } diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c index 52767cc8fde1..aace73302cb1 100644 --- a/libiberty/cplus-dem.c +++ b/libiberty/cplus-dem.c @@ -56,6 +56,13 @@ void * malloc (); void * realloc (); #endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifndef INT_MAX +# define INT_MAX (int)(((unsigned int) ~0) >> 1) /* 0x7FFFFFFF */ +#endif + #include #undef CURRENT_DEMANGLING_STYLE #define CURRENT_DEMANGLING_STYLE work->options @@ -1224,11 +1231,13 @@ squangle_mop_up (struct work_stuff *work) { free ((char *) work -> btypevec); work->btypevec = NULL; + work->bsize = 0; } if (work -> ktypevec != NULL) { free ((char *) work -> ktypevec); work->ktypevec = NULL; + work->ksize = 0; } } @@ -2986,6 +2995,11 @@ gnu_special (struct work_stuff *work, const char **mangled, string *declp) success = 1; break; } + else if (n == -1) + { + success = 0; + break; + } } else { @@ -4241,6 +4255,8 @@ remember_type (struct work_stuff *work, const char *start, int len) } else { + if (work -> typevec_size > INT_MAX / 2) + xmalloc_failed (INT_MAX); work -> typevec_size *= 2; work -> typevec = XRESIZEVEC (char *, work->typevec, work->typevec_size); @@ -4268,6 +4284,8 @@ remember_Ktype (struct work_stuff *work, const char *start, int len) } else { + if (work -> ksize > INT_MAX / 2) + xmalloc_failed (INT_MAX); work -> ksize *= 2; work -> ktypevec = XRESIZEVEC (char *, work->ktypevec, work->ksize); @@ -4297,6 +4315,8 @@ register_Btype (struct work_stuff *work) } else { + if (work -> bsize > INT_MAX / 2) + xmalloc_failed (INT_MAX); work -> bsize *= 2; work -> btypevec = XRESIZEVEC (char *, work->btypevec, work->bsize); @@ -4751,6 +4771,8 @@ string_need (string *s, int n) else if (s->e - s->p < n) { tem = s->p - s->b; + if (n > INT_MAX / 2 - tem) + xmalloc_failed (INT_MAX); n += tem; n *= 2; s->b = XRESIZEVEC (char, s->b, n); diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index 7038c7d13652..706c0cd760be 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -4406,3 +4406,23 @@ void baz(A*) --format=gnu-v3 _Z3fooI1FEN1XIXszdtcl1PclcvT__EEE5arrayEE4TypeEv X::Type foo() +# +# Tests a use-after-free problem PR70481 + +_Q.__0 +::Q.(void) +# +# Tests a use-after-free problem PR70481 + +_Q10-__9cafebabe. +cafebabe.::-(void) +# +# Tests integer overflow problem PR70492 + +__vt_90000000000cafebabe +__vt_90000000000cafebabe +# +# Tests write access violation PR70498 + +_Z80800000000000000000000 +_Z80800000000000000000000 -- 2.47.2