PR26469 UBSAN: elflink.c:8742 shift exponent 6148914691236511722
authorAlan Modra <amodra@gmail.com>
Thu, 27 Aug 2020 12:14:41 +0000 (21:44 +0930)
committerAlan Modra <amodra@gmail.com>
Thu, 27 Aug 2020 12:35:00 +0000 (22:05 +0930)
PR 26469
* elflink.c: Include limits.h.
(CHAR_BIT): Provide fallback define.
(set_symbol_value): Correct complex reloc comment.
(undefined_reference): Set bfd_error.
(BINARY_OP_HEAD, BINARY_OP_TAIL): Split out from..
(BINARY_OP): ..this.
(eval_symbol): Limit shifts.  Force unsigned for left shift.
Catch divide by zero.
* configure.ac (AC_CHECK_HEADERS): Combine, sort and add limits.h.
* configure: Regenerate.
* config.in: Regenerate.

bfd/ChangeLog
bfd/config.in
bfd/configure
bfd/configure.ac
bfd/elflink.c

index 6d3ba691da9116808d6b509c589252a7b3f5f46b..1d783f73830a0079e5d5ca574e3c96814a781e2a 100644 (file)
@@ -1,3 +1,18 @@
+2020-08-27  Alan Modra  <amodra@gmail.com>
+
+       PR 26469
+       * elflink.c: Include limits.h.
+       (CHAR_BIT): Provide fallback define.
+       (set_symbol_value): Correct complex reloc comment.
+       (undefined_reference): Set bfd_error.
+       (BINARY_OP_HEAD, BINARY_OP_TAIL): Split out from..
+       (BINARY_OP): ..this.
+       (eval_symbol): Limit shifts.  Force unsigned for left shift.
+       Catch divide by zero.
+       * configure.ac (AC_CHECK_HEADERS): Combine, sort and add limits.h.
+       * configure: Regenerate.
+       * config.in: Regenerate.
+
 2020-08-27  Alan Modra  <amodra@gmail.com>
 
        PR 26462
index c7be6c5176499a16dc9ba37d3b4ee6bf8d5afaf5..18fb8aeb50c327604a4f305d03ff2256356ed04a 100644 (file)
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
 /* Define to 1 if the system has the type `long double'. */
 #undef HAVE_LONG_DOUBLE
 
index ece165668247f4d4ba26cbc5453aac5be614eb6c..a9c4fd93669e77a46c1fdc77939f8fa17925455d 100755 (executable)
@@ -13531,20 +13531,9 @@ $as_echo "$bfd_cv_build_exeext" >&6; }
 fi
 
 
-for ac_header in alloca.h stddef.h string.h strings.h stdlib.h time.h unistd.h wchar.h wctype.h
-do :
-  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-for ac_header in fcntl.h sys/file.h sys/time.h sys/stat.h sys/resource.h
+for ac_header in alloca.h fcntl.h limits.h stddef.h stdlib.h string.h \
+                strings.h sys/file.h sys/resource.h sys/stat.h sys/time.h \
+                time.h unistd.h wchar.h wctype.h
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
 ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
index ae2de1318730c4612686fe6babb4df0a4ef2cd17..f62659acd7fbe3a62bb4ddd9262d468845d4ce30 100644 (file)
@@ -243,8 +243,9 @@ AC_SUBST(BFD_HOSTPTR_T)
 
 BFD_CC_FOR_BUILD
 
-AC_CHECK_HEADERS(alloca.h stddef.h string.h strings.h stdlib.h time.h unistd.h wchar.h wctype.h)
-AC_CHECK_HEADERS(fcntl.h sys/file.h sys/time.h sys/stat.h sys/resource.h)
+AC_CHECK_HEADERS(alloca.h fcntl.h limits.h stddef.h stdlib.h string.h \
+                strings.h sys/file.h sys/resource.h sys/stat.h sys/time.h \
+                time.h unistd.h wchar.h wctype.h)
 GCC_HEADER_STDINT(bfd_stdint.h)
 AC_HEADER_TIME
 AC_HEADER_DIRENT
@@ -1104,7 +1105,6 @@ AC_MSG_RESULT($bfd_file_ptr)
 AC_SUBST(bfd_file_ptr)
 AC_SUBST(bfd_ufile_ptr)
 
-dnl AC_CHECK_HEADERS(sys/mman.h)
 AC_FUNC_MMAP
 AC_CHECK_FUNCS(madvise mprotect)
 case ${want_mmap}+${ac_cv_func_mmap_fixed_mapped} in
index 17a423270ec147f3044c79ed0206dd57543d2cd0..5c085b14b79cd5f04ea0b871c8a207fbf779f8f8 100644 (file)
 #include "plugin.h"
 #endif
 
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
 /* This struct is used to pass information to routines called via
    elf_link_hash_traverse which must return failure.  */
 
@@ -8427,12 +8434,12 @@ struct elf_outext_info
    implementation of them consists of two parts: complex symbols, and the
    relocations themselves.
 
-   The relocations are use a reserved elf-wide relocation type code (R_RELC
+   The relocations use a reserved elf-wide relocation type code (R_RELC
    external / BFD_RELOC_RELC internal) and an encoding of relocation field
    information (start bit, end bit, word width, etc) into the addend.  This
    information is extracted from CGEN-generated operand tables within gas.
 
-   Complex symbols are mangled symbols (BSF_RELC external / STT_RELC
+   Complex symbols are mangled symbols (STT_RELC external / BSF_RELC
    internal) representing prefix-notation expressions, including but not
    limited to those sorts of expressions normally encoded as addends in the
    addend field.  The symbol mangling format is:
@@ -8607,6 +8614,7 @@ undefined_reference (const char *reftype, const char *name)
   /* xgettext:c-format */
   _bfd_error_handler (_("undefined %s reference in complex symbol: %s"),
                      reftype, name);
+  bfd_set_error (bfd_error_bad_value);
 }
 
 static bfd_boolean
@@ -8715,7 +8723,7 @@ eval_symbol (bfd_vma *result,
       return TRUE;                                             \
     }
 
-#define BINARY_OP(op)                                          \
+#define BINARY_OP_HEAD(op)                                     \
   if (strncmp (sym, #op, strlen (#op)) == 0)                   \
     {                                                          \
       sym += strlen (#op);                                     \
@@ -8728,18 +8736,33 @@ eval_symbol (bfd_vma *result,
       ++*symp;                                                 \
       if (!eval_symbol (&b, symp, input_bfd, flinfo, dot,      \
                        isymbuf, locsymcount, signed_p))        \
-       return FALSE;                                           \
+       return FALSE;
+#define BINARY_OP_TAIL(op)                                     \
       if (signed_p)                                            \
        *result = ((bfd_signed_vma) a) op ((bfd_signed_vma) b); \
       else                                                     \
        *result = a op b;                                       \
       return TRUE;                                             \
     }
+#define BINARY_OP(op) BINARY_OP_HEAD(op) BINARY_OP_TAIL(op)
 
     default:
       UNARY_OP  (0-);
-      BINARY_OP (<<);
-      BINARY_OP (>>);
+      BINARY_OP_HEAD (<<);
+      if (b >= sizeof (a) * CHAR_BIT)
+       {
+         *result = 0;
+         return TRUE;
+       }
+      signed_p = 0;
+      BINARY_OP_TAIL (<<);
+      BINARY_OP_HEAD (>>);
+      if (b >= sizeof (a) * CHAR_BIT)
+       {
+         *result = signed_p && (bfd_signed_vma) a < 0 ? -1 : 0;
+         return TRUE;
+       }
+      BINARY_OP_TAIL (>>);
       BINARY_OP (==);
       BINARY_OP (!=);
       BINARY_OP (<=);
@@ -8749,8 +8772,22 @@ eval_symbol (bfd_vma *result,
       UNARY_OP  (~);
       UNARY_OP  (!);
       BINARY_OP (*);
-      BINARY_OP (/);
-      BINARY_OP (%);
+      BINARY_OP_HEAD (/);
+      if (b == 0)
+       {
+         _bfd_error_handler (_("division by zero"));
+         bfd_set_error (bfd_error_bad_value);
+         return FALSE;
+       }
+      BINARY_OP_TAIL (/);
+      BINARY_OP_HEAD (%);
+      if (b == 0)
+       {
+         _bfd_error_handler (_("division by zero"));
+         bfd_set_error (bfd_error_bad_value);
+         return FALSE;
+       }
+      BINARY_OP_TAIL (%);
       BINARY_OP (^);
       BINARY_OP (|);
       BINARY_OP (&);