About undefined shift and integer overflow issues (cherry picked from commit 30b34d883dc099fbe68fe522bedbacc09c74eda6)
62 lines
1.5 KiB
Diff
62 lines
1.5 KiB
Diff
From 60e63c3e9750b036d50e58bc173591fa450601b6 Mon Sep 17 00:00:00 2001
|
|
From: Alan Modra <amodra@gmail.com>
|
|
Date: Mon, 16 Mar 2020 08:54:16 +1030
|
|
Subject: [PATCH] ubsan: shift exponent 70 is too large
|
|
|
|
Reference: https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=60e63c3e9750b036d50e58bc173591fa450601b6
|
|
|
|
* 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/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.19.1
|
|
|