[binutils-gdb] PR26447 UBSAN: expr.c:1936 left shift of negative value

Alan Modra amodra@sourceware.org
Wed Aug 26 13:54:41 GMT 2020


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=b2f386b99caeab72eae26ca5bc9024421de145d9

commit b2f386b99caeab72eae26ca5bc9024421de145d9
Author: Alan Modra <amodra@gmail.com>
Date:   Wed Aug 26 14:55:39 2020 +0930

    PR26447 UBSAN: expr.c:1936 left shift of negative value
    
            PR 26447
            * expr.c (expr <O_left_shift>): Do an unsigned shift.

Diff:
---
 gas/ChangeLog |  9 ++++++++-
 gas/expr.c    | 19 ++++++++++++++-----
 2 files changed, 22 insertions(+), 6 deletions(-)

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  <amodra@gmail.com>
+
+	PR 26447
+	* expr.c (expr <O_left_shift>): Do an unsigned shift.
+
+2020-08-25  Alan Modra  <amodra@gmail.com>
+
 2020-08-26  David Faust  <david.faust@oracle.com>
 
 	* config/tc-bpf.c: Add option -mxbpf to select xbpf isa.
@@ -9,7 +16,7 @@
 
 2020-08-25  Alan Modra  <amodra@gmail.com>
 
-	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;


More information about the Binutils-cvs mailing list