PR26466 UBSAN: elf32-mep.c:300 left shift of negative value

Alan Modra amodra@gmail.com
Mon Aug 31 10:50:28 GMT 2020


	PR 26466
	* mep-relocs.pl (emit_apply): Handle HI16S adjustment.  Use "u"
	variable and rewrite signed overflow check.
	* elf32-mep.c: Regenerate.
	(mep_final_link_relocate): Delete "s".

diff --git a/bfd/elf32-mep.c b/bfd/elf32-mep.c
index c5775de649..ef8c10049e 100644
--- a/bfd/elf32-mep.c
+++ b/bfd/elf32-mep.c
@@ -221,7 +221,6 @@ mep_final_link_relocate
      bfd_vma		 relocation)
 {
   unsigned long u;
-  long s;
   unsigned char *byte;
   bfd_vma pc;
   bfd_reloc_status_type r = bfd_reloc_ok;
@@ -242,12 +241,12 @@ mep_final_link_relocate
 	+ input_section->output_offset
 	+ rel->r_offset);
 
-  s = relocation + rel->r_addend;
+  u = relocation + rel->r_addend;
 
   byte = (unsigned char *)contents + rel->r_offset;
 
   if (howto->type == R_MEP_PCREL24A2
-      && s == 0
+      && u == 0
       && pc >= 0x800000)
     {
       /* This is an unreachable branch to an undefined weak function.
@@ -257,9 +256,7 @@ mep_final_link_relocate
     }
 
   if (howto->pc_relative)
-    s -= pc;
-
-  u = (unsigned long) s;
+    u -= pc;
 
   switch (howto->type)
     {
@@ -281,25 +278,25 @@ mep_final_link_relocate
       byte[3^e4] = (u & 0xff);
       break;
     case R_MEP_PCREL8A2: /* --------7654321- */
-      if (-128 > s || s > 127) r = bfd_reloc_overflow;
-      byte[1^e2] = (byte[1^e2] & 0x01) | (s & 0xfe);
+      if (u + 128 > 255) r = bfd_reloc_overflow;
+      byte[1^e2] = (byte[1^e2] & 0x01) | (u & 0xfe);
       break;
     case R_MEP_PCREL12A2: /* ----ba987654321- */
-      if (-2048 > s || s > 2047) r = bfd_reloc_overflow;
-      byte[0^e2] = (byte[0^e2] & 0xf0) | ((s >> 8) & 0x0f);
-      byte[1^e2] = (byte[1^e2] & 0x01) | (s & 0xfe);
+      if (u + 2048 > 4095) r = bfd_reloc_overflow;
+      byte[0^e2] = (byte[0^e2] & 0xf0) | ((u >> 8) & 0x0f);
+      byte[1^e2] = (byte[1^e2] & 0x01) | (u & 0xfe);
       break;
     case R_MEP_PCREL17A2: /* ----------------gfedcba987654321 */
-      if (-65536 > s || s > 65535) r = bfd_reloc_overflow;
-      byte[2^e2] = ((s >> 9) & 0xff);
-      byte[3^e2] = ((s >> 1) & 0xff);
+      if (u + 65536 > 131071) r = bfd_reloc_overflow;
+      byte[2^e2] = ((u >> 9) & 0xff);
+      byte[3^e2] = ((u >> 1) & 0xff);
       break;
     case R_MEP_PCREL24A2: /* -----7654321----nmlkjihgfedcba98 */
-      if (-8388608 > s || s > 8388607) r = bfd_reloc_overflow;
-      byte[0^e2] = (byte[0^e2] & 0xf8) | ((s >> 5) & 0x07);
-      byte[1^e2] = (byte[1^e2] & 0x0f) | ((s << 3) & 0xf0);
-      byte[2^e2] = ((s >> 16) & 0xff);
-      byte[3^e2] = ((s >> 8) & 0xff);
+      if (u + 8388608 > 16777215) r = bfd_reloc_overflow;
+      byte[0^e2] = (byte[0^e2] & 0xf8) | ((u >> 5) & 0x07);
+      byte[1^e2] = (byte[1^e2] & 0x0f) | ((u << 3) & 0xf0);
+      byte[2^e2] = ((u >> 16) & 0xff);
+      byte[3^e2] = ((u >> 8) & 0xff);
       break;
     case R_MEP_PCABS24A2: /* -----7654321----nmlkjihgfedcba98 */
       if (u > 16777215) r = bfd_reloc_overflow;
@@ -317,22 +314,21 @@ mep_final_link_relocate
       byte[3^e2] = ((u >> 16) & 0xff);
       break;
     case R_MEP_HI16S: /* ----------------vutsrqponmlkjihg */
-      if (s & 0x8000)
-	s += 0x10000;
-      byte[2^e2] = ((s >> 24) & 0xff);
-      byte[3^e2] = ((s >> 16) & 0xff);
+      u += 0x8000;
+      byte[2^e2] = ((u >> 24) & 0xff);
+      byte[3^e2] = ((u >> 16) & 0xff);
       break;
     case R_MEP_GPREL: /* ----------------fedcba9876543210 */
-      s -= mep_sdaoff_base(rel->r_offset);
-      if (-32768 > s || s > 32767) r = bfd_reloc_overflow;
-      byte[2^e2] = ((s >> 8) & 0xff);
-      byte[3^e2] = (s & 0xff);
+      u -= mep_sdaoff_base(rel->r_offset);
+      if (u + 32768 > 65535) r = bfd_reloc_overflow;
+      byte[2^e2] = ((u >> 8) & 0xff);
+      byte[3^e2] = (u & 0xff);
       break;
     case R_MEP_TPREL: /* ----------------fedcba9876543210 */
-      s -= mep_tpoff_base(rel->r_offset);
-      if (-32768 > s || s > 32767) r = bfd_reloc_overflow;
-      byte[2^e2] = ((s >> 8) & 0xff);
-      byte[3^e2] = (s & 0xff);
+      u -= mep_tpoff_base(rel->r_offset);
+      if (u + 32768 > 65535) r = bfd_reloc_overflow;
+      byte[2^e2] = ((u >> 8) & 0xff);
+      byte[3^e2] = (u & 0xff);
       break;
     case R_MEP_TPREL7: /* ---------6543210 */
       u -= mep_tpoff_base(rel->r_offset);
diff --git a/bfd/mep-relocs.pl b/bfd/mep-relocs.pl
index 599ff6436a..544ee012a7 100755
--- a/bfd/mep-relocs.pl
+++ b/bfd/mep-relocs.pl
@@ -156,20 +156,23 @@ sub emit_apply {
 	    $e = '^e4' # endian swap for data
 	}
 	print NEW "    case R_MEP_$relocs[$i]: /* $pattern[$i] */\n";
+	if ($relocs[$i] =~ /HI16S/) {
+	    print NEW "      u += 0x8000;\n"
+	}
 	if ($attrs[$i] =~ /tp-rel/i) {
-	    print NEW "      $v -= mep_tpoff_base(rel->r_offset);\n";
+	    print NEW "      u -= mep_tpoff_base(rel->r_offset);\n";
 	}
 	if ($attrs[$i] =~ /gp-rel/i) {
-	    print NEW "      $v -= mep_sdaoff_base(rel->r_offset);\n";
+	    print NEW "      u -= mep_sdaoff_base(rel->r_offset);\n";
 	}
 	if ($attrs[$i] !~ /no-overflow/ && $bits[$i] < 32) {
 	    if ($v eq "u") {
 		$max = (1 << $bits[$i]) - 1;
 		print NEW "      if (u > $max) r = bfd_reloc_overflow;\n";
 	    } else {
-		$min = -(1 << ($bits[$i]-1));
-		$max = (1 << ($bits[$i]-1)) - 1;
-		print NEW "      if ($min > s || s > $max) r = bfd_reloc_overflow;\n";
+		$min = (1 << ($bits[$i]-1));
+		$max = (1 << ($bits[$i])) - 1;
+		print NEW "      if (u + $min > $max) r = bfd_reloc_overflow;\n";
 	    }
 	}
 	for ($b=0; $b<length($pattern[$i]); $b += 8) {
@@ -183,11 +186,11 @@ sub emit_apply {
 		print NEW "      byte[$bb$e] = ";
 		print NEW "(byte[$bb$e] & 0x$rmask) | " if $rmask ne "00";
 		if ($left) {
-		    print NEW "(($v << $left) & 0x$mask)";
+		    print NEW "((u << $left) & 0x$mask)";
 		} elsif ($right) {
-		    print NEW "(($v >> $right) & 0x$mask)";
+		    print NEW "((u >> $right) & 0x$mask)";
 		} else {
-		    print NEW "($v & 0x$mask)";
+		    print NEW "(u & 0x$mask)";
 		}
 		print NEW ";\n";
 	    }


More information about the Binutils mailing list