From 60e63c3e9750b036d50e58bc173591fa450601b6 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Mon, 16 Mar 2020 08:54:16 +1030 Subject: [PATCH] ubsan: shift exponent 70 is too large * unwind-ia64.c (unw_decode_uleb128): Prevent overlarge shifts. Detect shift overflows and check that terminating byte is found. Print an error on a bad uleb128. --- binutils/ChangeLog | 6 ++++++ binutils/unwind-ia64.c | 21 +++++++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 5f8af946804..ee1534f98a6 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,9 @@ +2020-03-16 Alan Modra + + * unwind-ia64.c (unw_decode_uleb128): Prevent overlarge shifts. + Detect shift overflows and check that terminating byte is found. + Print an error on a bad uleb128. + 2020-03-14 Alan Modra * readelf.c (process_file): Clean ba_cache. diff --git a/binutils/unwind-ia64.c b/binutils/unwind-ia64.c index b59a531e685..b9eae5bb21d 100644 --- a/binutils/unwind-ia64.c +++ b/binutils/unwind-ia64.c @@ -544,21 +544,34 @@ static unw_word unw_decode_uleb128 (const unsigned char **dpp, const unsigned char * end) { unsigned shift = 0; + int status = 1; unw_word byte, result = 0; const unsigned char *bp = *dpp; while (bp < end) { byte = *bp++; - result |= (byte & 0x7f) << shift; + if (shift < sizeof (result) * 8) + { + result |= (byte & 0x7f) << shift; + if ((result >> shift) != (byte & 0x7f)) + /* Overflow. */ + status |= 2; + shift += 7; + } + else if ((byte & 0x7f) != 0) + status |= 2; if ((byte & 0x80) == 0) - break; - - shift += 7; + { + status &= ~1; + break; + } } *dpp = bp; + if (status != 0) + printf (_("Bad uleb128\n")); return result; } -- 2.30.2