summaryrefslogtreecommitdiff
path: root/opcodes/wasm32-dis.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2019-12-23 17:58:09 +1030
committerAlan Modra <amodra@gmail.com>2019-12-23 17:58:09 +1030
commit27c1c4271a14cc2ebc27227212c19d4227ef212d (patch)
tree348440ee0822b82ccffa82ac55d004af21b54e35 /opcodes/wasm32-dis.c
parent09b0d8a75fa379eacf0d9d6b27320d025475b14d (diff)
downloadbinutils-gdb-27c1c4271a14cc2ebc27227212c19d4227ef212d.tar.gz
ubsan: wasm: shift is too large for 64-bit type 'bfd_vma'
bfd/ * wasm-module.c (wasm_read_leb128): Don't allow oversize shifts. Catch value overflow. Sign extend only on terminating byte. opcodes/ * wasm32-dis.c (wasm_read_leb128): Don't allow oversize shifts. Catch value overflow. Sign extend only on terminating byte.
Diffstat (limited to 'opcodes/wasm32-dis.c')
-rw-r--r--opcodes/wasm32-dis.c29
1 files changed, 18 insertions, 11 deletions
diff --git a/opcodes/wasm32-dis.c b/opcodes/wasm32-dis.c
index b1042793a5e..a885148c8bd 100644
--- a/opcodes/wasm32-dis.c
+++ b/opcodes/wasm32-dis.c
@@ -192,29 +192,36 @@ wasm_read_leb128 (bfd_vma pc,
unsigned int num_read = 0;
unsigned int shift = 0;
unsigned char byte = 0;
- bfd_boolean success = FALSE;
+ int status = 1;
while (info->read_memory_func (pc + num_read, &byte, 1, info) == 0)
{
num_read++;
- result |= ((bfd_vma) (byte & 0x7f)) << shift;
+ if (shift < sizeof (result) * 8)
+ {
+ result |= ((uint64_t) (byte & 0x7f)) << shift;
+ if ((result >> shift) != (byte & 0x7f))
+ /* Overflow. */
+ status |= 2;
+ shift += 7;
+ }
+ else if ((byte & 0x7f) != 0)
+ status |= 2;
- shift += 7;
if ((byte & 0x80) == 0)
- {
- success = TRUE;
- break;
- }
+ {
+ status &= ~1;
+ if (sign && (shift < 8 * sizeof (result)) && (byte & 0x40))
+ result |= -((uint64_t) 1 << shift);
+ break;
+ }
}
if (length_return != NULL)
*length_return = num_read;
if (error_return != NULL)
- *error_return = ! success;
-
- if (sign && (shift < 8 * sizeof (result)) && (byte & 0x40))
- result |= -((uint64_t) 1 << shift);
+ *error_return = status != 0;
return result;
}