From: Alan Modra Date: Wed, 26 Aug 2020 05:25:39 +0000 (+0930) Subject: PR26447 UBSAN: expr.c:1936 left shift of negative value X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b2f386b99caeab72eae26ca5bc9024421de145d9;p=binutils-gdb.git PR26447 UBSAN: expr.c:1936 left shift of negative value PR 26447 * expr.c (expr ): Do an unsigned shift. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 4e367a4dade..cfa087ed6ac 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,10 @@ +2020-08-26 Alan Modra + + PR 26447 + * expr.c (expr ): Do an unsigned shift. + +2020-08-25 Alan Modra + 2020-08-26 David Faust * config/tc-bpf.c: Add option -mxbpf to select xbpf isa. @@ -9,7 +16,7 @@ 2020-08-25 Alan Modra - PR26501 + PR 26501 * gas/config/tc-tic54x.c (tic54x_undefined_symbol): Properly treat misc_symbol_hash entries without values. diff --git a/gas/expr.c b/gas/expr.c index 23a6a003b9c..7c002c0d964 100644 --- a/gas/expr.c +++ b/gas/expr.c @@ -1933,12 +1933,21 @@ expr (int rankarg, /* Larger # is higher rank. */ case O_multiply: resultP->X_add_number *= v; break; case O_divide: resultP->X_add_number /= v; break; case O_modulus: resultP->X_add_number %= v; break; - case O_left_shift: resultP->X_add_number <<= v; break; + case O_left_shift: + /* We always use unsigned shifts. According to the ISO + C standard, left shift of a signed type having a + negative value is undefined behaviour, and right + shift of a signed type having negative value is + implementation defined. Left shift of a signed type + when the result overflows is also undefined + behaviour. So don't trigger ubsan warnings or rely + on characteristics of the compiler. */ + resultP->X_add_number + = (valueT) resultP->X_add_number << (valueT) v; + break; case O_right_shift: - /* We always use unsigned shifts, to avoid relying on - characteristics of the compiler used to compile gas. */ - resultP->X_add_number = - (offsetT) ((valueT) resultP->X_add_number >> (valueT) v); + resultP->X_add_number + = (valueT) resultP->X_add_number >> (valueT) v; break; case O_bit_inclusive_or: resultP->X_add_number |= v; break; case O_bit_or_not: resultP->X_add_number |= ~v; break;