Avoid undefined behaviour with signed expressions
authorAlan Modra <amodra@gmail.com>
Tue, 14 Oct 2014 03:06:20 +0000 (13:36 +1030)
committerAlan Modra <amodra@gmail.com>
Tue, 14 Oct 2014 04:06:35 +0000 (14:36 +1030)
PR 17453
bfd/
* libbfd.c (COERCE16, COERCE32, COERCE64): Use unsigned types.
(EIGHT_GAZILLION): Delete.
binutils/
* dwarf.c (read_leb128): Avoid signed overflow.
(read_debug_line_header): Likewise.
gas/
* config/tc-i386.c (fits_in_signed_long): Use unsigned param and
expression to avoid signed overflow.
(fits_in_signed_byte, fits_in_unsigned_byte, fits_in_unsigned_word,
fits_in_signed_word, fits_in_unsigned_long): Similarly.
* expr.c (operand <'-'>): Avoid signed overflow.
* read.c (s_comm_internal): Likewise.

bfd/ChangeLog
bfd/libbfd.c
binutils/ChangeLog
binutils/dwarf.c
gas/ChangeLog
gas/config/tc-i386.c
gas/expr.c
gas/read.c
gas/write.c

index be3ae3857b22911741d876ace561deb278ea11d7..f9e81d3ef5595869671495cb101a2b796f43de20 100644 (file)
@@ -1,3 +1,9 @@
+2014-10-14  Alan Modra  <amodra@gmail.com>
+
+       PR 17453
+       * libbfd.c (COERCE16, COERCE32, COERCE64): Use unsigned types.
+       (EIGHT_GAZILLION): Delete.
+
 2014-10-13  Alan Modra  <amodra@gmail.com>
 
        PR 17467
index 6676dffb045add73bf892d94ac34343bfd9488db..d98a9d28a696a1e8c6a84bab113e71aaa5867f3b 100644 (file)
@@ -548,11 +548,10 @@ DESCRIPTION
 .*/
 
 /* Sign extension to bfd_signed_vma.  */
-#define COERCE16(x) (((bfd_signed_vma) (x) ^ 0x8000) - 0x8000)
-#define COERCE32(x) (((bfd_signed_vma) (x) ^ 0x80000000) - 0x80000000)
-#define EIGHT_GAZILLION ((bfd_int64_t) 1 << 63)
+#define COERCE16(x) (((bfd_vma) (x) ^ 0x8000) - 0x8000)
+#define COERCE32(x) (((bfd_vma) (x) ^ 0x80000000) - 0x80000000)
 #define COERCE64(x) \
-  (((bfd_int64_t) (x) ^ EIGHT_GAZILLION) - EIGHT_GAZILLION)
+  (((bfd_uint64_t) (x) ^ ((bfd_uint64_t) 1 << 63)) - ((bfd_uint64_t) 1 << 63))
 
 bfd_vma
 bfd_getb16 (const void *p)
index b6800f1e7b3c4b28132747d46861f0e1b8743b50..0b297cbeb2505050e330bd00d6438ffd5568fe5d 100644 (file)
@@ -1,3 +1,9 @@
+2014-10-14  Alan Modra  <amodra@gmail.com>
+
+       PR 17453
+       * dwarf.c (read_leb128): Avoid signed overflow.
+       (read_debug_line_header): Likewise.
+
 2014-10-14  Alan Modra  <amodra@gmail.com>
 
        PR 17453
index 3f4095a26e683d1b7bffe5ae58b2855be5784225..ee982debe9f5fb6a8a6657889b5a40a53b38b2e9 100644 (file)
@@ -259,7 +259,7 @@ read_leb128 (unsigned char *data,
     *length_return = num_read;
 
   if (sign && (shift < 8 * sizeof (result)) && (byte & 0x40))
-    result |= -1L << shift;
+    result |= (dwarf_vma) -1 << shift;
 
   return result;
 }
@@ -2661,14 +2661,10 @@ read_debug_line_header (struct dwarf_section * section,
     linfo->li_max_ops_per_insn = 1;
 
   SAFE_BYTE_GET_AND_INC (linfo->li_default_is_stmt, hdrptr, 1, end);
-  SAFE_BYTE_GET_AND_INC (linfo->li_line_base, hdrptr, 1, end);
+  SAFE_SIGNED_BYTE_GET_AND_INC (linfo->li_line_base, hdrptr, 1, end);
   SAFE_BYTE_GET_AND_INC (linfo->li_line_range, hdrptr, 1, end);
   SAFE_BYTE_GET_AND_INC (linfo->li_opcode_base, hdrptr, 1, end);
 
-      /* Sign extend the line base field.  */
-  linfo->li_line_base <<= 24;
-  linfo->li_line_base >>= 24;
-
   * end_of_sequence = data + linfo->li_length + initial_length_size;
   return hdrptr;
 }
index 5eb4813d227b1089882b737403d2c96e5a8626cd..1b4fda974085f362bdce13c10df4e43278c29405 100644 (file)
@@ -1,3 +1,13 @@
+2014-10-14  Alan Modra  <amodra@gmail.com>
+
+       PR 17453
+       * config/tc-i386.c (fits_in_signed_long): Use unsigned param and
+       expression to avoid signed overflow.
+       (fits_in_signed_byte, fits_in_unsigned_byte, fits_in_unsigned_word,
+       fits_in_signed_word, fits_in_unsigned_long): Similarly.
+       * expr.c (operand <'-'>): Avoid signed overflow.
+       * read.c (s_comm_internal): Likewise.
+
 2014-10-14  Alan Modra  <amodra@gmail.com>
 
        * config/tc-sparc.c (sparc_md_end): Fix unused variable warnings.
index 68ca7e4ae70817af1ecc89f34fc6b48b09798130..38e978151756ff2a080c50dbc792c03709046155 100644 (file)
@@ -1946,47 +1946,46 @@ mode_from_disp_size (i386_operand_type t)
 }
 
 static INLINE int
-fits_in_signed_byte (offsetT num)
+fits_in_signed_byte (addressT num)
 {
-  return (num >= -128) && (num <= 127);
+  return num + 0x80 <= 0xff;
 }
 
 static INLINE int
-fits_in_unsigned_byte (offsetT num)
+fits_in_unsigned_byte (addressT num)
 {
-  return (num & 0xff) == num;
+  return num <= 0xff;
 }
 
 static INLINE int
-fits_in_unsigned_word (offsetT num)
+fits_in_unsigned_word (addressT num)
 {
-  return (num & 0xffff) == num;
+  return num <= 0xffff;
 }
 
 static INLINE int
-fits_in_signed_word (offsetT num)
+fits_in_signed_word (addressT num)
 {
-  return (-32768 <= num) && (num <= 32767);
+  return num + 0x8000 <= 0xffff;
 }
 
 static INLINE int
-fits_in_signed_long (offsetT num ATTRIBUTE_UNUSED)
+fits_in_signed_long (addressT num ATTRIBUTE_UNUSED)
 {
 #ifndef BFD64
   return 1;
 #else
-  return (!(((offsetT) -1 << 31) & num)
-         || (((offsetT) -1 << 31) & num) == ((offsetT) -1 << 31));
+  return num + 0x80000000 <= 0xffffffff;
 #endif
 }                              /* fits_in_signed_long() */
 
 static INLINE int
-fits_in_unsigned_long (offsetT num ATTRIBUTE_UNUSED)
+fits_in_unsigned_long (addressT num ATTRIBUTE_UNUSED)
 {
 #ifndef BFD64
   return 1;
 #else
-  return (num & (((offsetT) 2 << 31) - 1)) == num;
+  return num <= 0xffffffff;
 #endif
 }                              /* fits_in_unsigned_long() */
 
index eb7255fe5cf01309aaf113307db103eda2fba3c1..0ccfbd3b8e9205c414aa3989856a10a60909396a 100644 (file)
@@ -1021,7 +1021,8 @@ operand (expressionS *expressionP, enum expr_mode mode)
            /* input_line_pointer -> char after operand.  */
            if (c == '-')
              {
-               expressionP->X_add_number = - expressionP->X_add_number;
+               expressionP->X_add_number
+                 = - (addressT) expressionP->X_add_number;
                /* Notice: '-' may overflow: no warning is given.
                   This is compatible with other people's
                   assemblers.  Sigh.  */
index 2d5fdf1fdd4ddc3512cce0a408cebd6f3672ae00..9fd0335d8e1f3e9844e2326d36418c79dcdc6b33 100644 (file)
@@ -1704,7 +1704,7 @@ s_comm_internal (int param,
 
   temp = get_absolute_expr (&exp);
   size = temp;
-  size &= ((offsetT) 2 << (stdoutput->arch_info->bits_per_address - 1)) - 1;
+  size &= ((addressT) 2 << (stdoutput->arch_info->bits_per_address - 1)) - 1;
   if (exp.X_op == O_absent)
     {
       as_bad (_("missing size expression"));
index 0657b56216f4699a4ddd9489aca32f1b6fa0366f..263b002e3ce9990f24863cd53f94572c405e467a 100644 (file)
@@ -2309,7 +2309,7 @@ relax_align (register relax_addressT address,     /* Address now.  */
   relax_addressT mask;
   relax_addressT new_address;
 
-  mask = ~((~0) << alignment);
+  mask = ~((relax_addressT) ~0 << alignment);
   new_address = (address + mask) & (~mask);
 #ifdef LINKER_RELAXING_SHRINKS_ONLY
   if (linkrelax)