diff options
-rw-r--r-- | libiberty/ChangeLog | 31 | ||||
-rw-r--r-- | libiberty/cp-demangle.c | 28 | ||||
-rw-r--r-- | libiberty/cp-demangle.h | 4 | ||||
-rw-r--r-- | libiberty/cplus-dem.c | 16 | ||||
-rw-r--r-- | libiberty/testsuite/demangle-expected | 15 |
5 files changed, 69 insertions, 25 deletions
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index 4b19fef..84be727 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -9,6 +9,37 @@ * waitpid.c (wait) [__MINGW32__]: Define as a macro that calls _cwait, so that this function works on MinGW. +2017-04-27 Jonathan Wakely <jwakely@redhat.com> + + PR demangler/80513 + * cp-demangle.c (d_number): Check for overflow. + * cplus-dem.c (consume_count): Fix overflow check. + (gnu_special): Check for underscore after thunk delta. + * testsuite/demangle-expected: Add tests for overflows and invalid + characters in thunks. + +2017-04-21 Mark Wielaard <mark@klomp.org> + + * cp-demangle.c (MAX_RECURSION_COUNT): New constant. + (struct d_print_info): Add recursion field. + (d_print_init): Initialize recursion. + (d_print_comp): Check and update d_print_info recursion depth. + +2017-04-21 Mark Wielaard <mark@klomp.org> + + * cp-demangle.c (d_substitution): Return NULL if d_add_substitution + fails. + +2017-04-21 Mark Wielaard <mark@klomp.org> + + * cp-demangle.h (struct d_info): Remove did_subs field. + * cp-demangle.c (struct d_info_checkpoint): Likewise. + (d_template_param): Don't update did_subs. + (d_substitution): Likewise. + (d_checkpoint): Don't assign did_subs. + (d_backtrack): Likewise. + (cplus_demangle_init_info): Don't initialize did_subs. + 2017-03-27 Pedro Alves <palves@redhat.com> * cp-demint.c (cplus_demangle_fill_component): Handle diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index 04832ff..7b8d0b4 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -316,10 +316,12 @@ struct d_info_checkpoint const char *n; int next_comp; int next_sub; - int did_subs; int expansion; }; +/* Maximum number of times d_print_comp may be called recursively. */ +#define MAX_RECURSION_COUNT 1024 + enum { D_PRINT_BUFFER_LENGTH = 256 }; struct d_print_info { @@ -342,6 +344,9 @@ struct d_print_info struct d_print_mod *modifiers; /* Set to 1 if we saw a demangling error. */ int demangle_failure; + /* Number of times d_print_comp was recursively called. Should not + be bigger than MAX_RECURSION_COUNT. */ + int recursion; /* Non-zero if we're printing a lambda argument. A template parameter reference actually means 'auto'. */ int is_lambda_arg; @@ -1687,6 +1692,8 @@ d_number (struct d_info *di) ret = - ret; return ret; } + if (ret > ((INT_MAX - (peek - '0')) / 10)) + return -1; ret = ret * 10 + peek - '0'; d_advance (di, 1); peek = d_peek_char (di); @@ -3075,8 +3082,6 @@ d_template_param (struct d_info *di) if (param < 0) return NULL; - ++di->did_subs; - return d_make_template_param (di, param); } @@ -3846,8 +3851,6 @@ d_substitution (struct d_info *di, int prefix) if (id >= (unsigned int) di->next_sub) return NULL; - ++di->did_subs; - return di->subs[id]; } else @@ -3896,7 +3899,8 @@ d_substitution (struct d_info *di, int prefix) /* If there are ABI tags on the abbreviation, it becomes a substitution candidate. */ dc = d_abi_tags (di, dc); - d_add_substitution (di, dc); + if (! d_add_substitution (di, dc)) + return NULL; } return dc; } @@ -3912,7 +3916,6 @@ d_checkpoint (struct d_info *di, struct d_info_checkpoint *checkpoint) checkpoint->n = di->n; checkpoint->next_comp = di->next_comp; checkpoint->next_sub = di->next_sub; - checkpoint->did_subs = di->did_subs; checkpoint->expansion = di->expansion; } @@ -3922,7 +3925,6 @@ d_backtrack (struct d_info *di, struct d_info_checkpoint *checkpoint) di->n = checkpoint->n; di->next_comp = checkpoint->next_comp; di->next_sub = checkpoint->next_sub; - di->did_subs = checkpoint->did_subs; di->expansion = checkpoint->expansion; } @@ -4157,6 +4159,7 @@ d_print_init (struct d_print_info *dpi, demangle_callbackref callback, dpi->opaque = opaque; dpi->demangle_failure = 0; + dpi->recursion = 0; dpi->is_lambda_arg = 0; dpi->component_stack = NULL; @@ -5691,13 +5694,14 @@ d_print_comp (struct d_print_info *dpi, int options, struct demangle_component *dc) { struct d_component_stack self; - if (dc == NULL || dc->d_printing > 1) + if (dc == NULL || dc->d_printing > 1 || dpi->recursion > MAX_RECURSION_COUNT) { d_print_error (dpi); return; } - else - dc->d_printing++; + + dc->d_printing++; + dpi->recursion++; self.dc = dc; self.parent = dpi->component_stack; @@ -5707,6 +5711,7 @@ d_print_comp (struct d_print_info *dpi, int options, dpi->component_stack = self.parent; dc->d_printing--; + dpi->recursion--; } /* Print a Java dentifier. For Java we try to handle encoded extended @@ -6159,7 +6164,6 @@ cplus_demangle_init_info (const char *mangled, int options, size_t len, chars in the mangled string. */ di->num_subs = len; di->next_sub = 0; - di->did_subs = 0; di->last_name = NULL; diff --git a/libiberty/cp-demangle.h b/libiberty/cp-demangle.h index a265775..d4a4ab6 100644 --- a/libiberty/cp-demangle.h +++ b/libiberty/cp-demangle.h @@ -111,10 +111,6 @@ struct d_info int next_sub; /* The number of available entries in the subs array. */ int num_subs; - /* The number of substitutions which we actually made from the subs - array, plus the number of template parameter references we - saw. */ - int did_subs; /* The last name we saw, for constructors and destructors. */ struct demangle_component *last_name; /* A running total of the length of large expansions from the diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c index a990e07..81c17a3 100644 --- a/libiberty/cplus-dem.c +++ b/libiberty/cplus-dem.c @@ -520,21 +520,17 @@ consume_count (const char **type) while (ISDIGIT ((unsigned char)**type)) { - count *= 10; - - /* 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) + const int digit = **type - '0'; + /* Check for overflow. */ + if (count > ((INT_MAX - digit) / 10)) { while (ISDIGIT ((unsigned char) **type)) (*type)++; return -1; } - count += **type - '0'; + count *= 10; + count += digit; (*type)++; } @@ -3173,6 +3169,8 @@ gnu_special (struct work_stuff *work, const char **mangled, string *declp) delta = consume_count (mangled); if (delta == -1) success = 0; + else if (**mangled != '_') + success = 0; else { char *method = internal_cplus_demangle (work, ++*mangled); diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index 45c5722..f2a12b9 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -4720,3 +4720,18 @@ _ZdvMMMMMMMMMMMMMrrrrA_DTdvfp_fp_Eededilfdfdfdfd _Z1MA_aMMMMA_MMA_MMMMMMMMSt1MS_o11T0000000000t2M0oooozoooo _Z1MA_aMMMMA_MMA_MMMMMMMMSt1MS_o11T0000000000t2M0oooozoooo + +# +# demangler/80513 Test for overflow in d_number +_Z4294967297x +_Z4294967297x + +# +# demangler/80513 Test for bogus characters after __thunk_ +__thunk_16a_$_1x +__thunk_16a_$_1x + +# +# demangler/80513 Test for overflow in consume_count +__thunk_4294967297__$_1x +__thunk_4294967297__$_1x |