gas signed overflow fixes
authorAlan Modra <amodra@gmail.com>
Wed, 11 Dec 2019 22:59:45 +0000 (09:29 +1030)
committerAlan Modra <amodra@gmail.com>
Thu, 12 Dec 2019 11:28:33 +0000 (21:58 +1030)
* config/tc-aarch64.c (get_aarch64_insn): Avoid signed overflow.
* config/tc-metag.c (parse_dalu): Likewise.
* config/tc-tic4x.c (md_pcrel_from): Likewise.
* config/tc-tic6x.c (tic6x_output_unwinding): Likewise.
* config/tc-csky.c (parse_fexp): Use an unsigned char temp buffer.
Don't use register keyword.  Avoid signed overflow and remove now
unneccesary char masks.  Formatting.
* config/tc-ia64.c (operand_match): Don't use shifts to sign extend.
* config/tc-mep.c (mep_apply_fix): Likewise.
* config/tc-pru.c (md_apply_fix): Likewise.
* config/tc-riscv.c (load_const): Likewise.
* config/tc-nios2.c (md_apply_fix): Likewise.  Don't potentially
truncate fixup before right shift.  Tidy BFD_RELOC_NIOS2_HIADJ16
calculation.

gas/ChangeLog
gas/config/tc-aarch64.c
gas/config/tc-csky.c
gas/config/tc-ia64.c
gas/config/tc-mep.c
gas/config/tc-metag.c
gas/config/tc-nios2.c
gas/config/tc-pru.c
gas/config/tc-riscv.c
gas/config/tc-tic4x.c
gas/config/tc-tic6x.c

index d8c5a17b3d3c95e63903036a6663e6841eb0ca03..a65b7d37a2898e5864507e7fbc671ea72e7c9f73 100644 (file)
@@ -1,3 +1,20 @@
+2019-12-12  Alan Modra  <amodra@gmail.com>
+
+       * config/tc-aarch64.c (get_aarch64_insn): Avoid signed overflow.
+       * config/tc-metag.c (parse_dalu): Likewise.
+       * config/tc-tic4x.c (md_pcrel_from): Likewise.
+       * config/tc-tic6x.c (tic6x_output_unwinding): Likewise.
+       * config/tc-csky.c (parse_fexp): Use an unsigned char temp buffer.
+       Don't use register keyword.  Avoid signed overflow and remove now
+       unneccesary char masks.  Formatting.
+       * config/tc-ia64.c (operand_match): Don't use shifts to sign extend.
+       * config/tc-mep.c (mep_apply_fix): Likewise.
+       * config/tc-pru.c (md_apply_fix): Likewise.
+       * config/tc-riscv.c (load_const): Likewise.
+       * config/tc-nios2.c (md_apply_fix): Likewise.  Don't potentially
+       truncate fixup before right shift.  Tidy BFD_RELOC_NIOS2_HIADJ16
+       calculation.
+
 2019-12-12  Alan Modra  <amodra@gmail.com>
 
        * config/obj-evax.c (crc32, encode_32, encode_16, decode_16):
index cd4601682beb4e03a943029a50c60fe8546680ba..8879451440057396cc51a50742ed0beb378f7aca 100644 (file)
@@ -5024,7 +5024,8 @@ get_aarch64_insn (char *buf)
 {
   unsigned char *where = (unsigned char *) buf;
   uint32_t result;
-  result = (where[0] | (where[1] << 8) | (where[2] << 16) | (where[3] << 24));
+  result = ((where[0] | (where[1] << 8) | (where[2] << 16)
+            | ((uint32_t) where[3] << 24)));
   return result;
 }
 
index 970c72afaf00c258ffade268d5e9def287e1ff53..6fa6ee5dd6a5f15bb557e13e67ea82380c0e2f9c 100644 (file)
@@ -1777,8 +1777,8 @@ static char *
 parse_fexp (char *s, expressionS *e, unsigned char isdouble, uint64_t *dbnum)
 {
   int length;                       /* Number of chars in an object.  */
-  register char const *err = NULL;  /* Error from scanning float literal.  */
-  char temp[8];
+  const char *err = NULL;           /* Error from scanning float literal.  */
+  unsigned char temp[8];
 
   /* input_line_pointer->1st char of a flonum (we hope!).  */
   input_line_pointer = s;
@@ -1788,9 +1788,9 @@ parse_fexp (char *s, expressionS *e, unsigned char isdouble, uint64_t *dbnum)
     input_line_pointer += 2;
 
   if (isdouble)
-    err = md_atof ('d', temp, &length);
+    err = md_atof ('d', (char *) temp, &length);
   else
-    err = md_atof ('f', temp, &length);
+    err = md_atof ('f', (char *) temp, &length);
   know (length <= 8);
   know (err != NULL || length > 0);
 
@@ -1818,41 +1818,42 @@ parse_fexp (char *s, expressionS *e, unsigned char isdouble, uint64_t *dbnum)
     {
       uint32_t fnum;
       if (target_big_endian)
-       fnum = (((temp[0] << 24) & 0xffffffff)
-               | ((temp[1] << 16) & 0xffffff)
-               | ((temp[2] << 8) & 0xffff)
-               | (temp[3] & 0xff));
+       fnum = (((uint32_t) temp[0] << 24)
+               | (temp[1] << 16)
+               | (temp[2] << 8)
+               | temp[3]);
       else
-       fnum = (((temp[3] << 24) & 0xffffffff)
-                          | ((temp[2] << 16) & 0xffffff)
-                          | ((temp[1] << 8) & 0xffff)
-                          | (temp[0] & 0xff));
-      e->X_add_number = fnum;    }
+       fnum = (((uint32_t) temp[3] << 24)
+               | (temp[2] << 16)
+               | (temp[1] << 8)
+               | temp[0]);
+      e->X_add_number = fnum;
+    }
   else
     {
       if (target_big_endian)
        {
-         *dbnum = (((temp[0] << 24) & 0xffffffff)
-                   | ((temp[1] << 16) & 0xffffff)
-                   | ((temp[2] << 8) & 0xffff)
-                   | (temp[3] & 0xff));
+         *dbnum = (((uint32_t) temp[0] << 24)
+                   | (temp[1] << 16)
+                   | (temp[2] << 8)
+                   | temp[3]);
          *dbnum <<= 32;
-         *dbnum |= (((temp[4] << 24) & 0xffffffff)
-                    | ((temp[5] << 16) & 0xffffff)
-                    | ((temp[6] << 8) & 0xffff)
-                    | (temp[7] & 0xff));
+         *dbnum |= (((uint32_t) temp[4] << 24)
+                    | (temp[5] << 16)
+                    | (temp[6] << 8)
+                    | temp[7]);
        }
       else
        {
-         *dbnum = (((temp[7] << 24) & 0xffffffff)
-                   | ((temp[6] << 16) & 0xffffff)
-                   | ((temp[5] << 8) & 0xffff)
-                   | (temp[4] & 0xff));
+         *dbnum = (((uint32_t) temp[7] << 24)
+                   | (temp[6] << 16)
+                   | (temp[5] << 8)
+                   | temp[4]);
          *dbnum <<= 32;
-         *dbnum |= (((temp[3] << 24) & 0xffffffff)
-                    | ((temp[2] << 16) & 0xffffff)
-                    | ((temp[1] << 8) & 0xffff)
-                    | (temp[0] & 0xff));
+         *dbnum |= (((uint32_t) temp[3] << 24)
+                    | (temp[2] << 16)
+                    | (temp[1] << 8)
+                    | temp[0]);
       }
     }
   return input_line_pointer;
index 0c618e811eeb701a88f92b459de5810540ad7bdc..5eb024e92ba3128ed89da4bb5b739430da9149e3 100644 (file)
@@ -5839,9 +5839,8 @@ operand_match (const struct ia64_opcode *idesc, int res_index, expressionS *e)
          /* Sign-extend 32-bit unsigned numbers, so that the following range
             checks will work.  */
          val = e->X_add_number;
-         if (((val & (~(bfd_vma) 0 << 32)) == 0)
-             && ((val & ((bfd_vma) 1 << 31)) != 0))
-           val = ((val << 32) >> 32);
+         if ((val & (~(bfd_vma) 0 << 32)) == 0)
+           val = (val ^ ((bfd_vma) 1 << 31)) - ((bfd_vma) 1 << 31);
 
          /* Check for 0x100000000.  This is valid because
             0x100000000-1 is the same as ((uint32_t) -1).  */
@@ -5879,9 +5878,8 @@ operand_match (const struct ia64_opcode *idesc, int res_index, expressionS *e)
          /* Sign-extend 32-bit unsigned numbers, so that the following range
             checks will work.  */
          val = e->X_add_number;
-         if (((val & (~(bfd_vma) 0 << 32)) == 0)
-             && ((val & ((bfd_vma) 1 << 31)) != 0))
-           val = ((val << 32) >> 32);
+         if ((val & (~(bfd_vma) 0 << 32)) == 0)
+           val = (val ^ ((bfd_vma) 1 << 31)) - ((bfd_vma) 1 << 31);
        }
       else
        val = e->X_add_number;
index c0d48e835437fb68fcb834d6f6db24a952957cfd..18e96c80465d2c2a17e817edf2f3277b389c2a6c 100644 (file)
@@ -1790,7 +1790,7 @@ mep_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
     switch (fixP->fx_cgen.opinfo)
       {
       case BFD_RELOC_MEP_LOW16:
-       *valP = ((long)(*valP & 0xffff)) << 16 >> 16;
+       *valP = ((*valP & 0xffff) ^ 0x8000) - 0x8000;
        break;
       case BFD_RELOC_MEP_HI16U:
        *valP >>= 16;
index c7bb36d5b9c57b80d8e17456506e9a5ebc999eba..d056e9adf705445a265106f7a479144a4cd3b22c 100644 (file)
@@ -5340,7 +5340,7 @@ parse_dalu (const char *line, metag_insn *insn,
              /* Only MOV instructions have a DSP register as a
                 destination. Set the MOV DSPe.r opcode. The simple
                 OR'ing is OK because the usual MOV opcode is 0x00.  */
-             insn->bits = (0x91 << 24);
+             insn->bits = 0x91u << 24;
              du_shift = 0;
              l1_shift = 2;
              regs_shift[0] = 19;
@@ -5455,7 +5455,7 @@ parse_dalu (const char *line, metag_insn *insn,
                          du_shift = 0;
                          l1_shift = 2;
                          regs_shift[1] = 14;
-                         insn->bits = (0x92 << 24); /* Set opcode.  */
+                         insn->bits = 0x92u << 24; /* Set opcode.  */
                        }
                    }
                }
index ec572a61ce63c80735d6f8b40d65aa386d167e29..f1a02001f8c59054621ac835ac23c4f0c3612511 100644 (file)
@@ -1384,7 +1384,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
            nios2_diagnose_overflow (fixup, howto, fixP, value);
 
          /* Apply the right shift.  */
-         fixup = ((signed)fixup) >> howto->rightshift;
+         fixup = (offsetT) fixup >> howto->rightshift;
 
          /* Truncate the fixup to right size.  */
          switch (fixP->fx_r_type)
@@ -1396,13 +1396,11 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
              fixup = fixup & 0xFFFF;
              break;
            case BFD_RELOC_NIOS2_HIADJ16:
-             fixup = ((((fixup >> 16) & 0xFFFF) + ((fixup >> 15) & 0x01))
-                      & 0xFFFF);
+             fixup = ((fixup + 0x8000) >> 16) & 0xFFFF;
              break;
            default:
              {
-               int n = sizeof (fixup) * 8 - howto->bitsize;
-               fixup = (fixup << n) >> n;
+               fixup &= ((valueT) 1 << howto->bitsize) - 1;
                break;
              }
            }
index 2e2058c1debb81adf60dd9ddba744caee1d4577e..6de9f3ce48225bced85851afb0d219e9da22999d 100644 (file)
@@ -642,7 +642,6 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 {
   unsigned char *where;
   valueT value = *valP;
-  long n;
 
   /* Assert that the fixup is one we can handle.  */
   gas_assert (fixP != NULL && valP != NULL
@@ -801,11 +800,13 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
            pru_diagnose_overflow (fixup, howto, fixP, insn);
 
          /* Apply the right shift.  */
-         fixup = ((offsetT)fixup) >> howto->rightshift;
+         fixup = (offsetT) fixup >> howto->rightshift;
 
          /* Truncate the fixup to right size.  */
-         n = sizeof (fixup) * 8 - howto->bitsize;
-         fixup = (fixup << n) >> n;
+         if (howto->bitsize == 0)
+           fixup = 0;
+         else
+           fixup &= ((valueT) 2 << (howto->bitsize - 1)) - 1;
 
          /* Fix up the instruction.  Non-contiguous bitfields need
             special handling.  */
index 055d80c3444431d5b3305f72970fb96958cde4b4..7ec1028b283657687c577e2325b6c5f7bfe90d0d 100644 (file)
@@ -1043,9 +1043,9 @@ static void
 load_const (int reg, expressionS *ep)
 {
   int shift = RISCV_IMM_BITS;
-  bfd_vma upper_imm;
+  bfd_vma upper_imm, sign = (bfd_vma) 1 << (RISCV_IMM_BITS - 1);
   expressionS upper = *ep, lower = *ep;
-  lower.X_add_number = (int32_t) ep->X_add_number << (32-shift) >> (32-shift);
+  lower.X_add_number = ((ep->X_add_number & (sign + sign - 1)) ^ sign) - sign;
   upper.X_add_number -= lower.X_add_number;
 
   if (ep->X_op != O_constant)
index b5588b9c46716e3cb015f441a4e5f41d1eff808c..bbbd696e43e7dafefcb3e52c6f95151afcc84d9b 100644 (file)
@@ -2937,7 +2937,7 @@ md_pcrel_from (fixS *fixP)
   unsigned int op;
 
   buf = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where;
-  op = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
+  op = ((unsigned) buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
 
   return ((fixP->fx_where + fixP->fx_frag->fr_address) >> 2) +
     tic4x_pc_offset (op);
index cd12c82dce164c01d60922115f5dfc1ef13dd0dd..6260ecb983319915e0a86e7b1be42eb4a24f0a08 100644 (file)
@@ -5060,7 +5060,7 @@ tic6x_output_unwinding (bfd_boolean need_extab)
       if (unwind->personality_index == -1)
        {
          tmp = md_chars_to_number (unwind->frag_start + 4, 4);
-         tmp |= ((unwind->data_bytes - 8) >> 2) << 24;
+         tmp |= (valueT) ((unwind->data_bytes - 8) >> 2) << 24;
          md_number_to_chars (unwind->frag_start + 4, tmp, 4);
        }
       else if (unwind->personality_index == 1 || unwind->personality_index == 2)