From de3b531c9aa93592f98ebd99c6b35be632e3c1b3 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 27 Apr 2017 10:44:28 +0100 Subject: [PATCH] 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. From-SVN: r247300 --- libiberty/ChangeLog | 9 +++++++++ libiberty/cp-demangle.c | 2 ++ libiberty/cplus-dem.c | 16 +++++++--------- libiberty/testsuite/demangle-expected | 15 +++++++++++++++ 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index 34e585eacaa..1e7a6c6daca 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,12 @@ +2017-04-27 Jonathan Wakely + + 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 * cp-demangle.c (MAX_RECURSION_COUNT): New constant. diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index e1db9005e15..7b8d0b4cbaa 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 a990e072975..81c17a3207d 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 45c572268b3..f2a12b9a7d1 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