diff options
author | Alan Modra <amodra@gmail.com> | 2020-08-27 21:44:41 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2020-08-27 22:05:00 +0930 |
commit | 4b69ce9b9121090ac42cf8fa20b949bbd9afff95 (patch) | |
tree | 196408e74cea24562bea850fc2ff4a8c6850e383 | |
parent | 6fbd4a8e8baa7fe5adcaa1c11c885f741fccd250 (diff) | |
download | gdb-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/ChangeLog | 15 | ||||
-rw-r--r-- | bfd/config.in | 3 | ||||
-rwxr-xr-x | bfd/configure | 17 | ||||
-rw-r--r-- | bfd/configure.ac | 6 | ||||
-rw-r--r-- | bfd/elflink.c | 53 |
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 (&); |