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 /binutils/unwind-ia64.c | |
parent | 7bac4137d757be98de8f6f8d8a649f04cacfdd2f (diff) | |
download | binutils-gdb-60e63c3e9750b036d50e58bc173591fa450601b6.tar.gz |
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.
Diffstat (limited to 'binutils/unwind-ia64.c')
-rw-r--r-- | binutils/unwind-ia64.c | 21 |
1 files changed, 17 insertions, 4 deletions
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; } |