diff options
author | Alan Modra <amodra@gmail.com> | 2020-03-16 08:54:16 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2020-03-16 13:04:49 +1030 |
commit | 60e63c3e9750b036d50e58bc173591fa450601b6 (patch) | |
tree | 165272afbf8a2d53cffc45816cbf0644595b18d8 | |
parent | 7bac4137d757be98de8f6f8d8a649f04cacfdd2f (diff) | |
download | binutils-60e63c3e9750b036d50e58bc173591fa450601b6.zip binutils-60e63c3e9750b036d50e58bc173591fa450601b6.tar.gz binutils-60e63c3e9750b036d50e58bc173591fa450601b6.tar.bz2 |
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.
-rw-r--r-- | binutils/ChangeLog | 6 | ||||
-rw-r--r-- | binutils/unwind-ia64.c | 21 |
2 files changed, 23 insertions, 4 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 5f8af94..ee1534f 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,9 @@ +2020-03-16 Alan Modra <amodra@gmail.com> + + * 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 <amodra@gmail.com> * readelf.c (process_file): Clean ba_cache. diff --git a/binutils/unwind-ia64.c b/binutils/unwind-ia64.c index b59a531..b9eae5b 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; } |