Hi Bernd, Thanks for the feedback!
> Patches need to be bootstrapped and regression tested, and patch submissions > should include which target this was done on. > > Ideally you'd also want to include testcases along with your patches, > although I'm not entirely sure how we can arrange for this type of problem to > be tested. Regression tested on x86_64-pc-linux-gnu (make check). Test cases added to libiberty/testsuite/demangler-expected and checked PR70498 is resolved. Not sure how to bootstrap the patch. > Lastly, for this specific patch, I have trouble seeing how it fixes anything. > I'd need a more detailed explanation of how the problem happens in the first > place. In the patched version, the values wrap around when they are parsed in d_number. Since the mangled string may contain negative numbers, there is usually proper handling of negative numbers in the clients of d_number. Without the patch a value can become negative when cast from long to int *after* these checks. For instance, in d_source_name the length of the identifier is parsed as long from the mangled string and checked whether it is negative. Since d_identifier takes an int as length, d_identifier is called with a negative length after the implicit cast: static struct demangle_component * d_source_name (struct d_info *di) { int len; struct demangle_component *ret; len = d_number (di); if (len <= 0) return NULL; ret = d_identifier (di, len); di->last_name = ret; return ret; } -- Index: libiberty/cp-demangle.c =================================================================== --- libiberty/cp-demangle.c (revision 234663) +++ libiberty/cp-demangle.c (working copy) @@ -398,7 +398,7 @@ 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); @@ -421,9 +421,9 @@ 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 *); @@ -1119,7 +1119,7 @@ /* 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; @@ -1135,7 +1135,7 @@ /* 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; @@ -1620,7 +1620,7 @@ static struct demangle_component * d_source_name (struct d_info *di) { - long len; + int len; struct demangle_component *ret; len = d_number (di); @@ -1633,12 +1633,12 @@ /* 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); @@ -1681,7 +1681,7 @@ /* 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; @@ -1702,7 +1702,7 @@ /* 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 >= ANONYMOUS_NAMESPACE_PREFIX_LEN + 2 && memcmp (name, ANONYMOUS_NAMESPACE_PREFIX, ANONYMOUS_NAMESPACE_PREFIX_LEN) == 0) { @@ -1870,7 +1870,7 @@ { struct demangle_component *p = NULL; struct demangle_component *next = NULL; - long len, i; + int len, i; char c; const char *str; @@ -2012,7 +2012,7 @@ case 'C': { struct demangle_component *derived_type; - long offset; + int offset; struct demangle_component *base_type; derived_type = cplus_demangle_type (di); @@ -2946,10 +2946,10 @@ /* <non-negative number> _ */ -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') @@ -2969,7 +2969,7 @@ static struct demangle_component * d_template_param (struct d_info *di) { - long param; + int param; if (! d_check_char (di, 'T')) return NULL; @@ -3502,7 +3502,7 @@ static int d_discriminator (struct d_info *di) { - long discrim; + int discrim; if (d_peek_char (di) != '_') return 1; @@ -3558,7 +3558,7 @@ d_unnamed_type (struct d_info *di) { struct demangle_component *ret; - long num; + int num; if (! d_check_char (di, 'U')) return NULL; @@ -4086,7 +4086,7 @@ } 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); Index: libiberty/testsuite/demangle-expected =================================================================== --- libiberty/testsuite/demangle-expected (revision 234663) +++ libiberty/testsuite/demangle-expected (working copy) @@ -4422,12 +4422,17 @@ _Z3fooI1FEN1XIXszdtcl1PclcvT__EEE5arrayEE4TypeEv X<sizeof ((P(((F)())())).array)>::Type foo<F>() # -# Tests a use-after-free problem +# Tests a use-after-free problem PR70481 _Q.__0 ::Q.(void) # -# Tests a use-after-free problem +# Tests a use-after-free problem PR70481 _Q10-__9cafebabe. cafebabe.::-(void) +# +# Tests write access violation PR70498 + +_Z80800000000000000000000 +_Z80800000000000000000000