aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2020-08-27 21:44:41 +0930
committerAlan Modra <amodra@gmail.com>2020-08-27 22:05:00 +0930
commit4b69ce9b9121090ac42cf8fa20b949bbd9afff95 (patch)
tree196408e74cea24562bea850fc2ff4a8c6850e383
parent6fbd4a8e8baa7fe5adcaa1c11c885f741fccd250 (diff)
downloadgdb-4b69ce9b9121090ac42cf8fa20b949bbd9afff95.zip
gdb-4b69ce9b9121090ac42cf8fa20b949bbd9afff95.tar.gz
gdb-4b69ce9b9121090ac42cf8fa20b949bbd9afff95.tar.bz2
PR26469 UBSAN: elflink.c:8742 shift exponent 6148914691236511722
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.
-rw-r--r--bfd/ChangeLog15
-rw-r--r--bfd/config.in3
-rwxr-xr-xbfd/configure17
-rw-r--r--bfd/configure.ac6
-rw-r--r--bfd/elflink.c53
5 files changed, 69 insertions, 25 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 6d3ba69..1d783f7 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,20 @@
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
* reloc.c (bfd_check_overflow): Return early if zero bitsize.
diff --git a/bfd/config.in b/bfd/config.in
index c7be6c5..18fb8ae 100644
--- a/bfd/config.in
+++ b/bfd/config.in
@@ -143,6 +143,9 @@
/* 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
diff --git a/bfd/configure b/bfd/configure
index ece1656..a9c4fd9 100755
--- a/bfd/configure
+++ b/bfd/configure
@@ -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"
diff --git a/bfd/configure.ac b/bfd/configure.ac
index ae2de13..f62659a 100644
--- a/bfd/configure.ac
+++ b/bfd/configure.ac
@@ -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
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 17a4232..5c085b1 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -32,6 +32,13 @@
#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 (&);