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 be3ae38..f9e81d3 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 6676dff..d98a9d2 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 b6800f1..0b297cb 100644 (file)
@@ -1,6 +1,12 @@
 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
        * readelf.c (process_program_headers): Correct fscanf format used
        for interpreter.
 
index 3f4095a..ee982de 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 5eb4813..1b4fda9 100644 (file)
@@ -1,5 +1,15 @@
 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.
 
 2014-10-09  Jose E. Marchesi  <jose.marchesi@oracle.com>
index 68ca7e4..38e9781 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 eb7255f..0ccfbd3 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 2d5fdf1..9fd0335 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 0657b56..263b002 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)