This ensures we notice if a number in a mangled name overflows an int. The check in consume_count can be optimized away, and there was no check in d_number.
It also adds a check that the next character after __thunk_<number> is an underscore, rather than just skipping over it. OK for trunk? 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.
commit 48c4e6098f7ea373615d46befba903a0a1b75230 Author: Jonathan Wakely <jwak...@redhat.com> Date: Wed Apr 26 20:20:24 2017 +0100 PR demangler/80513 check for overflows and invalid characters in thunks 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. diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index e1db900..7b8d0b4 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -1692,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); 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