diff --git a/backport-0001-CVE-2021-42574.patch b/backport-0001-CVE-2021-42574.patch new file mode 100644 index 0000000000000000000000000000000000000000..f94a9583f8e57c1cd57e12551d9d7dccf23c5c4c --- /dev/null +++ b/backport-0001-CVE-2021-42574.patch @@ -0,0 +1,1959 @@ +From b3aa80b45c4f46029efeb204bb9f2d2c4278a0e5 Mon Sep 17 00:00:00 2001 +From: Nick Clifton +Date: Tue, 9 Nov 2021 13:25:42 +0000 +Subject: [PATCH] Add --unicode option to control how unicode characters are + handled by display tools. + + * nm.c: Add --unicode option to control how unicode characters are + handled. + * objdump.c: Likewise. + * readelf.c: Likewise. + * strings.c: Likewise. + * binutils.texi: Document the new feature. + * NEWS: Document the new feature. + * testsuite/binutils-all/unicode.exp: New file. + * testsuite/binutils-all/nm.hex.unicode + * testsuite/binutils-all/strings.escape.unicode + * testsuite/binutils-all/objdump.highlight.unicode + * testsuite/binutils-all/readelf.invalid.unicode + +Conflict:Context adaptation +--- + binutils/NEWS | 9 + + binutils/doc/binutils.texi | 78 +++++ + binutils/nm.c | 228 +++++++++++++- + binutils/objdump.c | 218 ++++++++++++- + binutils/readelf.c | 190 +++++++++++- + binutils/strings.c | 757 +++++++++++++++++++++++++++++++++++++++++---- + 6 files changed, 1392 insertions(+), 88 deletions(-) + +diff --git a/binutils/NEWS b/binutils/NEWS +index 8a73387..db9114e 100644 +--- a/binutils/NEWS ++++ b/binutils/NEWS +@@ -1,5 +1,14 @@ + -*- text -*- + ++* Tools which display symbols or strings (readelf, strings, nm, objdump) ++ have a new command line option which controls how unicode characters are ++ handled. By default they are treated as normal for the tool. Using ++ --unicode=locale will display them according to the current locale. ++ Using --unicode=hex will display them as hex byte values, whilst ++ --unicode=escape will display them as escape sequences. In addition ++ using --unicode=highlight will display them as unicode escape sequences ++ highlighted in red (if supported by the output device). ++ + Changes in 2.37: + + * The readelf tool has a new command line option which can be used to specify +diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi +index 504c3ea..5de0631 100644 +--- a/binutils/doc/binutils.texi ++++ b/binutils/doc/binutils.texi +@@ -812,6 +812,7 @@ nm [@option{-A}|@option{-o}|@option{--print-file-name}] + [@option{-s}|@option{--print-armap}] + [@option{-t} @var{radix}|@option{--radix=}@var{radix}] + [@option{-u}|@option{--undefined-only}] ++ [@option{-U} @var{method}] [@option{--unicode=}@var{method}] + [@option{-V}|@option{--version}] + [@option{-X 32_64}] + [@option{--defined-only}] +@@ -1132,6 +1133,21 @@ Use @var{radix} as the radix for printing the symbol values. It must be + @cindex undefined symbols + Display only undefined symbols (those external to each object file). + ++@item -U @var{[d|i|l|e|x|h]} ++@itemx --unicode=@var{[default|invalid|locale|escape|hex|highlight]} ++Controls the display of UTF-8 encoded mulibyte characters in strings. ++The default (@option{--unicode=default}) is to give them no special ++treatment. The @option{--unicode=locale} option displays the sequence ++in the current locale, which may or may not support them. The options ++@option{--unicode=hex} and @option{--unicode=invalid} display them as ++hex byte sequences enclosed by either angle brackets or curly braces. ++ ++The @option{--unicode=escape} option displays them as escape sequences ++(@var{\uxxxx}) and the @option{--unicode=highlight} option displays ++them as escape sequences highlighted in red (if supported by the ++output device). The colouring is intended to draw attention to the ++presence of unicode sequences where they might not be expected. ++ + @item -V + @itemx --version + Show the version number of @command{nm} and exit. +@@ -2247,6 +2263,7 @@ objdump [@option{-a}|@option{--archive-headers}] + [@option{--prefix-strip=}@var{level}] + [@option{--insn-width=}@var{width}] + [@option{--visualize-jumps[=color|=extended-color|=off]} ++ [@option{-U} @var{method}] [@option{--unicode=}@var{method}] + [@option{-V}|@option{--version}] + [@option{-H}|@option{--help}] + @var{objfile}@dots{} +@@ -2921,6 +2938,21 @@ When displaying symbols include those which the target considers to be + special in some way and which would not normally be of interest to the + user. + ++@item -U @var{[d|i|l|e|x|h]} ++@itemx --unicode=@var{[default|invalid|locale|escape|hex|highlight]} ++Controls the display of UTF-8 encoded mulibyte characters in strings. ++The default (@option{--unicode=default}) is to give them no special ++treatment. The @option{--unicode=locale} option displays the sequence ++in the current locale, which may or may not support them. The options ++@option{--unicode=hex} and @option{--unicode=invalid} display them as ++hex byte sequences enclosed by either angle brackets or curly braces. ++ ++The @option{--unicode=escape} option displays them as escape sequences ++(@var{\uxxxx}) and the @option{--unicode=highlight} option displays ++them as escape sequences highlighted in red (if supported by the ++output device). The colouring is intended to draw attention to the ++presence of unicode sequences where they might not be expected. ++ + @item -V + @itemx --version + Print the version number of @command{objdump} and exit. +@@ -3197,6 +3229,7 @@ strings [@option{-afovV}] [@option{-}@var{min-len}] + [@option{-n} @var{min-len}] [@option{--bytes=}@var{min-len}] + [@option{-t} @var{radix}] [@option{--radix=}@var{radix}] + [@option{-e} @var{encoding}] [@option{--encoding=}@var{encoding}] ++ [@option{-U} @var{method}] [@option{--unicode=}@var{method}] + [@option{-}] [@option{--all}] [@option{--print-file-name}] + [@option{-T} @var{bfdname}] [@option{--target=}@var{bfdname}] + [@option{-w}] [@option{--include-all-whitespace}] +@@ -3288,6 +3321,28 @@ single-8-bit-byte characters, @samp{b} = 16-bit bigendian, @samp{l} = + littleendian. Useful for finding wide character strings. (@samp{l} + and @samp{b} apply to, for example, Unicode UTF-16/UCS-2 encodings). + ++@item -U @var{[d|i|l|e|x|h]} ++@itemx --unicode=@var{[default|invalid|locale|escape|hex|highlight]} ++Controls the display of UTF-8 encoded mulibyte characters in strings. ++The default (@option{--unicode=default}) is to give them no special ++treatment, and instead rely upon the setting of the ++@option{--encoding} option. The other values for this option ++automatically enable @option{--encoding=S}. ++ ++The @option{--unicode=invalid} option treats them as non-graphic ++characters and hence not part of a valid string. All the remaining ++options treat them as valid string characters. ++ ++The @option{--unicode=locale} option displays them in the current ++locale, which may or may not support UTF-8 encoding. The ++@option{--unicode=hex} option displays them as hex byte sequences ++enclosed between @var{<>} characters. The @option{--unicode=escape} ++option displays them as escape sequences (@var{\uxxxx}) and the ++@option{--unicode=highlight} option displays them as escape sequences ++highlighted in red (if supported by the output device). The colouring ++is intended to draw attention to the presence of unicode sequences ++where they might not be expected. ++ + @item -T @var{bfdname} + @itemx --target=@var{bfdname} + @cindex object code format +@@ -4796,6 +4851,7 @@ readelf [@option{-a}|@option{--all}] + [@option{--demangle@var{=style}}|@option{--no-demangle}] + [@option{--quiet}] + [@option{--recurse-limit}|@option{--no-recurse-limit}] ++ [@option{-U} @var{method}|@option{--unicode=}@var{method}] + [@option{-n}|@option{--notes}] + [@option{-r}|@option{--relocs}] + [@option{-u}|@option{--unwind}] +@@ -4962,6 +5018,28 @@ necessary in order to demangle truly complicated names. Note however + that if the recursion limit is disabled then stack exhaustion is + possible and any bug reports about such an event will be rejected. + ++@item -U @var{[d|i|l|e|x|h]} ++@itemx --unicode=[default|invalid|locale|escape|hex|highlight] ++Controls the display of non-ASCII characters in identifier names. ++The default (@option{--unicode=locale} or @option{--unicode=default}) is ++to treat them as multibyte characters and display them in the current ++locale. All other versions of this option treat the bytes as UTF-8 ++encoded values and attempt to interpret them. If they cannot be ++interpreted or if the @option{--unicode=invalid} option is used then ++they are displayed as a sequence of hex bytes, encloses in curly ++parethesis characters. ++ ++Using the @option{--unicode=escape} option will display the characters ++as as unicode escape sequences (@var{\uxxxx}). Using the ++@option{--unicode=hex} will display the characters as hex byte ++sequences enclosed between angle brackets. ++ ++Using the @option{--unicode=highlight} will display the characters as ++unicode escape sequences but it will also highlighted them in red, ++assuming that colouring is supported by the output device. The ++colouring is intended to draw attention to the presence of unicode ++sequences when they might not be expected. ++ + @item -e + @itemx --headers + Display all the headers in the file. Equivalent to @option{-h -l -S}. +diff --git a/binutils/nm.c b/binutils/nm.c +index 82ccec6..3f8abfc 100644 +--- a/binutils/nm.c ++++ b/binutils/nm.c +@@ -38,6 +38,11 @@ + #include "bucomm.h" + #include "plugin-api.h" + #include "plugin.h" ++#include "safe-ctype.h" ++ ++#ifndef streq ++#define streq(a,b) (strcmp ((a),(b)) == 0) ++#endif + + /* When sorting by size, we use this structure to hold the size and a + pointer to the minisymbol. */ +@@ -216,6 +221,18 @@ static const char *plugin_target = NULL; + static bfd *lineno_cache_bfd; + static bfd *lineno_cache_rel_bfd; + ++typedef enum unicode_display_type ++{ ++ unicode_default = 0, ++ unicode_locale, ++ unicode_escape, ++ unicode_hex, ++ unicode_highlight, ++ unicode_invalid ++} unicode_display_type; ++ ++static unicode_display_type unicode_display = unicode_default; ++ + enum long_option_values + { + OPTION_TARGET = 200, +@@ -260,6 +277,7 @@ static struct option long_options[] = + {"target", required_argument, 0, OPTION_TARGET}, + {"defined-only", no_argument, &defined_only, 1}, + {"undefined-only", no_argument, &undefined_only, 1}, ++ {"unicode", required_argument, NULL, 'U'}, + {"version", no_argument, &show_version, 1}, + {"with-symbol-versions", no_argument, &with_symbol_versions, 1}, + {"without-symbol-versions", no_argument, &with_symbol_versions, 0}, +@@ -313,6 +331,8 @@ usage (FILE *stream, int status) + -t, --radix=RADIX Use RADIX for printing symbol values\n\ + --target=BFDNAME Specify the target object format as BFDNAME\n\ + -u, --undefined-only Display only undefined symbols\n\ ++ -U {d|s|i|x|e|h} Specify how to treat UTF-8 encoded unicode characters\n\ ++ --unicode={default|show|invalid|hex|escape|highlight}\n\ + --with-symbol-versions Display version strings after symbol names\n\ + -X 32_64 (ignored)\n\ + @FILE Read options from FILE\n\ +@@ -432,6 +452,187 @@ get_coff_symbol_type (const struct internal_syment *sym) + return bufp; + } + ++/* Convert a potential UTF-8 encoded sequence in IN into characters in OUT. ++ The conversion format is controlled by the unicode_display variable. ++ Returns the number of characters added to OUT. ++ Returns the number of bytes consumed from IN in CONSUMED. ++ Always consumes at least one byte and displays at least one character. */ ++ ++static unsigned int ++display_utf8 (const unsigned char * in, char * out, unsigned int * consumed) ++{ ++ char * orig_out = out; ++ unsigned int nchars = 0; ++ unsigned int j; ++ ++ if (unicode_display == unicode_default) ++ goto invalid; ++ ++ if (in[0] < 0xc0) ++ goto invalid; ++ ++ if ((in[1] & 0xc0) != 0x80) ++ goto invalid; ++ ++ if ((in[0] & 0x20) == 0) ++ { ++ nchars = 2; ++ goto valid; ++ } ++ ++ if ((in[2] & 0xc0) != 0x80) ++ goto invalid; ++ ++ if ((in[0] & 0x10) == 0) ++ { ++ nchars = 3; ++ goto valid; ++ } ++ ++ if ((in[3] & 0xc0) != 0x80) ++ goto invalid; ++ ++ nchars = 4; ++ ++ valid: ++ switch (unicode_display) ++ { ++ case unicode_locale: ++ /* Copy the bytes into the output buffer as is. */ ++ memcpy (out, in, nchars); ++ out += nchars; ++ break; ++ ++ case unicode_invalid: ++ case unicode_hex: ++ out += sprintf (out, "%c", unicode_display == unicode_hex ? '<' : '{'); ++ out += sprintf (out, "0x"); ++ for (j = 0; j < nchars; j++) ++ out += sprintf (out, "%02x", in [j]); ++ out += sprintf (out, "%c", unicode_display == unicode_hex ? '>' : '}'); ++ break; ++ ++ case unicode_highlight: ++ if (isatty (1)) ++ out += sprintf (out, "\x1B[31;47m"); /* Red. */ ++ /* Fall through. */ ++ case unicode_escape: ++ switch (nchars) ++ { ++ case 2: ++ out += sprintf (out, "\\u%02x%02x", ++ ((in[0] & 0x1c) >> 2), ++ ((in[0] & 0x03) << 6) | (in[1] & 0x3f)); ++ break; ++ ++ case 3: ++ out += sprintf (out, "\\u%02x%02x", ++ ((in[0] & 0x0f) << 4) | ((in[1] & 0x3c) >> 2), ++ ((in[1] & 0x03) << 6) | ((in[2] & 0x3f))); ++ break; ++ ++ case 4: ++ out += sprintf (out, "\\u%02x%02x%02x", ++ ((in[0] & 0x07) << 6) | ((in[1] & 0x3c) >> 2), ++ ((in[1] & 0x03) << 6) | ((in[2] & 0x3c) >> 2), ++ ((in[2] & 0x03) << 6) | ((in[3] & 0x3f))); ++ break; ++ default: ++ /* URG. */ ++ break; ++ } ++ ++ if (unicode_display == unicode_highlight && isatty (1)) ++ out += sprintf (out, "\033[0m"); /* Default colour. */ ++ break; ++ ++ default: ++ /* URG */ ++ break; ++ } ++ ++ * consumed = nchars; ++ return out - orig_out; ++ ++ invalid: ++ /* Not a valid UTF-8 sequence. */ ++ *out = *in; ++ * consumed = 1; ++ return 1; ++} ++ ++/* Convert any UTF-8 encoded characters in NAME into the form specified by ++ unicode_display. Also converts control characters. Returns a static ++ buffer if conversion was necessary. ++ Code stolen from objdump.c:sanitize_string(). */ ++ ++static const char * ++convert_utf8 (const char * in) ++{ ++ static char * buffer = NULL; ++ static size_t buffer_len = 0; ++ const char * original = in; ++ char * out; ++ ++ /* Paranoia. */ ++ if (in == NULL) ++ return ""; ++ ++ /* See if any conversion is necessary. ++ In the majority of cases it will not be needed. */ ++ do ++ { ++ unsigned char c = *in++; ++ ++ if (c == 0) ++ return original; ++ ++ if (ISCNTRL (c)) ++ break; ++ ++ if (unicode_display != unicode_default && c >= 0xc0) ++ break; ++ } ++ while (1); ++ ++ /* Copy the input, translating as needed. */ ++ in = original; ++ if (buffer_len < (strlen (in) * 9)) ++ { ++ free ((void *) buffer); ++ buffer_len = strlen (in) * 9; ++ buffer = xmalloc (buffer_len + 1); ++ } ++ ++ out = buffer; ++ do ++ { ++ unsigned char c = *in++; ++ ++ if (c == 0) ++ break; ++ ++ if (ISCNTRL (c)) ++ { ++ *out++ = '^'; ++ *out++ = c + 0x40; ++ } ++ else if (unicode_display != unicode_default && c >= 0xc0) ++ { ++ unsigned int num_consumed; ++ ++ out += display_utf8 ((const unsigned char *)(in - 1), out, & num_consumed); ++ in += num_consumed - 1; ++ } ++ else ++ *out++ = c; ++ } ++ while (1); ++ ++ *out = 0; ++ return buffer; ++} ++ + /* Print symbol name NAME, read from ABFD, with printf format FORM, + demangling it if requested. */ + +@@ -444,6 +645,7 @@ print_symname (const char *form, struct extended_symbol_info *info, + + if (name == NULL) + name = info->sinfo->name; ++ + if (!with_symbol_versions + && bfd_get_flavour (abfd) == bfd_target_elf_flavour) + { +@@ -451,6 +653,7 @@ print_symname (const char *form, struct extended_symbol_info *info, + if (atver) + *atver = 0; + } ++ + if (do_demangle && *name) + { + alloc = bfd_demangle (abfd, name, demangle_flags); +@@ -458,6 +661,11 @@ print_symname (const char *form, struct extended_symbol_info *info, + name = alloc; + } + ++ if (unicode_display != unicode_default) ++ { ++ name = convert_utf8 (name); ++ } ++ + if (info != NULL && info->elfinfo && with_symbol_versions) + { + const char *version_string; +@@ -1807,7 +2015,7 @@ main (int argc, char **argv) + fatal (_("fatal error: libbfd ABI mismatch")); + set_default_bfd_target (); + +- while ((c = getopt_long (argc, argv, "aABCDef:gHhjJlnopPrSst:uvVvX:", ++ while ((c = getopt_long (argc, argv, "aABCDef:gHhjJlnopPrSst:uU:vVvX:", + long_options, (int *) 0)) != EOF) + { + switch (c) +@@ -1900,6 +2108,24 @@ main (int argc, char **argv) + case 'u': + undefined_only = 1; + break; ++ ++ case 'U': ++ if (streq (optarg, "default") || streq (optarg, "d")) ++ unicode_display = unicode_default; ++ else if (streq (optarg, "locale") || streq (optarg, "l")) ++ unicode_display = unicode_locale; ++ else if (streq (optarg, "escape") || streq (optarg, "e")) ++ unicode_display = unicode_escape; ++ else if (streq (optarg, "invalid") || streq (optarg, "i")) ++ unicode_display = unicode_invalid; ++ else if (streq (optarg, "hex") || streq (optarg, "x")) ++ unicode_display = unicode_hex; ++ else if (streq (optarg, "highlight") || streq (optarg, "h")) ++ unicode_display = unicode_highlight; ++ else ++ fatal (_("invalid argument to -U/--unicode: %s"), optarg); ++ break; ++ + case 'V': + show_version = 1; + break; +diff --git a/binutils/objdump.c b/binutils/objdump.c +index a7b8303..bb5e247 100644 +--- a/binutils/objdump.c ++++ b/binutils/objdump.c +@@ -204,6 +204,18 @@ static const struct objdump_private_desc * const objdump_private_vectors[] = + + /* The list of detected jumps inside a function. */ + static struct jump_info *detected_jumps = NULL; ++ ++typedef enum unicode_display_type ++{ ++ unicode_default = 0, ++ unicode_locale, ++ unicode_escape, ++ unicode_hex, ++ unicode_highlight, ++ unicode_invalid ++} unicode_display_type; ++ ++static unicode_display_type unicode_display = unicode_default; + + static void usage (FILE *, int) ATTRIBUTE_NORETURN; + static void +@@ -330,6 +342,9 @@ usage (FILE *stream, int status) + fprintf (stream, _("\ + -w, --wide Format output for more than 80 columns\n")); + fprintf (stream, _("\ ++ -U[d|l|i|x|e|h] Controls the display of UTF-8 unicode characters\n\ ++ --unicode=[default|locale|invalid|hex|escape|highlight]\n")); ++ fprintf (stream, _("\ + -z, --disassemble-zeroes Do not skip blocks of zeroes when disassembling\n")); + fprintf (stream, _("\ + --start-address=ADDR Only process data whose address is >= ADDR\n")); +@@ -420,17 +435,23 @@ static struct option long_options[]= + { + {"adjust-vma", required_argument, NULL, OPTION_ADJUST_VMA}, + {"all-headers", no_argument, NULL, 'x'}, +- {"private-headers", no_argument, NULL, 'p'}, +- {"private", required_argument, NULL, 'P'}, + {"architecture", required_argument, NULL, 'm'}, + {"archive-headers", no_argument, NULL, 'a'}, ++#ifdef ENABLE_LIBCTF ++ {"ctf", required_argument, NULL, OPTION_CTF}, ++ {"ctf-parent", required_argument, NULL, OPTION_CTF_PARENT}, ++#endif + {"debugging", no_argument, NULL, 'g'}, + {"debugging-tags", no_argument, NULL, 'e'}, + {"demangle", optional_argument, NULL, 'C'}, + {"disassemble", optional_argument, NULL, 'd'}, + {"disassemble-all", no_argument, NULL, 'D'}, +- {"disassembler-options", required_argument, NULL, 'M'}, + {"disassemble-zeroes", no_argument, NULL, 'z'}, ++ {"disassembler-options", required_argument, NULL, 'M'}, ++ {"dwarf", optional_argument, NULL, OPTION_DWARF}, ++ {"dwarf-check", no_argument, 0, OPTION_DWARF_CHECK}, ++ {"dwarf-depth", required_argument, 0, OPTION_DWARF_DEPTH}, ++ {"dwarf-start", required_argument, 0, OPTION_DWARF_START}, + {"dynamic-reloc", no_argument, NULL, 'R'}, + {"dynamic-syms", no_argument, NULL, 'T'}, + {"endian", required_argument, NULL, OPTION_ENDIAN}, +@@ -440,16 +461,23 @@ static struct option long_options[]= + {"full-contents", no_argument, NULL, 's'}, + {"headers", no_argument, NULL, 'h'}, + {"help", no_argument, NULL, 'H'}, ++ {"include", required_argument, NULL, 'I'}, + {"info", no_argument, NULL, 'i'}, ++ {"inlines", no_argument, 0, OPTION_INLINES}, ++ {"insn-width", required_argument, NULL, OPTION_INSN_WIDTH}, + {"line-numbers", no_argument, NULL, 'l'}, +- {"no-show-raw-insn", no_argument, &show_raw_insn, -1}, + {"no-addresses", no_argument, &no_addresses, 1}, +- {"process-links", no_argument, &process_links, true}, ++ {"no-recurse-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT}, ++ {"no-recursion-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT}, ++ {"no-show-raw-insn", no_argument, &show_raw_insn, -1}, ++ {"prefix", required_argument, NULL, OPTION_PREFIX}, + {"prefix-addresses", no_argument, &prefix_addresses, 1}, ++ {"prefix-strip", required_argument, NULL, OPTION_PREFIX_STRIP}, ++ {"private", required_argument, NULL, 'P'}, ++ {"private-headers", no_argument, NULL, 'p'}, ++ {"process-links", no_argument, &process_links, true}, + {"recurse-limit", no_argument, NULL, OPTION_RECURSE_LIMIT}, + {"recursion-limit", no_argument, NULL, OPTION_RECURSE_LIMIT}, +- {"no-recurse-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT}, +- {"no-recursion-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT}, + {"reloc", no_argument, NULL, 'r'}, + {"section", required_argument, NULL, 'j'}, + {"section-headers", no_argument, NULL, 'h'}, +@@ -468,6 +496,7 @@ static struct option long_options[]= + {"stop-address", required_argument, NULL, OPTION_STOP_ADDRESS}, + {"syms", no_argument, NULL, 't'}, + {"target", required_argument, NULL, 'b'}, ++ {"unicode", required_argument, NULL, 'U'}, + {"version", no_argument, NULL, 'V'}, + {"wide", no_argument, NULL, 'w'}, + {"prefix", required_argument, NULL, OPTION_PREFIX}, +@@ -488,9 +517,121 @@ nonfatal (const char *msg) + exit_status = 1; + } + ++/* Convert a potential UTF-8 encoded sequence in IN into characters in OUT. ++ The conversion format is controlled by the unicode_display variable. ++ Returns the number of characters added to OUT. ++ Returns the number of bytes consumed from IN in CONSUMED. ++ Always consumes at least one byte and displays at least one character. */ ++ ++static unsigned int ++display_utf8 (const unsigned char * in, char * out, unsigned int * consumed) ++{ ++ char * orig_out = out; ++ unsigned int nchars = 0; ++ unsigned int j; ++ ++ if (unicode_display == unicode_default) ++ goto invalid; ++ ++ if (in[0] < 0xc0) ++ goto invalid; ++ ++ if ((in[1] & 0xc0) != 0x80) ++ goto invalid; ++ ++ if ((in[0] & 0x20) == 0) ++ { ++ nchars = 2; ++ goto valid; ++ } ++ ++ if ((in[2] & 0xc0) != 0x80) ++ goto invalid; ++ ++ if ((in[0] & 0x10) == 0) ++ { ++ nchars = 3; ++ goto valid; ++ } ++ ++ if ((in[3] & 0xc0) != 0x80) ++ goto invalid; ++ ++ nchars = 4; ++ ++ valid: ++ switch (unicode_display) ++ { ++ case unicode_locale: ++ /* Copy the bytes into the output buffer as is. */ ++ memcpy (out, in, nchars); ++ out += nchars; ++ break; ++ ++ case unicode_invalid: ++ case unicode_hex: ++ out += sprintf (out, "%c", unicode_display == unicode_hex ? '<' : '{'); ++ out += sprintf (out, "0x"); ++ for (j = 0; j < nchars; j++) ++ out += sprintf (out, "%02x", in [j]); ++ out += sprintf (out, "%c", unicode_display == unicode_hex ? '>' : '}'); ++ break; ++ ++ case unicode_highlight: ++ if (isatty (1)) ++ out += sprintf (out, "\x1B[31;47m"); /* Red. */ ++ /* Fall through. */ ++ case unicode_escape: ++ switch (nchars) ++ { ++ case 2: ++ out += sprintf (out, "\\u%02x%02x", ++ ((in[0] & 0x1c) >> 2), ++ ((in[0] & 0x03) << 6) | (in[1] & 0x3f)); ++ break; ++ ++ case 3: ++ out += sprintf (out, "\\u%02x%02x", ++ ((in[0] & 0x0f) << 4) | ((in[1] & 0x3c) >> 2), ++ ((in[1] & 0x03) << 6) | ((in[2] & 0x3f))); ++ break; ++ ++ case 4: ++ out += sprintf (out, "\\u%02x%02x%02x", ++ ((in[0] & 0x07) << 6) | ((in[1] & 0x3c) >> 2), ++ ((in[1] & 0x03) << 6) | ((in[2] & 0x3c) >> 2), ++ ((in[2] & 0x03) << 6) | ((in[3] & 0x3f))); ++ break; ++ default: ++ /* URG. */ ++ break; ++ } ++ ++ if (unicode_display == unicode_highlight && isatty (1)) ++ out += sprintf (out, "\033[0m"); /* Default colour. */ ++ break; ++ ++ default: ++ /* URG */ ++ break; ++ } ++ ++ * consumed = nchars; ++ return out - orig_out; ++ ++ invalid: ++ /* Not a valid UTF-8 sequence. */ ++ *out = *in; ++ * consumed = 1; ++ return 1; ++} ++ + /* Returns a version of IN with any control characters + replaced by escape sequences. Uses a static buffer +- if necessary. */ ++ if necessary. ++ ++ If unicode display is enabled, then also handles the ++ conversion of unicode characters. */ + + static const char * + sanitize_string (const char * in) +@@ -508,40 +649,50 @@ sanitize_string (const char * in) + of cases it will not be needed. */ + do + { +- char c = *in++; ++ unsigned char c = *in++; + + if (c == 0) + return original; + + if (ISCNTRL (c)) + break; ++ ++ if (unicode_display != unicode_default && c >= 0xc0) ++ break; + } + while (1); + + /* Copy the input, translating as needed. */ + in = original; +- if (buffer_len < (strlen (in) * 2)) ++ if (buffer_len < (strlen (in) * 9)) + { + free ((void *) buffer); +- buffer_len = strlen (in) * 2; ++ buffer_len = strlen (in) * 9; + buffer = xmalloc (buffer_len + 1); + } + + out = buffer; + do + { +- char c = *in++; ++ unsigned char c = *in++; + + if (c == 0) + break; + +- if (!ISCNTRL (c)) +- *out++ = c; +- else ++ if (ISCNTRL (c)) + { + *out++ = '^'; + *out++ = c + 0x40; + } ++ else if (unicode_display != unicode_default && c >= 0xc0) ++ { ++ unsigned int num_consumed; ++ ++ out += display_utf8 ((const unsigned char *)(in - 1), out, & num_consumed); ++ in += num_consumed - 1; ++ } ++ else ++ *out++ = c; + } + while (1); + +@@ -4529,6 +4680,24 @@ dump_symbols (bfd *abfd ATTRIBUTE_UNUSED, bool dynamic) + free (alloc); + } + } ++ else if (unicode_display != unicode_default ++ && name != NULL && *name != '\0') ++ { ++ const char * sanitized_name; ++ ++ /* If we want to sanitize the name, we do it here, and ++ temporarily clobber it while calling bfd_print_symbol. ++ FIXME: This is a gross hack. */ ++ sanitized_name = sanitize_string (name); ++ if (sanitized_name != name) ++ (*current)->name = sanitized_name; ++ else ++ sanitized_name = NULL; ++ bfd_print_symbol (cur_bfd, stdout, *current, ++ bfd_print_symbol_all); ++ if (sanitized_name != NULL) ++ (*current)->name = name; ++ } + else + bfd_print_symbol (cur_bfd, stdout, *current, + bfd_print_symbol_all); +@@ -5212,7 +5381,7 @@ main (int argc, char **argv) + set_default_bfd_target (); + + while ((c = getopt_long (argc, argv, +- "pP:ib:m:M:VvCdDlfFaHhrRtTxsSI:j:wE:zgeGW::", ++ "pP:ib:m:M:U:VvCdDlfFaHhrRtTxsSI:j:wE:zgeGW::", + long_options, (int *) 0)) + != EOF) + { +@@ -5495,6 +5664,23 @@ main (int argc, char **argv) + seenflag = true; + break; + ++ case 'U': ++ if (streq (optarg, "default") || streq (optarg, "d")) ++ unicode_display = unicode_default; ++ else if (streq (optarg, "locale") || streq (optarg, "l")) ++ unicode_display = unicode_locale; ++ else if (streq (optarg, "escape") || streq (optarg, "e")) ++ unicode_display = unicode_escape; ++ else if (streq (optarg, "invalid") || streq (optarg, "i")) ++ unicode_display = unicode_invalid; ++ else if (streq (optarg, "hex") || streq (optarg, "x")) ++ unicode_display = unicode_hex; ++ else if (streq (optarg, "highlight") || streq (optarg, "h")) ++ unicode_display = unicode_highlight; ++ else ++ fatal (_("invalid argument to -U/--unicode: %s"), optarg); ++ break; ++ + case 'H': + usage (stdout, 0); + /* No need to set seenflag or to break - usage() does not return. */ +diff --git a/binutils/readelf.c b/binutils/readelf.c +index a6073f7..dd8660c 100644 +--- a/binutils/readelf.c ++++ b/binutils/readelf.c +@@ -328,6 +328,19 @@ typedef enum print_mode + } + print_mode; + ++typedef enum unicode_display_type ++{ ++ unicode_default = 0, ++ unicode_locale, ++ unicode_escape, ++ unicode_hex, ++ unicode_highlight, ++ unicode_invalid ++} unicode_display_type; ++ ++static unicode_display_type unicode_display = unicode_default; ++ ++ + /* Versioned symbol info. */ + enum versioned_symbol_info + { +@@ -632,11 +645,18 @@ print_symbol (signed int width, const char * symbol) + if (c == 0) + break; + +- /* Do not print control characters directly as they can affect terminal +- settings. Such characters usually appear in the names generated +- by the assembler for local labels. */ +- if (ISCNTRL (c)) ++ if (ISPRINT (c)) ++ { ++ putchar (c); ++ width_remaining --; ++ num_printed ++; ++ } ++ else if (ISCNTRL (c)) + { ++ /* Do not print control characters directly as they can affect terminal ++ settings. Such characters usually appear in the names generated ++ by the assembler for local labels. */ ++ + if (width_remaining < 2) + break; + +@@ -644,11 +664,137 @@ print_symbol (signed int width, const char * symbol) + width_remaining -= 2; + num_printed += 2; + } +- else if (ISPRINT (c)) ++ else if (c == 0x7f) + { +- putchar (c); +- width_remaining --; +- num_printed ++; ++ if (width_remaining < 5) ++ break; ++ printf (""); ++ width_remaining -= 5; ++ num_printed += 5; ++ } ++ else if (unicode_display != unicode_locale ++ && unicode_display != unicode_default) ++ { ++ /* Display unicode characters as something else. */ ++ unsigned char bytes[4]; ++ bool is_utf8; ++ uint nbytes; ++ ++ bytes[0] = c; ++ ++ if (bytes[0] < 0xc0) ++ { ++ nbytes = 1; ++ is_utf8 = false; ++ } ++ else ++ { ++ bytes[1] = *symbol++; ++ ++ if ((bytes[1] & 0xc0) != 0x80) ++ { ++ is_utf8 = false; ++ /* Do not consume this character. It may only ++ be the first byte in the sequence that was ++ corrupt. */ ++ --symbol; ++ nbytes = 1; ++ } ++ else if ((bytes[0] & 0x20) == 0) ++ { ++ is_utf8 = true; ++ nbytes = 2; ++ } ++ else ++ { ++ bytes[2] = *symbol++; ++ ++ if ((bytes[2] & 0xc0) != 0x80) ++ { ++ is_utf8 = false; ++ symbol -= 2; ++ nbytes = 1; ++ } ++ else if ((bytes[0] & 0x10) == 0) ++ { ++ is_utf8 = true; ++ nbytes = 3; ++ } ++ else ++ { ++ bytes[3] = *symbol++; ++ ++ nbytes = 4; ++ ++ if ((bytes[3] & 0xc0) != 0x80) ++ { ++ is_utf8 = false; ++ symbol -= 3; ++ nbytes = 1; ++ } ++ else ++ is_utf8 = true; ++ } ++ } ++ } ++ ++ if (unicode_display == unicode_invalid) ++ is_utf8 = false; ++ ++ if (unicode_display == unicode_hex || ! is_utf8) ++ { ++ uint i; ++ ++ if (width_remaining < (nbytes * 2) + 2) ++ break; ++ ++ putchar (is_utf8 ? '<' : '{'); ++ printf ("0x"); ++ for (i = 0; i < nbytes; i++) ++ printf ("%02x", bytes[i]); ++ putchar (is_utf8 ? '>' : '}'); ++ } ++ else ++ { ++ if (unicode_display == unicode_highlight && isatty (1)) ++ printf ("\x1B[31;47m"); /* Red. */ ++ ++ switch (nbytes) ++ { ++ case 2: ++ if (width_remaining < 6) ++ break; ++ printf ("\\u%02x%02x", ++ (bytes[0] & 0x1c) >> 2, ++ ((bytes[0] & 0x03) << 6) | (bytes[1] & 0x3f)); ++ break; ++ case 3: ++ if (width_remaining < 6) ++ break; ++ printf ("\\u%02x%02x", ++ ((bytes[0] & 0x0f) << 4) | ((bytes[1] & 0x3c) >> 2), ++ ((bytes[1] & 0x03) << 6) | (bytes[2] & 0x3f)); ++ break; ++ case 4: ++ if (width_remaining < 8) ++ break; ++ printf ("\\u%02x%02x%02x", ++ ((bytes[0] & 0x07) << 6) | ((bytes[1] & 0x3c) >> 2), ++ ((bytes[1] & 0x03) << 6) | ((bytes[2] & 0x3c) >> 2), ++ ((bytes[2] & 0x03) << 6) | (bytes[3] & 0x3f)); ++ ++ break; ++ default: ++ /* URG. */ ++ break; ++ } ++ ++ if (unicode_display == unicode_highlight && isatty (1)) ++ printf ("\033[0m"); /* Default colour. */ ++ } ++ ++ if (bytes[nbytes - 1] == 0) ++ break; + } + else + { +@@ -4668,6 +4814,7 @@ static struct option options[] = + {"syms", no_argument, 0, 's'}, + {"silent-truncation",no_argument, 0, 'T'}, + {"section-details", no_argument, 0, 't'}, ++ {"unicode", required_argument, NULL, 'U'}, + {"unwind", no_argument, 0, 'u'}, + {"version-info", no_argument, 0, 'V'}, + {"version", no_argument, 0, 'v'}, +@@ -4744,6 +4891,12 @@ usage (FILE * stream) + fprintf (stream, _("\ + --no-recurse-limit Disable a demangling recursion limit\n")); + fprintf (stream, _("\ ++ -U[dlexhi] --unicode=[default|locale|escape|hex|highlight|invalid]\n\ ++ Display unicode characters as determined by the current locale\n\ ++ (default), escape sequences, \"\", highlighted\n\ ++ escape sequences, or treat them as invalid and display as\n\ ++ \"{hex sequences}\"\n")); ++ fprintf (stream, _("\ + -n --notes Display the core notes (if present)\n")); + fprintf (stream, _("\ + -r --relocs Display the relocations (if present)\n")); +@@ -4928,7 +5081,7 @@ parse_args (struct dump_data *dumpdata, int argc, char ** argv) + usage (stderr); + + while ((c = getopt_long +- (argc, argv, "ACDHILNPR:STVWacdeghi:lnp:rstuvw::x:z", options, NULL)) != EOF) ++ (argc, argv, "ACDHILNPR:STU:VWacdeghi:lnp:rstuvw::x:z", options, NULL)) != EOF) + { + switch (c) + { +@@ -5130,6 +5283,25 @@ parse_args (struct dump_data *dumpdata, int argc, char ** argv) + /* Ignored for backward compatibility. */ + break; + ++ case 'U': ++ if (optarg == NULL) ++ error (_("Missing arg to -U/--unicode")); /* Can this happen ? */ ++ else if (streq (optarg, "default") || streq (optarg, "d")) ++ unicode_display = unicode_default; ++ else if (streq (optarg, "locale") || streq (optarg, "l")) ++ unicode_display = unicode_locale; ++ else if (streq (optarg, "escape") || streq (optarg, "e")) ++ unicode_display = unicode_escape; ++ else if (streq (optarg, "invalid") || streq (optarg, "i")) ++ unicode_display = unicode_invalid; ++ else if (streq (optarg, "hex") || streq (optarg, "x")) ++ unicode_display = unicode_hex; ++ else if (streq (optarg, "highlight") || streq (optarg, "h")) ++ unicode_display = unicode_highlight; ++ else ++ error (_("invalid argument to -U/--unicode: %s"), optarg); ++ break; ++ + case OPTION_SYM_BASE: + sym_base = 0; + if (optarg != NULL) +diff --git a/binutils/strings.c b/binutils/strings.c +index 44a8e1d..f50badf 100644 +--- a/binutils/strings.c ++++ b/binutils/strings.c +@@ -55,6 +55,19 @@ + -T {bfdname} + Specify a non-default object file format. + ++ --unicode={default|locale|invalid|hex|escape|highlight} ++ -u {d|l|i|x|e|h} ++ Determine how to handle UTF-8 unicode characters. The default ++ is no special treatment. All other versions of this option ++ only apply if the encoding is valid and enabling the option ++ implies --encoding=S. ++ The 'locale' option displays the characters according to the ++ current locale. The 'invalid' option treats them as ++ non-string characters. The 'hex' option displays them as hex ++ byte sequences. The 'escape' option displays them as escape ++ sequences and the 'highlight' option displays them as ++ coloured escape sequences. ++ + --output-separator=sep_string + -s sep_string String used to separate parsed strings in output. + Default is newline. +@@ -76,6 +89,22 @@ + #include "safe-ctype.h" + #include "bucomm.h" + ++#ifndef streq ++#define streq(a,b) (strcmp ((a),(b)) == 0) ++#endif ++ ++typedef enum unicode_display_type ++{ ++ unicode_default = 0, ++ unicode_locale, ++ unicode_escape, ++ unicode_hex, ++ unicode_highlight, ++ unicode_invalid ++} unicode_display_type; ++ ++static unicode_display_type unicode_display = unicode_default; ++ + #define STRING_ISGRAPHIC(c) \ + ( (c) >= 0 \ + && (c) <= 255 \ +@@ -94,7 +123,7 @@ extern int errno; + static int address_radix; + + /* Minimum length of sequence of graphic chars to trigger output. */ +-static int string_min; ++static uint string_min; + + /* Whether or not we include all whitespace as a graphic char. */ + static bool include_all_whitespace; +@@ -121,21 +150,22 @@ static char *output_separator; + static struct option long_options[] = + { + {"all", no_argument, NULL, 'a'}, ++ {"bytes", required_argument, NULL, 'n'}, + {"data", no_argument, NULL, 'd'}, ++ {"encoding", required_argument, NULL, 'e'}, ++ {"help", no_argument, NULL, 'h'}, ++ {"include-all-whitespace", no_argument, NULL, 'w'}, ++ {"output-separator", required_argument, NULL, 's'}, + {"print-file-name", no_argument, NULL, 'f'}, +- {"bytes", required_argument, NULL, 'n'}, + {"radix", required_argument, NULL, 't'}, +- {"include-all-whitespace", no_argument, NULL, 'w'}, +- {"encoding", required_argument, NULL, 'e'}, + {"target", required_argument, NULL, 'T'}, +- {"output-separator", required_argument, NULL, 's'}, +- {"help", no_argument, NULL, 'h'}, ++ {"unicode", required_argument, NULL, 'U'}, + {"version", no_argument, NULL, 'v'}, + {NULL, 0, NULL, 0} + }; + + static bool strings_file (char *); +-static void print_strings (const char *, FILE *, file_ptr, int, int, char *); ++static void print_strings (const char *, FILE *, file_ptr, int, char *); + static void usage (FILE *, int) ATTRIBUTE_NORETURN; + + int main (int, char **); +@@ -171,7 +201,7 @@ main (int argc, char **argv) + encoding = 's'; + output_separator = NULL; + +- while ((optc = getopt_long (argc, argv, "adfhHn:wot:e:T:s:Vv0123456789", ++ while ((optc = getopt_long (argc, argv, "adfhHn:wot:e:T:s:U:Vv0123456789", + long_options, (int *) 0)) != EOF) + { + switch (optc) +@@ -244,6 +274,23 @@ main (int argc, char **argv) + output_separator = optarg; + break; + ++ case 'U': ++ if (streq (optarg, "default") || streq (optarg, "d")) ++ unicode_display = unicode_default; ++ else if (streq (optarg, "locale") || streq (optarg, "l")) ++ unicode_display = unicode_locale; ++ else if (streq (optarg, "escape") || streq (optarg, "e")) ++ unicode_display = unicode_escape; ++ else if (streq (optarg, "invalid") || streq (optarg, "i")) ++ unicode_display = unicode_invalid; ++ else if (streq (optarg, "hex") || streq (optarg, "x")) ++ unicode_display = unicode_hex; ++ else if (streq (optarg, "highlight") || streq (optarg, "h")) ++ unicode_display = unicode_highlight; ++ else ++ fatal (_("invalid argument to -U/--unicode: %s"), optarg); ++ break; ++ + case 'V': + case 'v': + print_version ("strings"); +@@ -258,6 +305,9 @@ main (int argc, char **argv) + } + } + ++ if (unicode_display != unicode_default) ++ encoding = 'S'; ++ + if (numeric_opt != 0) + { + string_min = (int) strtoul (argv[numeric_opt - 1] + 1, &s, 0); +@@ -293,14 +343,14 @@ main (int argc, char **argv) + { + datasection_only = false; + SET_BINARY (fileno (stdin)); +- print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL); ++ print_strings ("{standard input}", stdin, 0, 0, (char *) NULL); + files_given = true; + } + else + { + for (; optind < argc; ++optind) + { +- if (strcmp (argv[optind], "-") == 0) ++ if (streq (argv[optind], "-")) + datasection_only = false; + else + { +@@ -342,7 +392,7 @@ strings_a_section (bfd *abfd, asection *sect, const char *filename, + } + + *got_a_section = true; +- print_strings (filename, NULL, sect->filepos, 0, sectsize, (char *) mem); ++ print_strings (filename, NULL, sect->filepos, sectsize, (char *) mem); + free (mem); + } + +@@ -427,7 +477,7 @@ strings_file (char *file) + return false; + } + +- print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0); ++ print_strings (file, stream, (file_ptr) 0, 0, (char *) NULL); + + if (fclose (stream) == EOF) + { +@@ -551,11 +601,627 @@ unget_part_char (long c, file_ptr *address, int *magiccount, char **magic) + } + } + } ++ ++static void ++print_filename_and_address (const char * filename, file_ptr address) ++{ ++ if (print_filenames) ++ printf ("%s: ", filename); ++ ++ if (! print_addresses) ++ return; ++ ++ switch (address_radix) ++ { ++ case 8: ++ if (sizeof (address) > sizeof (long)) ++ { ++#ifndef __MSVCRT__ ++ printf ("%7llo ", (unsigned long long) address); ++#else ++ printf ("%7I64o ", (unsigned long long) address); ++#endif ++ } ++ else ++ printf ("%7lo ", (unsigned long) address); ++ break; ++ ++ case 10: ++ if (sizeof (address) > sizeof (long)) ++ { ++#ifndef __MSVCRT__ ++ printf ("%7llu ", (unsigned long long) address); ++#else ++ printf ("%7I64d ", (unsigned long long) address); ++#endif ++ } ++ else ++ printf ("%7ld ", (long) address); ++ break; ++ ++ case 16: ++ if (sizeof (address) > sizeof (long)) ++ { ++#ifndef __MSVCRT__ ++ printf ("%7llx ", (unsigned long long) address); ++#else ++ printf ("%7I64x ", (unsigned long long) address); ++#endif ++ } ++ else ++ printf ("%7lx ", (unsigned long) address); ++ break; ++ } ++} ++ ++/* Return non-zero if the bytes starting at BUFFER form a valid UTF-8 encoding. ++ If the encoding is valid then returns the number of bytes it uses. */ ++ ++static unsigned int ++is_valid_utf8 (const unsigned char * buffer, unsigned long buflen) ++{ ++ if (buffer[0] < 0xc0) ++ return 0; ++ ++ if (buflen < 2) ++ return 0; ++ ++ if ((buffer[1] & 0xc0) != 0x80) ++ return 0; ++ ++ if ((buffer[0] & 0x20) == 0) ++ return 2; ++ ++ if (buflen < 3) ++ return 0; ++ ++ if ((buffer[2] & 0xc0) != 0x80) ++ return 0; ++ ++ if ((buffer[0] & 0x10) == 0) ++ return 3; ++ ++ if (buflen < 4) ++ return 0; ++ ++ if ((buffer[3] & 0xc0) != 0x80) ++ return 0; ++ ++ return 4; ++} ++ ++/* Display a UTF-8 encoded character in BUFFER according to the setting ++ of unicode_display. The character is known to be valid. ++ Returns the number of bytes consumed. */ ++ ++static uint ++display_utf8_char (const unsigned char * buffer) ++{ ++ uint j; ++ uint utf8_len; ++ ++ switch (buffer[0] & 0x30) ++ { ++ case 0x00: ++ case 0x10: ++ utf8_len = 2; ++ break; ++ case 0x20: ++ utf8_len = 3; ++ break; ++ default: ++ utf8_len = 4; ++ } ++ ++ switch (unicode_display) ++ { ++ default: ++ fprintf (stderr, "ICE: unexpected unicode display type\n"); ++ break; ++ ++ case unicode_escape: ++ case unicode_highlight: ++ if (unicode_display == unicode_highlight && isatty (1)) ++ printf ("\x1B[31;47m"); /* Red. */ ++ ++ switch (utf8_len) ++ { ++ case 2: ++ printf ("\\u%02x%02x", ++ ((buffer[0] & 0x1c) >> 2), ++ ((buffer[0] & 0x03) << 6) | (buffer[1] & 0x3f)); ++ break; ++ ++ case 3: ++ printf ("\\u%02x%02x", ++ ((buffer[0] & 0x0f) << 4) | ((buffer[1] & 0x3c) >> 2), ++ ((buffer[1] & 0x03) << 6) | ((buffer[2] & 0x3f))); ++ break; ++ ++ case 4: ++ printf ("\\u%02x%02x%02x", ++ ((buffer[0] & 0x07) << 6) | ((buffer[1] & 0x3c) >> 2), ++ ((buffer[1] & 0x03) << 6) | ((buffer[2] & 0x3c) >> 2), ++ ((buffer[2] & 0x03) << 6) | ((buffer[3] & 0x3f))); ++ break; ++ default: ++ /* URG. */ ++ break; ++ } ++ ++ if (unicode_display == unicode_highlight && isatty (1)) ++ printf ("\033[0m"); /* Default colour. */ ++ break; ++ ++ case unicode_hex: ++ putchar ('<'); ++ printf ("0x"); ++ for (j = 0; j < utf8_len; j++) ++ printf ("%02x", buffer [j]); ++ putchar ('>'); ++ break; ++ ++ case unicode_locale: ++ printf ("%.1s", buffer); ++ break; ++ } ++ ++ return utf8_len; ++} ++ ++/* Display strings in BUFFER. Treat any UTF-8 encoded characters encountered ++ according to the setting of the unicode_display variable. The buffer ++ contains BUFLEN bytes. ++ ++ Display the characters as if they started at ADDRESS and are contained in ++ FILENAME. */ ++ ++static void ++print_unicode_buffer (const char * filename, ++ file_ptr address, ++ const unsigned char * buffer, ++ unsigned long buflen) ++{ ++ /* Paranoia checks... */ ++ if (filename == NULL ++ || buffer == NULL ++ || unicode_display == unicode_default ++ || encoding != 'S' ++ || encoding_bytes != 1) ++ { ++ fprintf (stderr, "ICE: bad arguments to print_unicode_buffer\n"); ++ return; ++ } ++ ++ if (buflen == 0) ++ return; ++ ++ /* We must only display strings that are at least string_min *characters* ++ long. So we scan the buffer in two stages. First we locate the start ++ of a potential string. Then we walk along it until we have found ++ string_min characters. Then we go back to the start point and start ++ displaying characters according to the unicode_display setting. */ ++ ++ unsigned long start_point = 0; ++ unsigned long i = 0; ++ unsigned int char_len = 1; ++ unsigned int num_found = 0; ++ ++ for (i = 0; i < buflen; i += char_len) ++ { ++ int c = buffer[i]; ++ ++ char_len = 1; ++ ++ /* Find the first potential character of a string. */ ++ if (! STRING_ISGRAPHIC (c)) ++ { ++ num_found = 0; ++ continue; ++ } ++ ++ if (c > 126) ++ { ++ if (c < 0xc0) ++ { ++ num_found = 0; ++ continue; ++ } ++ ++ if ((char_len = is_valid_utf8 (buffer + i, buflen - i)) == 0) ++ { ++ char_len = 1; ++ num_found = 0; ++ continue; ++ } ++ ++ if (unicode_display == unicode_invalid) ++ { ++ /* We have found a valid UTF-8 character, but we treat it as non-graphic. */ ++ num_found = 0; ++ continue; ++ } ++ } ++ ++ if (num_found == 0) ++ /* We have found a potential starting point for a string. */ ++ start_point = i; ++ ++ ++ num_found; ++ ++ if (num_found >= string_min) ++ break; ++ } ++ ++ if (num_found < string_min) ++ return; ++ ++ print_filename_and_address (filename, address + start_point); ++ ++ /* We have found string_min characters. Display them and any ++ more that follow. */ ++ for (i = start_point; i < buflen; i += char_len) ++ { ++ int c = buffer[i]; ++ ++ char_len = 1; ++ ++ if (! STRING_ISGRAPHIC (c)) ++ break; ++ else if (c < 127) ++ putchar (c); ++ else if (! is_valid_utf8 (buffer + i, buflen - i)) ++ break; ++ else if (unicode_display == unicode_invalid) ++ break; ++ else ++ char_len = display_utf8_char (buffer + i); ++ } ++ ++ if (output_separator) ++ fputs (output_separator, stdout); ++ else ++ putchar ('\n'); ++ ++ /* FIXME: Using tail recursion here is lazy programming... */ ++ print_unicode_buffer (filename, address + i, buffer + i, buflen - i); ++} ++ ++static int ++get_unicode_byte (FILE * stream, unsigned char * putback, uint * num_putback, uint * num_read) ++{ ++ if (* num_putback > 0) ++ { ++ * num_putback = * num_putback - 1; ++ return putback [* num_putback]; ++ } ++ ++ * num_read = * num_read + 1; ++ ++#if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED ++ return getc_unlocked (stream); ++#else ++ return getc (stream); ++#endif ++} ++ ++/* Helper function for print_unicode_stream. */ ++ ++static void ++print_unicode_stream_body (const char * filename, ++ file_ptr address, ++ FILE * stream, ++ unsigned char * putback_buf, ++ uint num_putback, ++ unsigned char * print_buf) ++{ ++ /* It would be nice if we could just read the stream into a buffer ++ and then process if with print_unicode_buffer. But the input ++ might be huge or it might time-locked (eg stdin). So instead ++ we go one byte at a time... */ ++ ++ file_ptr start_point = 0; ++ uint num_read = 0; ++ uint num_chars = 0; ++ uint num_print = 0; ++ int c = 0; ++ ++ /* Find a series of string_min characters. Put them into print_buf. */ ++ do ++ { ++ if (num_chars >= string_min) ++ break; ++ ++ c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read); ++ if (c == EOF) ++ break; ++ ++ if (! STRING_ISGRAPHIC (c)) ++ { ++ num_chars = num_print = 0; ++ continue; ++ } ++ ++ if (num_chars == 0) ++ start_point = num_read - 1; ++ ++ if (c < 127) ++ { ++ print_buf[num_print] = c; ++ num_chars ++; ++ num_print ++; ++ continue; ++ } ++ ++ if (c < 0xc0) ++ { ++ num_chars = num_print = 0; ++ continue; ++ } ++ ++ /* We *might* have a UTF-8 sequence. Time to start peeking. */ ++ char utf8[4]; ++ ++ utf8[0] = c; ++ c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read); ++ if (c == EOF) ++ break; ++ utf8[1] = c; ++ ++ if ((utf8[1] & 0xc0) != 0x80) ++ { ++ /* Invalid UTF-8. */ ++ putback_buf[num_putback++] = utf8[1]; ++ num_chars = num_print = 0; ++ continue; ++ } ++ else if ((utf8[0] & 0x20) == 0) ++ { ++ /* A valid 2-byte UTF-8 encoding. */ ++ if (unicode_display == unicode_invalid) ++ { ++ putback_buf[num_putback++] = utf8[1]; ++ num_chars = num_print = 0; ++ } ++ else ++ { ++ print_buf[num_print ++] = utf8[0]; ++ print_buf[num_print ++] = utf8[1]; ++ num_chars ++; ++ } ++ continue; ++ } ++ ++ c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read); ++ if (c == EOF) ++ break; ++ utf8[2] = c; ++ ++ if ((utf8[2] & 0xc0) != 0x80) ++ { ++ /* Invalid UTF-8. */ ++ putback_buf[num_putback++] = utf8[2]; ++ putback_buf[num_putback++] = utf8[1]; ++ num_chars = num_print = 0; ++ continue; ++ } ++ else if ((utf8[0] & 0x10) == 0) ++ { ++ /* A valid 3-byte UTF-8 encoding. */ ++ if (unicode_display == unicode_invalid) ++ { ++ putback_buf[num_putback++] = utf8[2]; ++ putback_buf[num_putback++] = utf8[1]; ++ num_chars = num_print = 0; ++ } ++ else ++ { ++ print_buf[num_print ++] = utf8[0]; ++ print_buf[num_print ++] = utf8[1]; ++ print_buf[num_print ++] = utf8[2]; ++ num_chars ++; ++ } ++ continue; ++ } ++ ++ c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read); ++ if (c == EOF) ++ break; ++ utf8[3] = c; ++ ++ if ((utf8[3] & 0xc0) != 0x80) ++ { ++ /* Invalid UTF-8. */ ++ putback_buf[num_putback++] = utf8[3]; ++ putback_buf[num_putback++] = utf8[2]; ++ putback_buf[num_putback++] = utf8[1]; ++ num_chars = num_print = 0; ++ } ++ /* We have a valid 4-byte UTF-8 encoding. */ ++ else if (unicode_display == unicode_invalid) ++ { ++ putback_buf[num_putback++] = utf8[3]; ++ putback_buf[num_putback++] = utf8[1]; ++ putback_buf[num_putback++] = utf8[2]; ++ num_chars = num_print = 0; ++ } ++ else ++ { ++ print_buf[num_print ++] = utf8[0]; ++ print_buf[num_print ++] = utf8[1]; ++ print_buf[num_print ++] = utf8[2]; ++ print_buf[num_print ++] = utf8[3]; ++ num_chars ++; ++ } ++ } ++ while (1); ++ ++ if (num_chars >= string_min) ++ { ++ /* We know that we have string_min valid characters in print_buf, ++ and there may be more to come in the stream. Start displaying ++ them. */ ++ ++ print_filename_and_address (filename, address + start_point); ++ ++ uint i; ++ for (i = 0; i < num_print;) ++ { ++ if (print_buf[i] < 127) ++ putchar (print_buf[i++]); ++ else ++ i += display_utf8_char (print_buf + i); ++ } ++ ++ /* OK so now we have to start read unchecked bytes. */ ++ ++ /* Find a series of string_min characters. Put them into print_buf. */ ++ do ++ { ++ c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read); ++ if (c == EOF) ++ break; ++ ++ if (! STRING_ISGRAPHIC (c)) ++ break; ++ ++ if (c < 127) ++ { ++ putchar (c); ++ continue; ++ } ++ ++ if (c < 0xc0) ++ break; ++ ++ /* We *might* have a UTF-8 sequence. Time to start peeking. */ ++ unsigned char utf8[4]; ++ ++ utf8[0] = c; ++ c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read); ++ if (c == EOF) ++ break; ++ utf8[1] = c; ++ ++ if ((utf8[1] & 0xc0) != 0x80) ++ { ++ /* Invalid UTF-8. */ ++ putback_buf[num_putback++] = utf8[1]; ++ break; ++ } ++ else if ((utf8[0] & 0x20) == 0) ++ { ++ /* Valid 2-byte UTF-8. */ ++ if (unicode_display == unicode_invalid) ++ { ++ putback_buf[num_putback++] = utf8[1]; ++ break; ++ } ++ else ++ { ++ (void) display_utf8_char (utf8); ++ continue; ++ } ++ } ++ ++ c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read); ++ if (c == EOF) ++ break; ++ utf8[2] = c; ++ ++ if ((utf8[2] & 0xc0) != 0x80) ++ { ++ /* Invalid UTF-8. */ ++ putback_buf[num_putback++] = utf8[2]; ++ putback_buf[num_putback++] = utf8[1]; ++ break; ++ } ++ else if ((utf8[0] & 0x10) == 0) ++ { ++ /* Valid 3-byte UTF-8. */ ++ if (unicode_display == unicode_invalid) ++ { ++ putback_buf[num_putback++] = utf8[2]; ++ putback_buf[num_putback++] = utf8[1]; ++ break; ++ } ++ else ++ { ++ (void) display_utf8_char (utf8); ++ continue; ++ } ++ } ++ ++ c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read); ++ if (c == EOF) ++ break; ++ utf8[3] = c; ++ ++ if ((utf8[3] & 0xc0) != 0x80) ++ { ++ /* Invalid UTF-8. */ ++ putback_buf[num_putback++] = utf8[3]; ++ putback_buf[num_putback++] = utf8[2]; ++ putback_buf[num_putback++] = utf8[1]; ++ break; ++ } ++ else if (unicode_display == unicode_invalid) ++ { ++ putback_buf[num_putback++] = utf8[3]; ++ putback_buf[num_putback++] = utf8[2]; ++ putback_buf[num_putback++] = utf8[1]; ++ break; ++ } ++ else ++ /* A valid 4-byte UTF-8 encoding. */ ++ (void) display_utf8_char (utf8); ++ } ++ while (1); ++ ++ if (output_separator) ++ fputs (output_separator, stdout); ++ else ++ putchar ('\n'); ++ } ++ ++ if (c != EOF) ++ /* FIXME: Using tail recursion here is lazy, but it works. */ ++ print_unicode_stream_body (filename, address + num_read, stream, putback_buf, num_putback, print_buf); ++} ++ ++/* Display strings read in from STREAM. Treat any UTF-8 encoded characters ++ encountered according to the setting of the unicode_display variable. ++ The stream is positioned at ADDRESS and is attached to FILENAME. */ ++ ++static void ++print_unicode_stream (const char * filename, ++ file_ptr address, ++ FILE * stream) ++{ ++ /* Paranoia checks... */ ++ if (filename == NULL ++ || stream == NULL ++ || unicode_display == unicode_default ++ || encoding != 'S' ++ || encoding_bytes != 1) ++ { ++ fprintf (stderr, "ICE: bad arguments to print_unicode_stream\n"); ++ return; ++ } ++ ++ /* Allocate space for string_min 4-byte utf-8 characters. */ ++ unsigned char * print_buf = xmalloc ((4 * string_min) + 1); ++ /* We should never have to put back more than 4 bytes. */ ++ unsigned char putback_buf[5]; ++ uint num_putback = 0; ++ ++ print_unicode_stream_body (filename, address, stream, putback_buf, num_putback, print_buf); ++ free (print_buf); ++} + + /* Find the strings in file FILENAME, read from STREAM. + Assume that STREAM is positioned so that the next byte read + is at address ADDRESS in the file. +- Stop reading at address STOP_POINT in the file, if nonzero. + + If STREAM is NULL, do not read from it. + The caller can supply a buffer of characters +@@ -566,20 +1232,29 @@ unget_part_char (long c, file_ptr *address, int *magiccount, char **magic) + + static void + print_strings (const char *filename, FILE *stream, file_ptr address, +- int stop_point, int magiccount, char *magic) ++ int magiccount, char *magic) + { ++ if (unicode_display != unicode_default) ++ { ++ if (magic != NULL) ++ print_unicode_buffer (filename, address, ++ (const unsigned char *) magic, magiccount); ++ ++ if (stream != NULL) ++ print_unicode_stream (filename, address, stream); ++ return; ++ } ++ + char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1)); + + while (1) + { + file_ptr start; +- int i; ++ uint i; + long c; + + /* See if the next `string_min' chars are all graphic chars. */ + tryline: +- if (stop_point && address >= stop_point) +- break; + start = address; + for (i = 0; i < string_min; i++) + { +@@ -601,51 +1276,7 @@ print_strings (const char *filename, FILE *stream, file_ptr address, + + /* We found a run of `string_min' graphic characters. Print up + to the next non-graphic character. */ +- +- if (print_filenames) +- printf ("%s: ", filename); +- if (print_addresses) +- switch (address_radix) +- { +- case 8: +- if (sizeof (start) > sizeof (long)) +- { +-#ifndef __MSVCRT__ +- printf ("%7llo ", (unsigned long long) start); +-#else +- printf ("%7I64o ", (unsigned long long) start); +-#endif +- } +- else +- printf ("%7lo ", (unsigned long) start); +- break; +- +- case 10: +- if (sizeof (start) > sizeof (long)) +- { +-#ifndef __MSVCRT__ +- printf ("%7llu ", (unsigned long long) start); +-#else +- printf ("%7I64d ", (unsigned long long) start); +-#endif +- } +- else +- printf ("%7ld ", (long) start); +- break; +- +- case 16: +- if (sizeof (start) > sizeof (long)) +- { +-#ifndef __MSVCRT__ +- printf ("%7llx ", (unsigned long long) start); +-#else +- printf ("%7I64x ", (unsigned long long) start); +-#endif +- } +- else +- printf ("%7lx ", (unsigned long) start); +- break; +- } ++ print_filename_and_address (filename, start); + + buf[i] = '\0'; + fputs (buf, stdout); +@@ -697,6 +1328,8 @@ usage (FILE *stream, int status) + -T --target= Specify the binary file format\n\ + -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\ + s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\ ++ --unicode={default|show|invalid|hex|escape|highlight}\n\ ++ -u {d|s|i|x|e|h} Specify how to treat UTF-8 encoded unicode characters\n\ + -s --output-separator= String used to separate strings in output.\n\ + @ Read options from \n\ + -h --help Display this information\n\ +-- +1.8.3.1 + diff --git a/backport-0002-CVE-2021-42574.patch b/backport-0002-CVE-2021-42574.patch new file mode 100644 index 0000000000000000000000000000000000000000..8ef5dd642e1ca5aa86a0523ea03fde5b843d12c4 --- /dev/null +++ b/backport-0002-CVE-2021-42574.patch @@ -0,0 +1,199 @@ +From 795588aec4f894206863c938bd6d716895886009 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pekka=20Sepp=C3=A4nen?= +Date: Wed, 10 Nov 2021 20:15:19 +1030 +Subject: [PATCH] PR28575, readelf.c and strings.c use undefined type uint + +Since --unicode support (commit b3aa80b45c4) both binutils/readelf.c +and binutils/strings.c use 'uint' in a few locations. It likely +should be 'unsigned int' since there isn't anything defining 'uint' +within binutils (besides zlib) and AFAIK it isn't a standard type. + + * readelf.c (print_symbol): Replace uint with unsigned int. + * strings.c (string_min, display_utf8_char): Likewise. + (print_unicode_stream_body, print_unicode_stream): Likewise. + (print_strings): Likewise. + (get_unicode_byte): Wrap long line. + +Conflict:Context adaptation +--- + binutils/readelf.c | 4 ++-- + binutils/strings.c | 41 ++++++++++++++++++++++------------------- + 2 files changed, 24 insertions(+), 21 deletions(-) + +diff --git a/binutils/readelf.c b/binutils/readelf.c +index dd8660c..cc9023a 100644 +--- a/binutils/readelf.c ++++ b/binutils/readelf.c +@@ -678,7 +678,7 @@ print_symbol (signed int width, const char * symbol) + /* Display unicode characters as something else. */ + unsigned char bytes[4]; + bool is_utf8; +- uint nbytes; ++ unsigned int nbytes; + + bytes[0] = c; + +@@ -743,7 +743,7 @@ print_symbol (signed int width, const char * symbol) + + if (unicode_display == unicode_hex || ! is_utf8) + { +- uint i; ++ unsigned int i; + + if (width_remaining < (nbytes * 2) + 2) + break; +diff --git a/binutils/strings.c b/binutils/strings.c +index f50badf..e7dd534 100644 +--- a/binutils/strings.c ++++ b/binutils/strings.c +@@ -57,7 +57,7 @@ + + --unicode={default|locale|invalid|hex|escape|highlight} + -u {d|l|i|x|e|h} +- Determine how to handle UTF-8 unicode characters. The default ++ Determine how to handle UTF-8 unicode characters. The default + is no special treatment. All other versions of this option + only apply if the encoding is valid and enabling the option + implies --encoding=S. +@@ -123,7 +123,7 @@ extern int errno; + static int address_radix; + + /* Minimum length of sequence of graphic chars to trigger output. */ +-static uint string_min; ++static unsigned int string_min; + + /* Whether or not we include all whitespace as a graphic char. */ + static bool include_all_whitespace; +@@ -272,7 +272,7 @@ main (int argc, char **argv) + + case 's': + output_separator = optarg; +- break; ++ break; + + case 'U': + if (streq (optarg, "default") || streq (optarg, "d")) +@@ -677,7 +677,7 @@ is_valid_utf8 (const unsigned char * buffer, unsigned long buflen) + + if ((buffer[2] & 0xc0) != 0x80) + return 0; +- ++ + if ((buffer[0] & 0x10) == 0) + return 3; + +@@ -694,11 +694,11 @@ is_valid_utf8 (const unsigned char * buffer, unsigned long buflen) + of unicode_display. The character is known to be valid. + Returns the number of bytes consumed. */ + +-static uint ++static unsigned int + display_utf8_char (const unsigned char * buffer) + { +- uint j; +- uint utf8_len; ++ unsigned int j; ++ unsigned int utf8_len; + + switch (buffer[0] & 0x30) + { +@@ -712,7 +712,7 @@ display_utf8_char (const unsigned char * buffer) + default: + utf8_len = 4; + } +- ++ + switch (unicode_display) + { + default: +@@ -728,7 +728,7 @@ display_utf8_char (const unsigned char * buffer) + { + case 2: + printf ("\\u%02x%02x", +- ((buffer[0] & 0x1c) >> 2), ++ ((buffer[0] & 0x1c) >> 2), + ((buffer[0] & 0x03) << 6) | (buffer[1] & 0x3f)); + break; + +@@ -857,7 +857,7 @@ print_unicode_buffer (const char * filename, + return; + + print_filename_and_address (filename, address + start_point); +- ++ + /* We have found string_min characters. Display them and any + more that follow. */ + for (i = start_point; i < buflen; i += char_len) +@@ -888,7 +888,10 @@ print_unicode_buffer (const char * filename, + } + + static int +-get_unicode_byte (FILE * stream, unsigned char * putback, uint * num_putback, uint * num_read) ++get_unicode_byte (FILE * stream, ++ unsigned char * putback, ++ unsigned int * num_putback, ++ unsigned int * num_read) + { + if (* num_putback > 0) + { +@@ -912,7 +915,7 @@ print_unicode_stream_body (const char * filename, + file_ptr address, + FILE * stream, + unsigned char * putback_buf, +- uint num_putback, ++ unsigned int num_putback, + unsigned char * print_buf) + { + /* It would be nice if we could just read the stream into a buffer +@@ -921,9 +924,9 @@ print_unicode_stream_body (const char * filename, + we go one byte at a time... */ + + file_ptr start_point = 0; +- uint num_read = 0; +- uint num_chars = 0; +- uint num_print = 0; ++ unsigned int num_read = 0; ++ unsigned int num_chars = 0; ++ unsigned int num_print = 0; + int c = 0; + + /* Find a series of string_min characters. Put them into print_buf. */ +@@ -1064,7 +1067,7 @@ print_unicode_stream_body (const char * filename, + + print_filename_and_address (filename, address + start_point); + +- uint i; ++ unsigned int i; + for (i = 0; i < num_print;) + { + if (print_buf[i] < 127) +@@ -1075,7 +1078,7 @@ print_unicode_stream_body (const char * filename, + + /* OK so now we have to start read unchecked bytes. */ + +- /* Find a series of string_min characters. Put them into print_buf. */ ++ /* Find a series of string_min characters. Put them into print_buf. */ + do + { + c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read); +@@ -1213,7 +1216,7 @@ print_unicode_stream (const char * filename, + unsigned char * print_buf = xmalloc ((4 * string_min) + 1); + /* We should never have to put back more than 4 bytes. */ + unsigned char putback_buf[5]; +- uint num_putback = 0; ++ unsigned int num_putback = 0; + + print_unicode_stream_body (filename, address, stream, putback_buf, num_putback, print_buf); + free (print_buf); +@@ -1250,7 +1253,7 @@ print_strings (const char *filename, FILE *stream, file_ptr address, + while (1) + { + file_ptr start; +- uint i; ++ unsigned int i; + long c; + + /* See if the next `string_min' chars are all graphic chars. */ +-- +1.8.3.1 + diff --git a/backport-0003-CVE-2021-20197.patch b/backport-0003-CVE-2021-20197.patch deleted file mode 100644 index 4e2e2c72d4eb875d3142e341341a6df337b054c7..0000000000000000000000000000000000000000 --- a/backport-0003-CVE-2021-20197.patch +++ /dev/null @@ -1,368 +0,0 @@ -From 014cc7f849e8209623fc99264814bce7b3b6faf2 Mon Sep 17 00:00:00 2001 -From: Siddhesh Poyarekar -Date: Mon, 7 Dec 2020 20:48:33 +0530 -Subject: [PATCH] binutils: Make smart_rename safe too - -smart_rename is capable of handling symlinks by copying and it also -tries to preserve ownership and permissions of files when they're -overwritten during the rename. This is useful in objcopy where the -file properties need to be preserved. - -However because smart_rename does this using file names, it leaves a -race window between renames and permission fixes. This change removes -this race window by using file descriptors from the original BFDs that -were used to manipulate these files wherever possible. - -The file that is to be renamed is also passed as a file descriptor so -that we use fchown/fchmod on the file descriptor, thus making sure -that we only modify the file we have opened to write. Further, in -case the file is to be overwritten (as is the case in ar or objcopy), -the permissions that need to be restored are taken from the file -descriptor that was opened for input so that integrity of the file -status is maintained all the way through to the rename. - -binutils/ - - * rename.c - * ar.c - (write_archive) [!defined (_WIN32) || defined (__CYGWIN32__)]: - Initialize TARGET_STAT and OFD to pass to SMART_RENAME. - * arsup.c - (ar_save) [defined (_WIN32) || defined (__CYGWIN32__)]: - Likewise. - * bucomm.h (smart_rename): Add new arguments to declaration. - * objcopy.c - (strip_main)[defined (_WIN32) || defined (__CYGWIN32__)]: - Initialize COPYFD and pass to SMART_RENAME. - (copy_main) [defined (_WIN32) || defined (__CYGWIN32__)]: - Likewise. - * rename.c (try_preserve_permissions): New function. - (smart_rename): Use it and add new arguments. ---- - binutils/ChangeLog | 18 ++++++++++ - binutils/ar.c | 12 ++++++- - binutils/arsup.c | 14 +++++++- - binutils/bucomm.h | 3 +- - binutils/objcopy.c | 42 +++++++++++++++++----- - binutils/rename.c | 101 +++++++++++++++++++++++++++++++++++++---------------- - 6 files changed, 148 insertions(+), 42 deletions(-) - -diff --git a/binutils/ar.c b/binutils/ar.c -index 2253242..6598dd9 100644 ---- a/binutils/ar.c -+++ b/binutils/ar.c -@@ -1254,6 +1254,8 @@ write_archive (bfd *iarch) - char *old_name, *new_name; - bfd *contents_head = iarch->archive_next; - int ofd = -1; -+ struct stat target_stat; -+ bfd_boolean skip_stat = FALSE; - - old_name = (char *) xmalloc (strlen (bfd_get_filename (iarch)) + 1); - strcpy (old_name, bfd_get_filename (iarch)); -@@ -1299,6 +1301,14 @@ write_archive (bfd *iarch) - if (!bfd_set_archive_head (obfd, contents_head)) - bfd_fatal (old_name); - -+#if !defined (_WIN32) || defined (__CYGWIN32__) -+ ofd = dup (ofd); -+ if (iarch == NULL || iarch->iostream == NULL) -+ skip_stat = TRUE; -+ else if (ofd == -1 || fstat (fileno (iarch->iostream), &target_stat) != 0) -+ bfd_fatal (old_name); -+#endif -+ - if (!bfd_close (obfd)) - bfd_fatal (old_name); - -@@ -1308,7 +1318,7 @@ write_archive (bfd *iarch) - /* We don't care if this fails; we might be creating the archive. */ - bfd_close (iarch); - -- if (smart_rename (new_name, old_name, 0) != 0) -+ if (smart_rename (new_name, old_name, ofd, skip_stat ? NULL : &target_stat, 0) != 0) - xexit (1); - free (old_name); - free (new_name); -diff --git a/binutils/arsup.c b/binutils/arsup.c -index a668f27..8b4437f 100644 ---- a/binutils/arsup.c -+++ b/binutils/arsup.c -@@ -345,13 +345,25 @@ ar_save (void) - else - { - char *ofilename = xstrdup (bfd_get_filename (obfd)); -+ bfd_boolean skip_stat = FALSE; -+ struct stat target_stat; -+ int ofd = -1; - - if (deterministic > 0) - obfd->flags |= BFD_DETERMINISTIC_OUTPUT; - -+#if !defined (_WIN32) || defined (__CYGWIN32__) -+ /* It's OK to fail; at worst it will result in SMART_RENAME using a slow -+ copy fallback to write the output. */ -+ ofd = dup (fileno (obfd->iostream)); -+ if (lstat (real_name, &target_stat) != 0) -+ skip_stat = TRUE; -+#endif -+ - bfd_close (obfd); - -- smart_rename (ofilename, real_name, 0); -+ smart_rename (ofilename, real_name, ofd, -+ skip_stat ? NULL : &target_stat, 0); - obfd = 0; - free (ofilename); - } -diff --git a/binutils/bucomm.h b/binutils/bucomm.h -index afb8e09..9613b92 100644 ---- a/binutils/bucomm.h -+++ b/binutils/bucomm.h -@@ -71,7 +71,8 @@ extern void print_version (const char *); - /* In rename.c. */ - extern void set_times (const char *, const struct stat *); - --extern int smart_rename (const char *, const char *, int); -+extern int smart_rename (const char *, const char *, int, struct stat *, int); -+ - - /* In libiberty. */ - void *xmalloc (size_t); -diff --git a/binutils/objcopy.c b/binutils/objcopy.c -index b6cf6ea..04ba95e 100644 ---- a/binutils/objcopy.c -+++ b/binutils/objcopy.c -@@ -4815,6 +4815,7 @@ strip_main (int argc, char *argv[]) - struct stat statbuf; - char *tmpname; - int tmpfd = -1; -+ int copyfd = -1; - - if (get_file_size (argv[i]) < 1) - { -@@ -4828,7 +4829,12 @@ strip_main (int argc, char *argv[]) - else - tmpname = output_file; - -- if (tmpname == NULL) -+ if (tmpname == NULL -+#if !defined (_WIN32) || defined (__CYGWIN32__) -+ /* Retain a copy of TMPFD since we will need it for SMART_RENAME. */ -+ || (tmpfd >= 0 && (copyfd = dup (tmpfd)) == -1) -+#endif -+ ) - { - bfd_nonfatal_message (argv[i], NULL, NULL, - _("could not create temporary file to hold stripped copy")); -@@ -4846,12 +4852,18 @@ strip_main (int argc, char *argv[]) - if (output_file != tmpname) - status = (smart_rename (tmpname, - output_file ? output_file : argv[i], -- preserve_dates) != 0); -+ copyfd, &statbuf, preserve_dates) != 0); - if (status == 0) - status = hold_status; - } - else -- unlink_if_ordinary (tmpname); -+ { -+#if !defined (_WIN32) || defined (__CYGWIN32__) -+ if (copyfd >= 0) -+ close (copyfd); -+#endif -+ unlink_if_ordinary (tmpname); -+ } - if (output_file != tmpname) - free (tmpname); - } -@@ -5059,6 +5071,7 @@ copy_main (int argc, char *argv[]) - bfd_boolean use_globalize = FALSE; - bfd_boolean use_keep_global = FALSE; - int c, tmpfd = -1; -+ int copyfd = -1; - struct stat statbuf; - const bfd_arch_info_type *input_arch = NULL; - -@@ -5903,9 +5916,16 @@ copy_main (int argc, char *argv[]) - else - tmpname = output_filename; - -- if (tmpname == NULL) -- fatal (_("warning: could not create temporary file whilst copying '%s', (error: %s)"), -- input_filename, strerror (errno)); -+ if (tmpname == NULL -+#if !defined (_WIN32) || defined (__CYGWIN32__) -+ /* Retain a copy of TMPFD since we will need it for SMART_RENAME. */ -+ || (tmpfd >= 0 && (copyfd = dup (tmpfd)) == -1) -+#endif -+ ) -+ { -+ fatal (_("warning: could not create temporary file whilst copying '%s', (error: %s)"), -+ input_filename, strerror (errno)); -+ } - - copy_file (input_filename, tmpname, tmpfd, &statbuf, input_target, - output_target, input_arch); -@@ -5914,11 +5934,17 @@ copy_main (int argc, char *argv[]) - if (preserve_dates) - set_times (tmpname, &statbuf); - if (tmpname != output_filename) -- status = (smart_rename (tmpname, input_filename, -+ status = (smart_rename (tmpname, input_filename, copyfd, &statbuf, - preserve_dates) != 0); - } - else -- unlink_if_ordinary (tmpname); -+ { -+#if !defined (_WIN32) || defined (__CYGWIN32__) -+ if (copyfd >= 0) -+ close (copyfd); -+#endif -+ unlink_if_ordinary (tmpname); -+ } - - if (tmpname != output_filename) - free (tmpname); -diff --git a/binutils/rename.c b/binutils/rename.c -index bf3b68d..6b9165e 100644 ---- a/binutils/rename.c -+++ b/binutils/rename.c -@@ -131,17 +131,55 @@ set_times (const char *destination, const struct stat *statbuf) - #endif - #endif - --/* Rename FROM to TO, copying if TO is a link. -- Return 0 if ok, -1 if error. */ -+#if !defined (_WIN32) || defined (__CYGWIN32__) -+/* Try to preserve the permission bits and ownership of an existing file when -+ rename overwrites it. FD is the file being renamed and TARGET_STAT has the -+ status of the file that was overwritten. */ -+static void -+try_preserve_permissions (int fd, struct stat *target_stat) -+{ -+ struct stat from_stat; -+ int ret = 0; -+ -+ if (fstat (fd, &from_stat) != 0) -+ return; -+ -+ int from_mode = from_stat.st_mode & 0777; -+ int to_mode = target_stat->st_mode & 0777; -+ -+ /* Fix up permissions before we potentially lose ownership with fchown. -+ Clear the setxid bits because in case the fchown below fails then we don't -+ want to end up with a sxid file owned by the invoking user. If the user -+ hasn't changed or if fchown succeeded, we add back the sxid bits at the -+ end. */ -+ if (from_mode != to_mode) -+ fchmod (fd, to_mode); -+ -+ /* Fix up ownership, this will clear the setxid bits. */ -+ if (from_stat.st_uid != target_stat->st_uid -+ || from_stat.st_gid != target_stat->st_gid) -+ ret = fchown (fd, target_stat->st_uid, target_stat->st_gid); -+ -+ /* Fix up the sxid bits if either the fchown wasn't needed or it -+ succeeded. */ -+ if (ret == 0) -+ fchmod (fd, target_stat->st_mode & 07777); -+} -+#endif -+ -+/* Rename FROM to TO, copying if TO is either a link or is not a regular file. -+ FD is an open file descriptor pointing to FROM that we can use to safely fix -+ up permissions of the file after renaming. TARGET_STAT has the file status -+ that is used to fix up permissions and timestamps after rename. Return 0 if -+ ok, -1 if error and FD is closed before returning. */ - - int --smart_rename (const char *from, const char *to, int preserve_dates ATTRIBUTE_UNUSED) -+smart_rename (const char *from, const char *to, int fd ATTRIBUTE_UNUSED, -+ struct stat *target_stat ATTRIBUTE_UNUSED, -+ int preserve_dates ATTRIBUTE_UNUSED) - { -- bfd_boolean exists; -- struct stat s; - int ret = 0; -- -- exists = lstat (to, &s) == 0; -+ bfd_boolean exists = target_stat != NULL; - - #if defined (_WIN32) && !defined (__CYGWIN32__) - /* Win32, unlike unix, will not erase `to' in `rename(from, to)' but -@@ -158,36 +196,35 @@ smart_rename (const char *from, const char *to, int preserve_dates ATTRIBUTE_UNU - unlink (from); - } - #else -- /* Use rename only if TO is not a symbolic link and has -- only one hard link, and we have permission to write to it. */ -+ /* Avoid a full copy and use rename if we can fix up permissions of the -+ file after renaming, i.e.: -+ -+ - TO is not a symbolic link -+ - TO is a regular file with only one hard link -+ - We have permission to write to TO -+ - FD is available to safely fix up permissions to be the same as the file -+ we overwrote with the rename. -+ -+ Note though that the actual file on disk that TARGET_STAT describes may -+ have changed and we're only trying to preserve the status we know about. -+ At no point do we try to interact with the new file changes, so there can -+ only be two outcomes, i.e. either the external file change survives -+ without knowledge of our change (if it happens after the rename syscall) -+ or our rename and permissions fixup survive without any knowledge of the -+ external change. */ - if (! exists -- || (!S_ISLNK (s.st_mode) -- && S_ISREG (s.st_mode) -- && (s.st_mode & S_IWUSR) -- && s.st_nlink == 1) -+ || (fd >= 0 -+ && !S_ISLNK (target_stat->st_mode) -+ && S_ISREG (target_stat->st_mode) -+ && (target_stat->st_mode & S_IWUSR) -+ && target_stat->st_nlink == 1) - ) - { - ret = rename (from, to); - if (ret == 0) - { - if (exists) -- { -- /* Try to preserve the permission bits and ownership of -- TO. First get the mode right except for the setuid -- bit. Then change the ownership. Then fix the setuid -- bit. We do the chmod before the chown because if the -- chown succeeds, and we are a normal user, we won't be -- able to do the chmod afterward. We don't bother to -- fix the setuid bit first because that might introduce -- a fleeting security problem, and because the chown -- will clear the setuid bit anyhow. We only fix the -- setuid bit if the chown succeeds, because we don't -- want to introduce an unexpected setuid file owned by -- the user running objcopy. */ -- chmod (to, s.st_mode & 0777); -- if (chown (to, s.st_uid, s.st_gid) >= 0) -- chmod (to, s.st_mode & 07777); -- } -+ try_preserve_permissions (fd, target_stat); - } - else - { -@@ -203,9 +240,11 @@ smart_rename (const char *from, const char *to, int preserve_dates ATTRIBUTE_UNU - non_fatal (_("unable to copy file '%s'; reason: %s"), to, strerror (errno)); - - if (preserve_dates) -- set_times (to, &s); -+ set_times (to, target_stat); - unlink (from); - } -+ if (fd >= 0) -+ close (fd); - #endif /* _WIN32 && !__CYGWIN32__ */ - - return ret; --- -1.8.3.1 - diff --git a/backport-0003-CVE-2021-42574.patch b/backport-0003-CVE-2021-42574.patch new file mode 100644 index 0000000000000000000000000000000000000000..8bb90d14b90473325d9cdf292d7ce9586095fe55 --- /dev/null +++ b/backport-0003-CVE-2021-42574.patch @@ -0,0 +1,33 @@ +From 584294c4066d0101161e4e04744a46cce7a7863e Mon Sep 17 00:00:00 2001 +From: Nick Clifton +Date: Mon, 29 Nov 2021 15:37:24 +0000 +Subject: [PATCH] strings: Replace references to -u option with references to + -U. + + PR 28632 +--- + binutils/strings.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/binutils/strings.c b/binutils/strings.c +index f594299939f9..f85cb03406c9 100644 +--- a/binutils/strings.c ++++ b/binutils/strings.c +@@ -57,7 +57,7 @@ + Specify a non-default object file format. + + --unicode={default|locale|invalid|hex|escape|highlight} +- -u {d|l|i|x|e|h} ++ -U {d|l|i|x|e|h} + Determine how to handle UTF-8 unicode characters. The default + is no special treatment. All other versions of this option + only apply if the encoding is valid and enabling the option +@@ -1333,7 +1333,7 @@ usage (FILE *stream, int status) + -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\ + s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\ + --unicode={default|show|invalid|hex|escape|highlight}\n\ +- -u {d|s|i|x|e|h} Specify how to treat UTF-8 encoded unicode characters\n\ ++ -U {d|s|i|x|e|h} Specify how to treat UTF-8 encoded unicode characters\n\ + -s --output-separator= String used to separate strings in output.\n\ + @ Read options from \n\ + -h --help Display this information\n\ diff --git a/backport-0004-CVE-2021-20197.patch b/backport-0004-CVE-2021-20197.patch deleted file mode 100644 index 39a16eca1cc8d59055863a4404d3446f321a34fd..0000000000000000000000000000000000000000 --- a/backport-0004-CVE-2021-20197.patch +++ /dev/null @@ -1,193 +0,0 @@ -From 95b91a043aeaeb546d2fea556d84a2de1e917770 Mon Sep 17 00:00:00 2001 -From: Alan Modra -Date: Mon, 1 Feb 2021 02:04:41 +1030 -Subject: [PATCH] pr27270 and pr27284, ar segfaults and wrong file mode - - PR 27270 - PR 27284 - PR 26945 - * ar.c: Don't include libbfd.h. - (write_archive): Replace xmalloc+strcpy with xstrdup. Use - bfd_stat rather than fstat on iostream. Move stat and fd tests - outside of _WIN32 ifdef. Delete skip_stat variable. - * arsup.c (temp_name, real_ofd): New static variables. - (ar_open): Use make_tempname and bfd_fdopenw. - (ar_save): Adjust to suit ar_open changes. Move stat output - of _WIN32 ifdef. - * objcopy.c: Don't include libbfd.h. - (copy_file): Use bfd_stat. ---- - binutils/ChangeLog | 16 ++++++++++++++++ - binutils/ar.c | 13 ++++--------- - binutils/arsup.c | 46 +++++++++++++++++++++++++++++----------------- - binutils/objcopy.c | 3 +-- - 4 files changed, 50 insertions(+), 28 deletions(-) - -diff --git a/binutils/ar.c b/binutils/ar.c -index 24ff092..0ecfa33 100644 ---- a/binutils/ar.c -+++ b/binutils/ar.c -@@ -25,7 +25,6 @@ - - #include "sysdep.h" - #include "bfd.h" --#include "libbfd.h" - #include "libiberty.h" - #include "progress.h" - #include "getopt.h" -@@ -1255,10 +1254,8 @@ write_archive (bfd *iarch) - bfd *contents_head = iarch->archive_next; - int ofd = -1; - struct stat target_stat; -- bfd_boolean skip_stat = FALSE; - -- old_name = (char *) xmalloc (strlen (bfd_get_filename (iarch)) + 1); -- strcpy (old_name, bfd_get_filename (iarch)); -+ old_name = xstrdup (bfd_get_filename (iarch)); - new_name = make_tempname (old_name, &ofd); - - if (new_name == NULL) -@@ -1303,11 +1300,9 @@ write_archive (bfd *iarch) - - #if !defined (_WIN32) || defined (__CYGWIN32__) - ofd = dup (ofd); -- if (iarch == NULL || iarch->iostream == NULL) -- skip_stat = TRUE; -- else if (ofd == -1 || fstat (fileno ((FILE *) iarch->iostream), &target_stat) != 0) -- bfd_fatal (old_name); - #endif -+ if (ofd == -1 || bfd_stat (iarch, &target_stat) != 0) -+ bfd_fatal (old_name); - - if (!bfd_close (obfd)) - bfd_fatal (old_name); -@@ -1318,7 +1313,7 @@ write_archive (bfd *iarch) - /* We don't care if this fails; we might be creating the archive. */ - bfd_close (iarch); - -- if (smart_rename (new_name, old_name, ofd, skip_stat ? NULL : &target_stat, 0) != 0) -+ if (smart_rename (new_name, old_name, ofd, &target_stat, 0) != 0) - xexit (1); - free (old_name); - free (new_name); -diff --git a/binutils/arsup.c b/binutils/arsup.c -index 837011b..a60629f 100644 ---- a/binutils/arsup.c -+++ b/binutils/arsup.c -@@ -42,6 +42,8 @@ extern int deterministic; - - static bfd *obfd; - static char *real_name; -+static char *temp_name; -+static int real_ofd; - static FILE *outfile; - - static void -@@ -149,27 +151,24 @@ maybequit (void) - void - ar_open (char *name, int t) - { -- char *tname; -- const char *bname = lbasename (name); -- real_name = name; -+ real_name = xstrdup (name); -+ temp_name = make_tempname (real_name, &real_ofd); - -- /* Prepend tmp- to the beginning, to avoid file-name clashes after -- truncation on filesystems with limited namespaces (DOS). */ -- if (asprintf (&tname, "%.*stmp-%s", (int) (bname - name), name, bname) == -1) -+ if (temp_name == NULL) - { -- fprintf (stderr, _("%s: Can't allocate memory for temp name (%s)\n"), -+ fprintf (stderr, _("%s: Can't open temporary file (%s)\n"), - program_name, strerror(errno)); - maybequit (); - return; - } - -- obfd = bfd_openw (tname, NULL); -+ obfd = bfd_fdopenw (temp_name, NULL, real_ofd); - - if (!obfd) - { - fprintf (stderr, - _("%s: Can't open output archive %s\n"), -- program_name, tname); -+ program_name, temp_name); - - maybequit (); - } -@@ -344,10 +343,9 @@ ar_save (void) - } - else - { -- char *ofilename = xstrdup (bfd_get_filename (obfd)); - bfd_boolean skip_stat = FALSE; - struct stat target_stat; -- int ofd = -1; -+ int ofd = real_ofd; - - if (deterministic > 0) - obfd->flags |= BFD_DETERMINISTIC_OUTPUT; -@@ -355,17 +353,31 @@ ar_save (void) - #if !defined (_WIN32) || defined (__CYGWIN32__) - /* It's OK to fail; at worst it will result in SMART_RENAME using a slow - copy fallback to write the output. */ -- ofd = dup (fileno ((FILE *) obfd->iostream)); -- if (lstat (real_name, &target_stat) != 0) -- skip_stat = TRUE; -+ ofd = dup (ofd); - #endif -- - bfd_close (obfd); - -- smart_rename (ofilename, real_name, ofd, -+ if (lstat (real_name, &target_stat) != 0) -+ { -+ /* The temp file created in ar_open has mode 0600 as per mkstemp. -+ Create the real empty output file here so smart_rename will -+ update the mode according to the process umask. */ -+ obfd = bfd_openw (real_name, NULL); -+ if (obfd == NULL -+ || bfd_stat (obfd, &target_stat) != 0) -+ skip_stat = TRUE; -+ if (obfd != NULL) -+ { -+ bfd_set_format (obfd, bfd_archive); -+ bfd_close (obfd); -+ } -+ } -+ -+ smart_rename (temp_name, real_name, ofd, - skip_stat ? NULL : &target_stat, 0); - obfd = 0; -- free (ofilename); -+ free (temp_name); -+ free (real_name); - } - } - -diff --git a/binutils/objcopy.c b/binutils/objcopy.c -index 39a1ccb..0e1047e 100644 ---- a/binutils/objcopy.c -+++ b/binutils/objcopy.c -@@ -20,7 +20,6 @@ - - #include "sysdep.h" - #include "bfd.h" --#include "libbfd.h" - #include "progress.h" - #include "getopt.h" - #include "libiberty.h" -@@ -3768,7 +3767,7 @@ copy_file (const char *input_filename, const char *output_filename, int ofd, - /* To allow us to do "strip *" without dying on the first - non-object file, failures are nonfatal. */ - ibfd = bfd_openr (input_filename, input_target); -- if (ibfd == NULL || fstat (fileno ((FILE *) ibfd->iostream), in_stat) != 0) -+ if (ibfd == NULL || bfd_stat (ibfd, in_stat) != 0) - { - bfd_nonfatal_message (input_filename, NULL, NULL, NULL); - status = 1; --- -1.8.3.1 - diff --git a/backport-CVE-2021-3549.patch b/backport-CVE-2021-3549.patch deleted file mode 100644 index 6147f984ebd96cf8674c8b6bc95cbe1dce8c2928..0000000000000000000000000000000000000000 --- a/backport-CVE-2021-3549.patch +++ /dev/null @@ -1,162 +0,0 @@ -From 1cfcf3004e1830f8fe9112cfcd15285508d2c2b7 Mon Sep 17 00:00:00 2001 -From: Alan Modra -Date: Thu, 11 Feb 2021 16:56:42 +1030 -Subject: [PATCH] PR27290, PR27293, PR27295, various avr objdump fixes - -Adds missing sanity checks for avr device info note, to avoid -potential buffer overflows. Uses bfd_malloc_and_get_section for -sanity checking section size. - - PR 27290 - PR 27293 - PR 27295 - * od-elf32_avr.c (elf32_avr_get_note_section_contents): Formatting. - Use bfd_malloc_and_get_section. - (elf32_avr_get_note_desc): Formatting. Return descsz. Sanity - check namesz. Return NULL if descsz is too small. Ensure - string table is terminated. - (elf32_avr_get_device_info): Formatting. Add note_size param. - Sanity check note. - (elf32_avr_dump_mem_usage): Adjust to suit. ---- - binutils/od-elf32_avr.c | 66 +++++++++++++++++++++++++++++++------------------ - 1 files changed, 56 insertions(+), 24 deletions(-) - -diff --git a/binutils/od-elf32_avr.c b/binutils/od-elf32_avr.c -index 11800e7..4377a7c 100644 ---- a/binutils/od-elf32_avr.c -+++ b/binutils/od-elf32_avr.c -@@ -77,23 +77,29 @@ elf32_avr_filter (bfd *abfd) - return bfd_get_flavour (abfd) == bfd_target_elf_flavour; - } - --static char* -+static char * - elf32_avr_get_note_section_contents (bfd *abfd, bfd_size_type *size) - { - asection *section; -+ bfd_byte *contents; - -- if ((section = bfd_get_section_by_name (abfd, ".note.gnu.avr.deviceinfo")) == NULL) -+ section = bfd_get_section_by_name (abfd, ".note.gnu.avr.deviceinfo"); -+ if (section == NULL) - return NULL; - -- *size = bfd_section_size (section); -- char *contents = (char *) xmalloc (*size); -- bfd_get_section_contents (abfd, section, contents, 0, *size); -+ if (!bfd_malloc_and_get_section (abfd, section, &contents)) -+ { -+ free (contents); -+ contents = NULL; -+ } - -- return contents; -+ *size = bfd_section_size (section); -+ return (char *) contents; - } - --static char* elf32_avr_get_note_desc (bfd *abfd, char *contents, -- bfd_size_type size) -+static char * -+elf32_avr_get_note_desc (bfd *abfd, char *contents, bfd_size_type size, -+ bfd_size_type *descsz) - { - Elf_External_Note *xnp = (Elf_External_Note *) contents; - Elf_Internal_Note in; -@@ -107,42 +113,54 @@ static char* elf32_avr_get_note_desc (bfd *abfd, char *contents, - if (in.namesz > contents - in.namedata + size) - return NULL; - -+ if (in.namesz != 4 || strcmp (in.namedata, "AVR") != 0) -+ return NULL; -+ - in.descsz = bfd_get_32 (abfd, xnp->descsz); - in.descdata = in.namedata + align_power (in.namesz, 2); -- if (in.descsz != 0 -- && (in.descdata >= contents + size -- || in.descsz > contents - in.descdata + size)) -+ if (in.descsz < 6 * sizeof (uint32_t) -+ || in.descdata >= contents + size -+ || in.descsz > contents - in.descdata + size) - return NULL; - -- if (strcmp (in.namedata, "AVR") != 0) -- return NULL; -+ /* If the note has a string table, ensure it is 0 terminated. */ -+ if (in.descsz > 8 * sizeof (uint32_t)) -+ in.descdata[in.descsz - 1] = 0; - -+ *descsz = in.descsz; - return in.descdata; - } - - static void - elf32_avr_get_device_info (bfd *abfd, char *description, -- deviceinfo *device) -+ bfd_size_type desc_size, deviceinfo *device) - { - if (description == NULL) - return; - - const bfd_size_type memory_sizes = 6; - -- memcpy (device, description, memory_sizes * sizeof(uint32_t)); -- device->name = NULL; -+ memcpy (device, description, memory_sizes * sizeof (uint32_t)); -+ desc_size -= memory_sizes * sizeof (uint32_t); -+ if (desc_size < 8) -+ return; - -- uint32_t *stroffset_table = ((uint32_t *) description) + memory_sizes; -+ uint32_t *stroffset_table = (uint32_t *) description + memory_sizes; - bfd_size_type stroffset_table_size = bfd_get_32 (abfd, stroffset_table); -- char *str_table = ((char *) stroffset_table) + stroffset_table_size; - - /* If the only content is the size itself, there's nothing in the table */ -- if (stroffset_table_size == 4) -+ if (stroffset_table_size < 8) - return; -+ if (desc_size <= stroffset_table_size) -+ return; -+ desc_size -= stroffset_table_size; - - /* First entry is the device name index. */ - uint32_t device_name_index = bfd_get_32 (abfd, stroffset_table + 1); -+ if (device_name_index >= desc_size) -+ return; - -+ char *str_table = (char *) stroffset_table + stroffset_table_size; - device->name = str_table + device_name_index; - } - -@@ -183,7 +201,7 @@ static void - elf32_avr_dump_mem_usage (bfd *abfd) - { - char *description = NULL; -- bfd_size_type note_section_size = 0; -+ bfd_size_type sec_size, desc_size; - - deviceinfo device = { 0, 0, 0, 0, 0, 0, NULL }; - device.name = "Unknown"; -@@ -192,13 +210,13 @@ elf32_avr_dump_mem_usage (bfd *abfd) - bfd_size_type text_usage = 0; - bfd_size_type eeprom_usage = 0; - -- char *contents = elf32_avr_get_note_section_contents (abfd, -- ¬e_section_size); -+ char *contents = elf32_avr_get_note_section_contents (abfd, &sec_size); - - if (contents != NULL) - { -- description = elf32_avr_get_note_desc (abfd, contents, note_section_size); -- elf32_avr_get_device_info (abfd, description, &device); -+ description = elf32_avr_get_note_desc (abfd, contents, sec_size, -+ &desc_size); -+ elf32_avr_get_device_info (abfd, description, desc_size, &device); - } - - elf32_avr_get_memory_usage (abfd, &text_usage, &data_usage, --- -1.8.3.1 - diff --git a/backport-CVE-2021-45078.patch b/backport-CVE-2021-45078.patch index 5c6f1600c84490d5cbffea99eeb034d0c4e0fe82..6b3dd1fd24ea63a7e36412f81e69420263108e77 100644 --- a/backport-CVE-2021-45078.patch +++ b/backport-CVE-2021-45078.patch @@ -12,11 +12,11 @@ Subject: [PATCH] PR28694, Out-of-bounds write in stab_xcoff_builtin_type 1 file changed, 43 insertions(+), 44 deletions(-) diff --git a/binutils/stabs.c b/binutils/stabs.c -index 90254fd..d430d4a 100644 +index 274bfb0e7fa..83ee3ea5fa4 100644 --- a/binutils/stabs.c +++ b/binutils/stabs.c @@ -202,7 +202,7 @@ static debug_type stab_find_type (void *, struct stab_handle *, const int *); - static bfd_boolean stab_record_type + static bool stab_record_type (void *, struct stab_handle *, const int *, debug_type); static debug_type stab_xcoff_builtin_type - (void *, struct stab_handle *, int); @@ -55,52 +55,52 @@ index 90254fd..d430d4a 100644 /* The size of this and all the other types are fixed, defined by the debugging format. */ name = "int"; - rettype = debug_make_int_type (dhandle, 4, FALSE); + rettype = debug_make_int_type (dhandle, 4, false); break; - case 2: + case 1: name = "char"; - rettype = debug_make_int_type (dhandle, 1, FALSE); + rettype = debug_make_int_type (dhandle, 1, false); break; - case 3: + case 2: name = "short"; - rettype = debug_make_int_type (dhandle, 2, FALSE); + rettype = debug_make_int_type (dhandle, 2, false); break; - case 4: + case 3: name = "long"; - rettype = debug_make_int_type (dhandle, 4, FALSE); + rettype = debug_make_int_type (dhandle, 4, false); break; - case 5: + case 4: name = "unsigned char"; - rettype = debug_make_int_type (dhandle, 1, TRUE); + rettype = debug_make_int_type (dhandle, 1, true); break; - case 6: + case 5: name = "signed char"; - rettype = debug_make_int_type (dhandle, 1, FALSE); + rettype = debug_make_int_type (dhandle, 1, false); break; - case 7: + case 6: name = "unsigned short"; - rettype = debug_make_int_type (dhandle, 2, TRUE); + rettype = debug_make_int_type (dhandle, 2, true); break; - case 8: + case 7: name = "unsigned int"; - rettype = debug_make_int_type (dhandle, 4, TRUE); + rettype = debug_make_int_type (dhandle, 4, true); break; - case 9: + case 8: name = "unsigned"; - rettype = debug_make_int_type (dhandle, 4, TRUE); + rettype = debug_make_int_type (dhandle, 4, true); break; - case 10: + case 9: name = "unsigned long"; - rettype = debug_make_int_type (dhandle, 4, TRUE); + rettype = debug_make_int_type (dhandle, 4, true); break; - case 11: + case 10: @@ -130,7 +130,7 @@ index 90254fd..d430d4a 100644 - case 15: + case 14: name = "integer"; - rettype = debug_make_int_type (dhandle, 4, FALSE); + rettype = debug_make_int_type (dhandle, 4, false); break; - case 16: + case 15: @@ -157,7 +157,7 @@ index 90254fd..d430d4a 100644 + case 19: /* FIXME */ name = "character"; - rettype = debug_make_int_type (dhandle, 1, TRUE); + rettype = debug_make_int_type (dhandle, 1, true); break; - case 21: + case 20: @@ -194,33 +194,33 @@ index 90254fd..d430d4a 100644 - case 27: + case 26: name = "integer*1"; - rettype = debug_make_int_type (dhandle, 1, FALSE); + rettype = debug_make_int_type (dhandle, 1, false); break; - case 28: + case 27: name = "integer*2"; - rettype = debug_make_int_type (dhandle, 2, FALSE); + rettype = debug_make_int_type (dhandle, 2, false); break; - case 29: + case 28: name = "integer*4"; - rettype = debug_make_int_type (dhandle, 4, FALSE); + rettype = debug_make_int_type (dhandle, 4, false); break; - case 30: + case 29: /* FIXME */ name = "wchar"; - rettype = debug_make_int_type (dhandle, 2, FALSE); + rettype = debug_make_int_type (dhandle, 2, false); break; - case 31: + case 30: name = "long long"; - rettype = debug_make_int_type (dhandle, 8, FALSE); + rettype = debug_make_int_type (dhandle, 8, false); break; - case 32: + case 31: name = "unsigned long long"; - rettype = debug_make_int_type (dhandle, 8, TRUE); + rettype = debug_make_int_type (dhandle, 8, true); break; - case 33: + case 32: @@ -230,7 +230,7 @@ index 90254fd..d430d4a 100644 - case 34: + case 33: name = "integer*8"; - rettype = debug_make_int_type (dhandle, 8, FALSE); + rettype = debug_make_int_type (dhandle, 8, false); break; @@ -3664,9 +3665,7 @@ stab_xcoff_builtin_type (void *dhandle, struct stab_handle *info, } @@ -243,6 +243,3 @@ index 90254fd..d430d4a 100644 return rettype; } --- -1.8.3.1 - diff --git a/backport-Fix-a-build-problem-when-using-FreeBSD-12.patch b/backport-Fix-a-build-problem-when-using-FreeBSD-12.patch deleted file mode 100644 index 36671d64f8c68feeb6b315819bc7b765b666248b..0000000000000000000000000000000000000000 --- a/backport-Fix-a-build-problem-when-using-FreeBSD-12.patch +++ /dev/null @@ -1,57 +0,0 @@ -From b143e2d506bee1020752597f979d5af174edc36d Mon Sep 17 00:00:00 2001 -From: Sebastian Huber -Date: Fri, 11 Dec 2020 13:27:45 +0000 -Subject: [PATCH] Fix a build problem when using FreeBSD 12. - - * ar.c (write_archive): Cast iostream pointer to FILE *. - * arsup.c (ar_save): Likewise. - * objcopy.c (copy_file): Likewise. ---- - binutils/ChangeLog | 6 ++++++ - binutils/ar.c | 2 +- - binutils/arsup.c | 2 +- - binutils/objcopy.c | 2 +- - 4 files changed, 9 insertions(+), 3 deletions(-) - -diff --git a/binutils/ar.c b/binutils/ar.c -index 6598dd9..8329223 100644 ---- a/binutils/ar.c -+++ b/binutils/ar.c -@@ -1305,7 +1305,7 @@ write_archive (bfd *iarch) - ofd = dup (ofd); - if (iarch == NULL || iarch->iostream == NULL) - skip_stat = TRUE; -- else if (ofd == -1 || fstat (fileno (iarch->iostream), &target_stat) != 0) -+ else if (ofd == -1 || fstat (fileno ((FILE *) iarch->iostream), &target_stat) != 0) - bfd_fatal (old_name); - #endif - -diff --git a/binutils/arsup.c b/binutils/arsup.c -index 8b4437f..dad4174 100644 ---- a/binutils/arsup.c -+++ b/binutils/arsup.c -@@ -355,7 +355,7 @@ ar_save (void) - #if !defined (_WIN32) || defined (__CYGWIN32__) - /* It's OK to fail; at worst it will result in SMART_RENAME using a slow - copy fallback to write the output. */ -- ofd = dup (fileno (obfd->iostream)); -+ ofd = dup (fileno ((FILE *) obfd->iostream)); - if (lstat (real_name, &target_stat) != 0) - skip_stat = TRUE; - #endif -diff --git a/binutils/objcopy.c b/binutils/objcopy.c -index 06ecf3e..0ea3ea1 100644 ---- a/binutils/objcopy.c -+++ b/binutils/objcopy.c -@@ -3745,7 +3745,7 @@ copy_file (const char *input_filename, const char *output_filename, int ofd, - /* To allow us to do "strip *" without dying on the first - non-object file, failures are nonfatal. */ - ibfd = bfd_openr (input_filename, input_target); -- if (ibfd == NULL || fstat (fileno (ibfd->iostream), in_stat) != 0) -+ if (ibfd == NULL || fstat (fileno ((FILE *) ibfd->iostream), in_stat) != 0) - { - bfd_nonfatal_message (input_filename, NULL, NULL, NULL); - status = 1; --- -1.8.3.1 - diff --git a/backport-Fix-demangle-style-usage-info.patch b/backport-Fix-demangle-style-usage-info.patch deleted file mode 100644 index 99d2fc70805d8e047bf8f29849b21f4a086ff651..0000000000000000000000000000000000000000 --- a/backport-Fix-demangle-style-usage-info.patch +++ /dev/null @@ -1,463 +0,0 @@ -From 0d64622696e02ad649d048f4af3a3f293481f89f Mon Sep 17 00:00:00 2001 -From: Alan Modra -Date: Thu, 11 Nov 2021 20:21:32 +1030 -Subject: [PATCH] Fix demangle style usage info - -Extract allowed styles from libiberty, so we don't have to worry about -our help messages getting out of date. The function probably belongs -in libiberty/cplus-dem.c but it can be here for a while to iron out -bugs. - - PR 28581 - * demanguse.c: New file. - * demanguse.h: New file. - * nm.c (usage): Break up output. Use display_demangler_styles. - * objdump.c (usage): Use display_demangler_styles. - * readelf.c (usage): Likewise. - * Makefile.am: Add demanguse.c and demanguse.h. - * Makefile.in: Regenerate. - * po/POTFILESin: Regenerate. ---- - binutils/Makefile.am | 10 ++-- - binutils/Makefile.in | 19 ++++--- - binutils/demanguse.c | 54 +++++++++++++++++++ - binutils/demanguse.h | 34 ++++++++++++ - binutils/nm.c | 113 ++++++++++++++++++++++++++-------------- - binutils/objdump.c | 8 +-- - binutils/po/POTFILES.in | 2 + - binutils/readelf.c | 8 +-- - 8 files changed, 188 insertions(+), 60 deletions(-) - create mode 100644 binutils/demanguse.c - create mode 100644 binutils/demanguse.h - -diff --git a/binutils/Makefile.am b/binutils/Makefile.am -index 00416cb635e..7f4c24c213b 100644 ---- a/binutils/Makefile.am -+++ b/binutils/Makefile.am -@@ -122,7 +122,7 @@ AM_CPPFLAGS = -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) \ - - HFILES = \ - arsup.h binemul.h bucomm.h budbg.h \ -- coffgrok.h debug.h dlltool.h dwarf.h elfcomm.h \ -+ coffgrok.h debug.h demanguse.h dlltool.h dwarf.h elfcomm.h \ - objdump.h sysdep.h unwind-ia64.h windres.h winduni.h windint.h \ - windmc.h - -@@ -132,7 +132,7 @@ BUILT_SOURCES = $(GENERATED_HFILES) - CFILES = \ - addr2line.c ar.c arsup.c bin2c.c binemul.c bucomm.c \ - coffdump.c coffgrok.c cxxfilt.c \ -- dwarf.c debug.c dlltool.c dllwrap.c \ -+ dwarf.c debug.c demanguse.c dlltool.c dllwrap.c \ - elfcomm.c emul_aix.c emul_vanilla.c filemode.c \ - is-ranlib.c is-strip.c maybe-ranlib.c maybe-strip.c \ - nm.c not-ranlib.c not-strip.c \ -@@ -252,7 +252,7 @@ objcopy_SOURCES = objcopy.c not-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS) - - strings_SOURCES = strings.c $(BULIBS) - --readelf_SOURCES = readelf.c version.c unwind-ia64.c dwarf.c $(ELFLIBS) -+readelf_SOURCES = readelf.c version.c unwind-ia64.c dwarf.c demanguse.c $(ELFLIBS) - readelf_LDADD = $(LIBCTF_NOBFD) $(LIBINTL) $(LIBIBERTY) $(ZLIB) $(DEBUGINFOD_LIBS) - - elfedit_SOURCES = elfedit.c version.c $(ELFLIBS) -@@ -260,9 +260,9 @@ elfedit_LDADD = $(LIBINTL) $(LIBIBERTY) - - strip_new_SOURCES = objcopy.c is-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS) - --nm_new_SOURCES = nm.c $(BULIBS) -+nm_new_SOURCES = nm.c demanguse.c $(BULIBS) - --objdump_SOURCES = objdump.c dwarf.c prdbg.c $(DEBUG_SRCS) $(BULIBS) $(ELFLIBS) -+objdump_SOURCES = objdump.c dwarf.c prdbg.c demanguse.c $(DEBUG_SRCS) $(BULIBS) $(ELFLIBS) - EXTRA_objdump_SOURCES = od-xcoff.c - objdump_LDADD = $(OBJDUMP_PRIVATE_OFILES) $(OPCODES) $(LIBCTF) $(BFDLIB) $(LIBIBERTY) $(LIBINTL) $(DEBUGINFOD_LIBS) - -diff --git a/binutils/Makefile.in b/binutils/Makefile.in -index bed8fef64d8..5252ef18b5c 100644 ---- a/binutils/Makefile.in -+++ b/binutils/Makefile.in -@@ -212,7 +212,7 @@ am__objects_2 = elfcomm.$(OBJEXT) - am_elfedit_OBJECTS = elfedit.$(OBJEXT) version.$(OBJEXT) \ - $(am__objects_2) - elfedit_OBJECTS = $(am_elfedit_OBJECTS) --am_nm_new_OBJECTS = nm.$(OBJEXT) $(am__objects_1) -+am_nm_new_OBJECTS = nm.$(OBJEXT) demanguse.$(OBJEXT) $(am__objects_1) - nm_new_OBJECTS = $(am_nm_new_OBJECTS) - nm_new_LDADD = $(LDADD) - am__objects_3 = rddbg.$(OBJEXT) debug.$(OBJEXT) stabs.$(OBJEXT) \ -@@ -223,7 +223,8 @@ am_objcopy_OBJECTS = objcopy.$(OBJEXT) not-strip.$(OBJEXT) \ - objcopy_OBJECTS = $(am_objcopy_OBJECTS) - objcopy_LDADD = $(LDADD) - am_objdump_OBJECTS = objdump.$(OBJEXT) dwarf.$(OBJEXT) prdbg.$(OBJEXT) \ -- $(am__objects_3) $(am__objects_1) $(am__objects_2) -+ demanguse.$(OBJEXT) $(am__objects_3) $(am__objects_1) \ -+ $(am__objects_2) - objdump_OBJECTS = $(am_objdump_OBJECTS) - @ENABLE_LIBCTF_TRUE@am__DEPENDENCIES_2 = ../libctf/libctf.la - am_ranlib_OBJECTS = ar.$(OBJEXT) is-ranlib.$(OBJEXT) arparse.$(OBJEXT) \ -@@ -231,7 +232,8 @@ am_ranlib_OBJECTS = ar.$(OBJEXT) is-ranlib.$(OBJEXT) arparse.$(OBJEXT) \ - binemul.$(OBJEXT) emul_$(EMULATION).$(OBJEXT) $(am__objects_1) - ranlib_OBJECTS = $(am_ranlib_OBJECTS) - am_readelf_OBJECTS = readelf.$(OBJEXT) version.$(OBJEXT) \ -- unwind-ia64.$(OBJEXT) dwarf.$(OBJEXT) $(am__objects_2) -+ unwind-ia64.$(OBJEXT) dwarf.$(OBJEXT) demanguse.$(OBJEXT) \ -+ $(am__objects_2) - readelf_OBJECTS = $(am_readelf_OBJECTS) - @ENABLE_LIBCTF_TRUE@am__DEPENDENCIES_3 = ../libctf/libctf-nobfd.la - am_size_OBJECTS = size.$(OBJEXT) $(am__objects_1) -@@ -632,7 +634,7 @@ AM_CPPFLAGS = -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) \ - - HFILES = \ - arsup.h binemul.h bucomm.h budbg.h \ -- coffgrok.h debug.h dlltool.h dwarf.h elfcomm.h \ -+ coffgrok.h debug.h demanguse.h dlltool.h dwarf.h elfcomm.h \ - objdump.h sysdep.h unwind-ia64.h windres.h winduni.h windint.h \ - windmc.h - -@@ -641,7 +643,7 @@ BUILT_SOURCES = $(GENERATED_HFILES) - CFILES = \ - addr2line.c ar.c arsup.c bin2c.c binemul.c bucomm.c \ - coffdump.c coffgrok.c cxxfilt.c \ -- dwarf.c debug.c dlltool.c dllwrap.c \ -+ dwarf.c debug.c demanguse.c dlltool.c dllwrap.c \ - elfcomm.c emul_aix.c emul_vanilla.c filemode.c \ - is-ranlib.c is-strip.c maybe-ranlib.c maybe-strip.c \ - nm.c not-ranlib.c not-strip.c \ -@@ -720,13 +722,13 @@ LDADD = $(BFDLIB) $(LIBIBERTY) $(LIBINTL) - size_SOURCES = size.c $(BULIBS) - objcopy_SOURCES = objcopy.c not-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS) - strings_SOURCES = strings.c $(BULIBS) --readelf_SOURCES = readelf.c version.c unwind-ia64.c dwarf.c $(ELFLIBS) -+readelf_SOURCES = readelf.c version.c unwind-ia64.c dwarf.c demanguse.c $(ELFLIBS) - readelf_LDADD = $(LIBCTF_NOBFD) $(LIBINTL) $(LIBIBERTY) $(ZLIB) $(DEBUGINFOD_LIBS) - elfedit_SOURCES = elfedit.c version.c $(ELFLIBS) - elfedit_LDADD = $(LIBINTL) $(LIBIBERTY) - strip_new_SOURCES = objcopy.c is-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS) --nm_new_SOURCES = nm.c $(BULIBS) --objdump_SOURCES = objdump.c dwarf.c prdbg.c $(DEBUG_SRCS) $(BULIBS) $(ELFLIBS) -+nm_new_SOURCES = nm.c demanguse.c $(BULIBS) -+objdump_SOURCES = objdump.c dwarf.c prdbg.c demanguse.c $(DEBUG_SRCS) $(BULIBS) $(ELFLIBS) - EXTRA_objdump_SOURCES = od-xcoff.c - objdump_LDADD = $(OBJDUMP_PRIVATE_OFILES) $(OPCODES) $(LIBCTF) $(BFDLIB) $(LIBIBERTY) $(LIBINTL) $(DEBUGINFOD_LIBS) - cxxfilt_SOURCES = cxxfilt.c $(BULIBS) -@@ -1049,6 +1051,7 @@ distclean-compile: - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/deflex.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/defparse.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demanguse.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dlltool.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dllwrap.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf.Po@am__quote@ -diff --git a/binutils/demanguse.c b/binutils/demanguse.c -new file mode 100644 -index 00000000000..578a3ef56fe ---- /dev/null -+++ b/binutils/demanguse.c -@@ -0,0 +1,54 @@ -+/* demanguse.c -- libiberty demangler usage -+ Copyright (C) 2021 Free Software Foundation, Inc. -+ -+ This file is part of GNU Binutils. -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -+ 02110-1301, USA. */ -+ -+#include -+#include -+#include "demangle.h" -+#include "demanguse.h" -+ -+/* Print the list of demangling styles to STREAM. A one line MSG is -+ printed before the styles. Output is limited to 80 columns, with -+ continuation lines being indented by leading spaces in MSG. */ -+ -+void -+display_demangler_styles (FILE *stream, const char *msg) -+{ -+ const struct demangler_engine *info = libiberty_demanglers; -+ int col; -+ int lead_spaces = 0; -+ const char *cont = ""; -+ -+ while (msg[lead_spaces] == ' ') -+ ++lead_spaces; -+ col = fprintf (stream, "%s", msg); -+ while (info->demangling_style_name) -+ { -+ if (col + strlen (info->demangling_style_name) >= 75) -+ { -+ fprintf (stream, "%.1s\n", cont); -+ col = fprintf (stream, "%.*s", lead_spaces, msg); -+ cont = ""; -+ } -+ col += fprintf (stream, "%s\"%s\"", cont, info->demangling_style_name); -+ cont = ", "; -+ ++info; -+ } -+ fprintf (stream, "\n"); -+} -diff --git a/binutils/demanguse.h b/binutils/demanguse.h -new file mode 100644 -index 00000000000..965f116682d ---- /dev/null -+++ b/binutils/demanguse.h -@@ -0,0 +1,34 @@ -+/* demanguse.h -- libiberty demangler usage -+ Copyright (C) 2021 Free Software Foundation, Inc. -+ -+ This file is part of GNU Binutils. -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -+ 02110-1301, USA. */ -+ -+#ifndef DEMANGUSE_H -+#define DEMANGUSE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+void display_demangler_styles (FILE *, const char *); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* DEMANGUSE_H */ -diff --git a/binutils/nm.c b/binutils/nm.c -index acfdf665..854aafd6 100644 ---- a/binutils/nm.c -+++ b/binutils/nm.c -@@ -36,6 +36,7 @@ - #include "coff/internal.h" - #include "libcoff.h" - #include "bucomm.h" -+#include "demanguse.h" - #include "plugin-api.h" - #include "plugin.h" - -@@ -247,50 +248,87 @@ usage (FILE *stream, int status) - { - fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name); - fprintf (stream, _(" List symbols in [file(s)] (a.out by default).\n")); -- fprintf (stream, _(" The options are:\n\ -- -a, --debug-syms Display debugger-only symbols\n\ -- -A, --print-file-name Print name of the input file before every symbol\n\ -- -B Same as --format=bsd\n\ -- -C, --demangle[=STYLE] Decode low-level symbol names into user-level names\n\ -- The STYLE, if specified, can be `auto' (the default),\n\ -- `gnu', `lucid', `arm', `hp', `edg', `gnu-v3', `java'\n\ -- or `gnat'\n\ -- --no-demangle Do not demangle low-level symbol names\n\ -- --recurse-limit Enable a demangling recursion limit. This is the default.\n\ -- --no-recurse-limit Disable a demangling recursion limit.\n\ -- -D, --dynamic Display dynamic symbols instead of normal symbols\n\ -- --defined-only Display only defined symbols\n\ -- -e (ignored)\n\ -+ fprintf (stream, _(" The options are:\n")); -+ fprintf (stream, _("\ -+ -a, --debug-syms Display debugger-only symbols\n")); -+ fprintf (stream, _("\ -+ -A, --print-file-name Print name of the input file before every symbol\n")); -+ fprintf (stream, _("\ -+ -B Same as --format=bsd\n")); -+ fprintf (stream, _("\ -+ -C, --demangle[=STYLE] Decode mangled/processed symbol names\n")); -+ display_demangler_styles (stream, _("\ -+ STYLE can be ")); -+ fprintf (stream, _("\ -+ --no-demangle Do not demangle low-level symbol names\n")); -+ fprintf (stream, _("\ -+ --recurse-limit Enable a demangling recursion limit. (default)\n")); -+ fprintf (stream, _("\ -+ --no-recurse-limit Disable a demangling recursion limit.\n")); -+ fprintf (stream, _("\ -+ -D, --dynamic Display dynamic symbols instead of normal symbols\n")); -+ fprintf (stream, _("\ -+ --defined-only Display only defined symbols\n")); -+ fprintf (stream, _("\ -+ -e (ignored)\n")); -+ fprintf (stream, _("\ - -f, --format=FORMAT Use the output format FORMAT. FORMAT can be `bsd',\n\ -- `sysv' or `posix'. The default is `bsd'\n\ -- -g, --extern-only Display only external symbols\n\ -- --ifunc-chars=CHARS Characters to use when displaying ifunc symbols\n\ -+ `sysv', `posix' or 'just-symbols'.\n\ -+ The default is `bsd'\n")); -+ fprintf (stream, _("\ -+ -g, --extern-only Display only external symbols\n")); -+ fprintf (stream, _("\ -+ --ifunc-chars=CHARS Characters to use when displaying ifunc symbols\n")); -+ fprintf (stream, _("\ -+ -j, --just-symbols Same as --format=just-symbols\n")); -+ fprintf (stream, _("\ - -l, --line-numbers Use debugging information to find a filename and\n\ -- line number for each symbol\n\ -- -n, --numeric-sort Sort symbols numerically by address\n\ -- -o Same as -A\n\ -- -p, --no-sort Do not sort the symbols\n\ -- -P, --portability Same as --format=posix\n\ -+ line number for each symbol\n")); -+ fprintf (stream, _("\ -+ -n, --numeric-sort Sort symbols numerically by address\n")); -+ fprintf (stream, _("\ -+ -o Same as -A\n")); -+ fprintf (stream, _("\ -+ -p, --no-sort Do not sort the symbols\n")); -+ fprintf (stream, _("\ -+ -P, --portability Same as --format=posix\n")); -+ fprintf (stream, _("\ - -r, --reverse-sort Reverse the sense of the sort\n")); - #if BFD_SUPPORTS_PLUGINS - fprintf (stream, _("\ - --plugin NAME Load the specified plugin\n")); - #endif - fprintf (stream, _("\ -- -S, --print-size Print size of defined symbols\n\ -- -s, --print-armap Include index for symbols from archive members\n\ -- --size-sort Sort symbols by size\n\ -- --special-syms Include special symbols in the output\n\ -- --synthetic Display synthetic symbols as well\n\ -- -t, --radix=RADIX Use RADIX for printing symbol values\n\ -- --target=BFDNAME Specify the target object format as BFDNAME\n\ -- -u, --undefined-only Display only undefined symbols\n\ -- --with-symbol-versions Display version strings after symbol names\n\ -- -X 32_64 (ignored)\n\ -- @FILE Read options from FILE\n\ -- -h, --help Display this information\n\ -- -V, --version Display this program's version number\n\ --\n")); -+ -S, --print-size Print size of defined symbols\n")); -+ fprintf (stream, _("\ -+ -s, --print-armap Include index for symbols from archive members\n")); -+ fprintf (stream, _("\ -+ --quiet Suppress \"no symbols\" diagnostic\n")); -+ fprintf (stream, _("\ -+ --size-sort Sort symbols by size\n")); -+ fprintf (stream, _("\ -+ --special-syms Include special symbols in the output\n")); -+ fprintf (stream, _("\ -+ --synthetic Display synthetic symbols as well\n")); -+ fprintf (stream, _("\ -+ -t, --radix=RADIX Use RADIX for printing symbol values\n")); -+ fprintf (stream, _("\ -+ --target=BFDNAME Specify the target object format as BFDNAME\n")); -+ fprintf (stream, _("\ -+ -u, --undefined-only Display only undefined symbols\n")); -+ fprintf (stream, _("\ -+ --unicode={default|show|invalid|hex|escape|highlight}\n")); -+ fprintf (stream, _("\ -+ --with-symbol-versions Display version strings after symbol names\n")); -+ fprintf (stream, _("\ -+ -X 32_64 (ignored)\n")); -+ fprintf (stream, _("\ -+ @FILE Read options from FILE\n")); -+ fprintf (stream, _("\ -+ -h, --help Display this information\n")); -+ fprintf (stream, _("\ -+ -V, --version Display this program's version number\n")); -+ - list_supported_targets (program_name, stream); - if (REPORT_BUGS_TO[0] && status == 0) - fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO); -diff --git a/binutils/objdump.c b/binutils/objdump.c -index 2cd0d84c..09a91c04 100644 ---- a/binutils/objdump.c -+++ b/binutils/objdump.c -@@ -55,6 +55,7 @@ - #include "progress.h" - #include "bucomm.h" - #include "elfcomm.h" -+#include "demanguse.h" - #include "dwarf.h" - #include "ctf-api.h" - #include "getopt.h" -@@ -266,11 +267,12 @@ usage (FILE *stream, int status) - --file-start-context Include context from start of file (with -S)\n\ - -I, --include=DIR Add DIR to search list for source files\n\ - -l, --line-numbers Include line numbers and filenames in output\n\ -- -F, --file-offsets Include file offsets when displaying information\n\ -- -C, --demangle[=STYLE] Decode mangled/processed symbol names\n\ -- The STYLE, if specified, can be `auto', `gnu',\n\ -- `lucid', `arm', `hp', `edg', `gnu-v3', `java'\n\ -- or `gnat'\n\ -+ -F, --file-offsets Include file offsets when displaying information\n")); -+ fprintf (stream, _("\ -+ -C, --demangle[=STYLE] Decode mangled/processed symbol names\n")); -+ display_demangler_styles (stream, _("\ -+ STYLE can be ")); -+ fprintf (stream, _("\ - --recurse-limit Enable a limit on recursion whilst demangling. [Default]\n\ - --no-recurse-limit Disable a limit on recursion whilst demangling\n\ - -w, --wide Format output for more than 80 columns\n\ - diff --git a/binutils/po/POTFILES.in b/binutils/po/POTFILES.in -index 9a1443fbf19..376f1340c3f 100644 ---- a/binutils/po/POTFILES.in -+++ b/binutils/po/POTFILES.in -@@ -15,6 +15,8 @@ cxxfilt.c - debug.c - debug.c - debug.h -+demanguse.c -+demanguse.h - dlltool.c - dlltool.h - dllwrap.c -diff --git a/binutils/readelf.c b/binutils/readelf.c -index ad16b457..4c5351d9 100644 ---- a/binutils/readelf.c -+++ b/binutils/readelf.c -@@ -59,6 +59,7 @@ - #include "bfd.h" - #include "bucomm.h" - #include "elfcomm.h" -+#include "demanguse.h" - #include "dwarf.h" - #include "ctf-api.h" - #include "demangle.h" -@@ -4600,11 +4601,12 @@ usage (FILE * stream) - -s --syms Display the symbol table\n\ - --symbols An alias for --syms\n\ - --dyn-syms Display the dynamic symbol table\n\ -- --lto-syms Display LTO symbol tables\n\ -- -C --demangle[=STYLE] Decode low-level symbol names into user-level names\n\ -- The STYLE, if specified, can be `auto' (the default),\n\ -- `gnu', `lucid', `arm', `hp', `edg', `gnu-v3', `java'\n\ -- or `gnat'\n\ -+ --lto-syms Display LTO symbol tables\n")); -+ fprintf (stream, _("\ -+ -C --demangle[=STYLE] Decode mangled/processed symbol names\n")); -+ display_demangler_styles (stream, _("\ -+ STYLE can be ")); -+ fprintf (stream, _("\ - --no-demangle Do not demangle low-level symbol names. (This is the default)\n\ - --recurse-limit Enable a demangling recursion limit. (This is the default)\n\ - --no-recurse-limit Disable a demangling recursion limit\n\ --- -2.27.0 - diff --git a/backport-PR27345-binutils-arsup.c-lstat-not-available-on-all.patch b/backport-PR27345-binutils-arsup.c-lstat-not-available-on-all.patch deleted file mode 100644 index e3b0df1564d9032499fa4a55f87cc15bc2d2a9c2..0000000000000000000000000000000000000000 --- a/backport-PR27345-binutils-arsup.c-lstat-not-available-on-all.patch +++ /dev/null @@ -1,27 +0,0 @@ -From c180f095f32ca62f138da9bc7fb96cac0365fb5d Mon Sep 17 00:00:00 2001 -From: Alan Modra -Date: Fri, 5 Feb 2021 12:59:16 +1030 -Subject: [PATCH] PR27345, binutils/arsup.c: lstat() not available on all - targets - -We can just use stat here, the same as is done in ar.c:open_inarch. - - PR 27345 - * arsup.c (ar_save): Use stat rather than lstat. ---- - binutils/arsup.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/binutils/arsup.c b/binutils/arsup.c -index a60629f67618..fa7706f79e50 100644 ---- a/binutils/arsup.c -+++ b/binutils/arsup.c -@@ -357,7 +357,7 @@ ar_save (void) - #endif - bfd_close (obfd); - -- if (lstat (real_name, &target_stat) != 0) -+ if (stat (real_name, &target_stat) != 0) - { - /* The temp file created in ar_open has mode 0600 as per mkstemp. - Create the real empty output file here so smart_rename will diff --git a/backport-PR27349-ar-breaks-symlinks.patch b/backport-PR27349-ar-breaks-symlinks.patch deleted file mode 100644 index 67635ee08fc9734e9b255d0cdae0bdb2477ca723..0000000000000000000000000000000000000000 --- a/backport-PR27349-ar-breaks-symlinks.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 51a25252814f8b6f88ff5999a091e47ca1dbdeb9 Mon Sep 17 00:00:00 2001 -From: Alan Modra -Date: Fri, 5 Feb 2021 22:33:08 +1030 -Subject: [PATCH] PR27349, ar breaks symlinks - - PR 27349 - * rename.c (smart_rename): Test for existence and type of output - file with lstat. ---- - binutils/rename.c | 17 ++++++++++------- - 1 files changed, 10 insertions(+), 7 deletions(-) - -diff --git a/binutils/rename.c b/binutils/rename.c -index fece31179153..e36b75132ded 100644 ---- a/binutils/rename.c -+++ b/binutils/rename.c -@@ -179,7 +179,10 @@ smart_rename (const char *from, const char *to, int fd ATTRIBUTE_UNUSED, - int preserve_dates ATTRIBUTE_UNUSED) - { - int ret = 0; -- bfd_boolean exists = target_stat != NULL; -+ struct stat to_stat; -+ bfd_boolean exists; -+ -+ exists = lstat (to, &to_stat) == 0; - - #if defined (_WIN32) && !defined (__CYGWIN32__) - /* Win32, unlike unix, will not erase `to' in `rename(from, to)' but -@@ -214,16 +217,16 @@ smart_rename (const char *from, const char *to, int fd ATTRIBUTE_UNUSED, - external change. */ - if (! exists - || (fd >= 0 -- && !S_ISLNK (target_stat->st_mode) -- && S_ISREG (target_stat->st_mode) -- && (target_stat->st_mode & S_IWUSR) -- && target_stat->st_nlink == 1) -+ && !S_ISLNK (to_stat.st_mode) -+ && S_ISREG (to_stat.st_mode) -+ && (to_stat.st_mode & S_IWUSR) -+ && to_stat.st_nlink == 1) - ) - { - ret = rename (from, to); - if (ret == 0) - { -- if (exists) -+ if (exists && target_stat != NULL) - try_preserve_permissions (fd, target_stat); - } - else -@@ -239,7 +242,7 @@ smart_rename (const char *from, const char *to, int fd ATTRIBUTE_UNUSED, - if (ret != 0) - non_fatal (_("unable to copy file '%s'; reason: %s"), to, strerror (errno)); - -- if (preserve_dates) -+ if (preserve_dates && target_stat != NULL) - set_times (to, target_stat); - unlink (from); - } diff --git a/backport-PR27456-lstat-in-rename.c-on-MinGW.patch b/backport-PR27456-lstat-in-rename.c-on-MinGW.patch deleted file mode 100644 index d9a890db616b9e2b5c76d40cb524cf95e91a1415..0000000000000000000000000000000000000000 --- a/backport-PR27456-lstat-in-rename.c-on-MinGW.patch +++ /dev/null @@ -1,162 +0,0 @@ -From cca8873dd5a6015d5557ea44bc1ea9c252435a29 Mon Sep 17 00:00:00 2001 -From: Alan Modra -Date: Tue, 23 Feb 2021 09:37:39 +1030 -Subject: [PATCH] PR27456, lstat in rename.c on MinGW - - PR 27456 - * rename.c: Tidy throughout. - (smart_rename): Always copy. Remove windows specific code. ---- - binutils/rename.c | 111 ++++++++++++++------------------------------- - 1 file changed, 35 insertions(+), 76 deletions(-) - -diff --git a/binutils/rename.c b/binutils/rename.c -index 2ff092ee22b5..72a9323d72c4 100644 ---- a/binutils/rename.c -+++ b/binutils/rename.c -@@ -24,14 +24,9 @@ - - #ifdef HAVE_GOOD_UTIME_H - #include --#else /* ! HAVE_GOOD_UTIME_H */ --#ifdef HAVE_UTIMES -+#elif defined HAVE_UTIMES - #include --#endif /* HAVE_UTIMES */ --#endif /* ! HAVE_GOOD_UTIME_H */ -- --#if ! defined (_WIN32) || defined (__CYGWIN32__) --static int simple_copy (const char *, const char *); -+#endif - - /* The number of bytes to copy at once. */ - #define COPY_BUF 8192 -@@ -82,7 +77,6 @@ simple_copy (const char *from, const char *to) - } - return 0; - } --#endif /* __CYGWIN32__ or not _WIN32 */ - - /* Set the times of the file DESTINATION to be the same as those in - STATBUF. */ -@@ -91,87 +85,52 @@ void - set_times (const char *destination, const struct stat *statbuf) - { - int result; -- -- { - #ifdef HAVE_GOOD_UTIME_H -- struct utimbuf tb; -- -- tb.actime = statbuf->st_atime; -- tb.modtime = statbuf->st_mtime; -- result = utime (destination, &tb); --#else /* ! HAVE_GOOD_UTIME_H */ --#ifndef HAVE_UTIMES -- long tb[2]; -- -- tb[0] = statbuf->st_atime; -- tb[1] = statbuf->st_mtime; -- result = utime (destination, tb); --#else /* HAVE_UTIMES */ -- struct timeval tv[2]; -- -- tv[0].tv_sec = statbuf->st_atime; -- tv[0].tv_usec = 0; -- tv[1].tv_sec = statbuf->st_mtime; -- tv[1].tv_usec = 0; -- result = utimes (destination, tv); --#endif /* HAVE_UTIMES */ --#endif /* ! HAVE_GOOD_UTIME_H */ -- } -+ struct utimbuf tb; -+ -+ tb.actime = statbuf->st_atime; -+ tb.modtime = statbuf->st_mtime; -+ result = utime (destination, &tb); -+#elif defined HAVE_UTIMES -+ struct timeval tv[2]; -+ -+ tv[0].tv_sec = statbuf->st_atime; -+ tv[0].tv_usec = 0; -+ tv[1].tv_sec = statbuf->st_mtime; -+ tv[1].tv_usec = 0; -+ result = utimes (destination, tv); -+#else -+ long tb[2]; -+ -+ tb[0] = statbuf->st_atime; -+ tb[1] = statbuf->st_mtime; -+ result = utime (destination, tb); -+#endif - - if (result != 0) - non_fatal (_("%s: cannot set time: %s"), destination, strerror (errno)); - } - --/* Rename FROM to TO, copying if TO exists. TARGET_STAT has the file status -- that, if non-NULL, is used to fix up timestamps after rename. Return 0 if -- ok, -1 if error. */ -+/* Copy FROM to TO. TARGET_STAT has the file status that, if non-NULL, -+ is used to fix up timestamps. Return 0 if ok, -1 if error. -+ At one time this function renamed files, but file permissions are -+ tricky to update given the number of different schemes used by -+ various systems. So now we just copy. */ - - int - smart_rename (const char *from, const char *to, -- struct stat *target_stat ATTRIBUTE_UNUSED) -+ struct stat *target_stat) - { -- int ret = 0; -- struct stat to_stat; -- bfd_boolean exists; -- -- exists = lstat (to, &to_stat) == 0; -- --#if defined (_WIN32) && !defined (__CYGWIN32__) -- /* Win32, unlike unix, will not erase `to' in `rename(from, to)' but -- fail instead. Also, chown is not present. */ -- -- if (exists) -- remove (to); -+ int ret; - -- ret = rename (from, to); -+ ret = simple_copy (from, to); - if (ret != 0) -- { -- /* We have to clean up here. */ -- non_fatal (_("unable to rename '%s'; reason: %s"), to, strerror (errno)); -- unlink (from); -- } --#else -- /* Avoid a full copy and use rename if TO does not exist. */ -- if (!exists) -- { -- if ((ret = rename (from, to)) != 0) -- { -- /* We have to clean up here. */ -- non_fatal (_("unable to rename '%s'; reason: %s"), to, strerror (errno)); -- unlink (from); -- } -- } -- else -- { -- ret = simple_copy (from, to); -- if (ret != 0) -- non_fatal (_("unable to copy file '%s'; reason: %s"), to, strerror (errno)); -+ non_fatal (_("unable to copy file '%s'; reason: %s"), -+ to, strerror (errno)); - -- if (target_stat != NULL) -- set_times (to, target_stat); -- unlink (from); -- } --#endif /* _WIN32 && !__CYGWIN32__ */ -+ if (target_stat != NULL) -+ set_times (to, target_stat); -+ unlink (from); - - return ret; - } diff --git a/backport-Use-make_tempname-file-descriptor-in-smart_rename.patch b/backport-Use-make_tempname-file-descriptor-in-smart_rename.patch deleted file mode 100644 index 6da004d82db3a1babc5b9461bb0e789aec236aab..0000000000000000000000000000000000000000 --- a/backport-Use-make_tempname-file-descriptor-in-smart_rename.patch +++ /dev/null @@ -1,320 +0,0 @@ -From c42c71a1527dd70417d3966dce7ba9edbcf4bdb4 Mon Sep 17 00:00:00 2001 -From: Alan Modra -Date: Tue, 23 Feb 2021 12:10:58 +1030 -Subject: [PATCH] Use make_tempname file descriptor in smart_rename - -This patch makes use of the temp file descriptor in smart_rename -rather than reopening the file. I don't believe there is a security -issue in reopening the file, but this way is one less directory -operation. The patch also attempts to preserve S_ISUID and S_ISGID. - - PR 27456 - * bucomm.h (smart_rename): Update prototype. - * rename.c (smart_rename): Add fromfd and preserve_dates params. - Pass fromfd and target_stat to simple_copy. Call set_times - when preserve_dates. - (simple_copy): Accept fromfd rather than from filename. Add - target_stat param. Rewind fromfd rather than opening. Open - "to" file without O_CREAT. Try to preserve S_ISUID and S_ISGID. - * ar.c (write_archive): Rename ofd to tmpfd. Dup tmpfd before - closing output temp file, and pass tmpfd to smart_rename. - * arsup.c (temp_fd): Rename from real_fd. - (ar_save): Dup temp_fd and pass to smart_rename. - * objcopy.c (strip_main, copy_main): Likewise, and pass - preserve_dates. ---- - binutils/ar.c | 11 ++++++----- - binutils/arsup.c | 9 +++++---- - binutils/bucomm.h | 3 ++- - binutils/objcopy.c | 42 +++++++++++++++++++++++++++++++----------- - binutils/rename.c | 35 +++++++++++++++++++++-------------- - 5 files changed, 65 insertions(+), 35 deletions(-) - -diff --git a/binutils/ar.c b/binutils/ar.c -index 44df48c5c677..fb19b14fec57 100644 ---- a/binutils/ar.c -+++ b/binutils/ar.c -@@ -1252,21 +1252,21 @@ write_archive (bfd *iarch) - bfd *obfd; - char *old_name, *new_name; - bfd *contents_head = iarch->archive_next; -- int ofd = -1; -+ int tmpfd = -1; - - old_name = xstrdup (bfd_get_filename (iarch)); -- new_name = make_tempname (old_name, &ofd); -+ new_name = make_tempname (old_name, &tmpfd); - - if (new_name == NULL) - bfd_fatal (_("could not create temporary file whilst writing archive")); - - output_filename = new_name; - -- obfd = bfd_fdopenw (new_name, bfd_get_target (iarch), ofd); -+ obfd = bfd_fdopenw (new_name, bfd_get_target (iarch), tmpfd); - - if (obfd == NULL) - { -- close (ofd); -+ close (tmpfd); - bfd_fatal (old_name); - } - -@@ -1297,6 +1297,7 @@ write_archive (bfd *iarch) - if (!bfd_set_archive_head (obfd, contents_head)) - bfd_fatal (old_name); - -+ tmpfd = dup (tmpfd); - if (!bfd_close (obfd)) - bfd_fatal (old_name); - -@@ -1306,7 +1307,7 @@ write_archive (bfd *iarch) - /* We don't care if this fails; we might be creating the archive. */ - bfd_close (iarch); - -- if (smart_rename (new_name, old_name, NULL) != 0) -+ if (smart_rename (new_name, old_name, tmpfd, NULL, FALSE) != 0) - xexit (1); - free (old_name); - free (new_name); -diff --git a/binutils/arsup.c b/binutils/arsup.c -index f7ce8f0bc820..9982484dbe0c 100644 ---- a/binutils/arsup.c -+++ b/binutils/arsup.c -@@ -43,7 +43,7 @@ extern int deterministic; - static bfd *obfd; - static char *real_name; - static char *temp_name; --static int real_ofd; -+static int temp_fd; - static FILE *outfile; - - static void -@@ -152,7 +152,7 @@ void - ar_open (char *name, int t) - { - real_name = xstrdup (name); -- temp_name = make_tempname (real_name, &real_ofd); -+ temp_name = make_tempname (real_name, &temp_fd); - - if (temp_name == NULL) - { -@@ -162,7 +162,7 @@ ar_open (char *name, int t) - return; - } - -- obfd = bfd_fdopenw (temp_name, NULL, real_ofd); -+ obfd = bfd_fdopenw (temp_name, NULL, temp_fd); - - if (!obfd) - { -@@ -348,6 +348,7 @@ ar_save (void) - if (deterministic > 0) - obfd->flags |= BFD_DETERMINISTIC_OUTPUT; - -+ temp_fd = dup (temp_fd); - bfd_close (obfd); - - if (stat (real_name, &target_stat) != 0) -@@ -363,7 +364,7 @@ ar_save (void) - } - } - -- smart_rename (temp_name, real_name, NULL); -+ smart_rename (temp_name, real_name, temp_fd, NULL, FALSE); - obfd = 0; - free (temp_name); - free (real_name); -diff --git a/binutils/bucomm.h b/binutils/bucomm.h -index aa7e33d8cd15..f1ae47fa1b56 100644 ---- a/binutils/bucomm.h -+++ b/binutils/bucomm.h -@@ -71,7 +71,8 @@ extern void print_version (const char *); - /* In rename.c. */ - extern void set_times (const char *, const struct stat *); - --extern int smart_rename (const char *, const char *, struct stat *); -+extern int smart_rename (const char *, const char *, int, -+ struct stat *, bfd_boolean); - - - /* In libiberty. */ -diff --git a/binutils/objcopy.c b/binutils/objcopy.c -index abbcb7c51907..90ae0bd46bd0 100644 ---- a/binutils/objcopy.c -+++ b/binutils/objcopy.c -@@ -4837,6 +4837,7 @@ strip_main (int argc, char *argv[]) - struct stat statbuf; - char *tmpname; - int tmpfd = -1; -+ int copyfd = -1; - - if (get_file_size (argv[i]) < 1) - { -@@ -4846,7 +4847,11 @@ strip_main (int argc, char *argv[]) - - if (output_file == NULL - || filename_cmp (argv[i], output_file) == 0) -- tmpname = make_tempname (argv[i], &tmpfd); -+ { -+ tmpname = make_tempname (argv[i], &tmpfd); -+ if (tmpfd >= 0) -+ copyfd = dup (tmpfd); -+ } - else - tmpname = output_file; - -@@ -4864,14 +4869,18 @@ strip_main (int argc, char *argv[]) - if (status == 0) - { - if (output_file != tmpname) -- status = (smart_rename (tmpname, -- output_file ? output_file : argv[i], -- preserve_dates ? &statbuf : NULL) != 0); -+ status = smart_rename (tmpname, -+ output_file ? output_file : argv[i], -+ copyfd, &statbuf, preserve_dates) != 0; - if (status == 0) - status = hold_status; - } - else -- unlink_if_ordinary (tmpname); -+ { -+ if (copyfd >= 0) -+ close (copyfd); -+ unlink_if_ordinary (tmpname); -+ } - if (output_file != tmpname) - free (tmpname); - } -@@ -5078,7 +5087,9 @@ copy_main (int argc, char *argv[]) - bfd_boolean formats_info = FALSE; - bfd_boolean use_globalize = FALSE; - bfd_boolean use_keep_global = FALSE; -- int c, tmpfd = -1; -+ int c; -+ int tmpfd = -1; -+ int copyfd; - struct stat statbuf; - const bfd_arch_info_type *input_arch = NULL; - -@@ -5916,10 +5927,15 @@ copy_main (int argc, char *argv[]) - } - - /* If there is no destination file, or the source and destination files -- are the same, then create a temp and rename the result into the input. */ -+ are the same, then create a temp and copy the result into the input. */ -+ copyfd = -1; - if (output_filename == NULL - || filename_cmp (input_filename, output_filename) == 0) -- tmpname = make_tempname (input_filename, &tmpfd); -+ { -+ tmpname = make_tempname (input_filename, &tmpfd); -+ if (tmpfd >= 0) -+ copyfd = dup (tmpfd); -+ } - else - tmpname = output_filename; - -@@ -5934,11 +5950,15 @@ copy_main (int argc, char *argv[]) - if (status == 0) - { - if (tmpname != output_filename) -- status = (smart_rename (tmpname, input_filename, -- preserve_dates ? &statbuf : NULL) != 0); -+ status = smart_rename (tmpname, input_filename, copyfd, -+ &statbuf, preserve_dates) != 0; - } - else -- unlink_if_ordinary (tmpname); -+ { -+ if (copyfd >= 0) -+ close (copyfd); -+ unlink_if_ordinary (tmpname); -+ } - - if (tmpname != output_filename) - free (tmpname); -diff --git a/binutils/rename.c b/binutils/rename.c -index 72a9323d72c4..f688f350d51f 100644 ---- a/binutils/rename.c -+++ b/binutils/rename.c -@@ -31,24 +31,21 @@ - /* The number of bytes to copy at once. */ - #define COPY_BUF 8192 - --/* Copy file FROM to file TO, performing no translations. -+/* Copy file FROMFD to file TO, performing no translations. - Return 0 if ok, -1 if error. */ - - static int --simple_copy (const char *from, const char *to) -+simple_copy (int fromfd, const char *to, struct stat *target_stat) - { -- int fromfd, tofd, nread; -+ int tofd, nread; - int saved; - char buf[COPY_BUF]; - -- fromfd = open (from, O_RDONLY | O_BINARY); -- if (fromfd < 0) -+ if (fromfd < 0 -+ || lseek (fromfd, 0, SEEK_SET) != 0) - return -1; --#ifdef O_CREAT -- tofd = open (to, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, 0777); --#else -- tofd = creat (to, 0777); --#endif -+ -+ tofd = open (to, O_WRONLY | O_TRUNC | O_BINARY); - if (tofd < 0) - { - saved = errno; -@@ -56,6 +53,7 @@ simple_copy (const char *from, const char *to) - errno = saved; - return -1; - } -+ - while ((nread = read (fromfd, buf, sizeof buf)) > 0) - { - if (write (tofd, buf, nread) != nread) -@@ -67,7 +65,16 @@ simple_copy (const char *from, const char *to) - return -1; - } - } -+ - saved = errno; -+ -+#if !defined (_WIN32) || defined (__CYGWIN32__) -+ /* Writing to a setuid/setgid file may clear S_ISUID and S_ISGID. -+ Try to restore them, ignoring failure. */ -+ if (target_stat != NULL) -+ fchmod (tofd, target_stat->st_mode); -+#endif -+ - close (fromfd); - close (tofd); - if (nread < 0) -@@ -118,17 +125,17 @@ set_times (const char *destination, const struct stat *statbuf) - various systems. So now we just copy. */ - - int --smart_rename (const char *from, const char *to, -- struct stat *target_stat) -+smart_rename (const char *from, const char *to, int fromfd, -+ struct stat *target_stat, bfd_boolean preserve_dates) - { - int ret; - -- ret = simple_copy (from, to); -+ ret = simple_copy (fromfd, to, target_stat); - if (ret != 0) - non_fatal (_("unable to copy file '%s'; reason: %s"), - to, strerror (errno)); - -- if (target_stat != NULL) -+ if (preserve_dates) - set_times (to, target_stat); - unlink (from); - diff --git a/backport-binutils-Avoid-renaming-over-existing-files.patch b/backport-binutils-Avoid-renaming-over-existing-files.patch deleted file mode 100644 index ea6776c6eebfa2ee51daac967c735b0add15b8a0..0000000000000000000000000000000000000000 --- a/backport-binutils-Avoid-renaming-over-existing-files.patch +++ /dev/null @@ -1,353 +0,0 @@ -From 3685de750e6a091663a0abe42528cad29e960e35 Mon Sep 17 00:00:00 2001 -From: Siddhesh Poyarekar -Date: Fri, 19 Feb 2021 08:05:33 +0530 -Subject: [PATCH] binutils: Avoid renaming over existing files - -Renaming over existing files needs additional care to restore -permissions and ownership, which may not always succeed. -Additionally, other properties of the file such as extended attributes -may be lost, making the operation flaky. - -For predictable results, resort to rename() only if the file does not -exist, otherwise copy the file contents into the existing file. This -ensures that no additional tricks are needed to retain file -properties. - -This also allows dropping of the redundant set_times on the tmpfile in -objcopy/strip since now we no longer rename over existing files. - -binutils/ - - * ar.c (write_archive): Remove TARGET_STAT. Adjust call to - SMART_RENAME. - * arsup.c (ar_save): Likewise. - * objcopy (strip_main): Don't copy TMPFD. Don't set times on - temporary file and adjust call to SMART_RENAME. - (copy_main): Likewise. - * rename.c [!S_ISLNK]: Remove definitions. - (try_preserve_permissions): Remove function. - (smart_rename): Remove FD, PRESERVE_DATES arguments. Use - rename system call only if TO does not exist. - * bucomm.h (smart_rename): Adjust declaration. ---- - binutils/ar.c | 9 +---- - binutils/arsup.c | 13 +------ - binutils/bucomm.h | 2 +- - binutils/objcopy.c | 42 ++++---------------- - binutils/rename.c | 95 +++++----------------------------------------- - 5 files changed, 19 insertions(+), 142 deletions(-) - -diff --git a/binutils/ar.c b/binutils/ar.c -index 0ecfa3372281..44df48c5c677 100644 ---- a/binutils/ar.c -+++ b/binutils/ar.c -@@ -1253,7 +1253,6 @@ write_archive (bfd *iarch) - char *old_name, *new_name; - bfd *contents_head = iarch->archive_next; - int ofd = -1; -- struct stat target_stat; - - old_name = xstrdup (bfd_get_filename (iarch)); - new_name = make_tempname (old_name, &ofd); -@@ -1298,12 +1297,6 @@ write_archive (bfd *iarch) - if (!bfd_set_archive_head (obfd, contents_head)) - bfd_fatal (old_name); - --#if !defined (_WIN32) || defined (__CYGWIN32__) -- ofd = dup (ofd); --#endif -- if (ofd == -1 || bfd_stat (iarch, &target_stat) != 0) -- bfd_fatal (old_name); -- - if (!bfd_close (obfd)) - bfd_fatal (old_name); - -@@ -1313,7 +1306,7 @@ write_archive (bfd *iarch) - /* We don't care if this fails; we might be creating the archive. */ - bfd_close (iarch); - -- if (smart_rename (new_name, old_name, ofd, &target_stat, 0) != 0) -+ if (smart_rename (new_name, old_name, NULL) != 0) - xexit (1); - free (old_name); - free (new_name); -diff --git a/binutils/arsup.c b/binutils/arsup.c -index fa7706f79e50..f7ce8f0bc820 100644 ---- a/binutils/arsup.c -+++ b/binutils/arsup.c -@@ -343,18 +343,11 @@ ar_save (void) - } - else - { -- bfd_boolean skip_stat = FALSE; - struct stat target_stat; -- int ofd = real_ofd; - - if (deterministic > 0) - obfd->flags |= BFD_DETERMINISTIC_OUTPUT; - --#if !defined (_WIN32) || defined (__CYGWIN32__) -- /* It's OK to fail; at worst it will result in SMART_RENAME using a slow -- copy fallback to write the output. */ -- ofd = dup (ofd); --#endif - bfd_close (obfd); - - if (stat (real_name, &target_stat) != 0) -@@ -363,9 +356,6 @@ ar_save (void) - Create the real empty output file here so smart_rename will - update the mode according to the process umask. */ - obfd = bfd_openw (real_name, NULL); -- if (obfd == NULL -- || bfd_stat (obfd, &target_stat) != 0) -- skip_stat = TRUE; - if (obfd != NULL) - { - bfd_set_format (obfd, bfd_archive); -@@ -373,8 +363,7 @@ ar_save (void) - } - } - -- smart_rename (temp_name, real_name, ofd, -- skip_stat ? NULL : &target_stat, 0); -+ smart_rename (temp_name, real_name, NULL); - obfd = 0; - free (temp_name); - free (real_name); -diff --git a/binutils/bucomm.h b/binutils/bucomm.h -index 7a0adfae5659..aa7e33d8cd15 100644 ---- a/binutils/bucomm.h -+++ b/binutils/bucomm.h -@@ -71,7 +71,7 @@ extern void print_version (const char *); - /* In rename.c. */ - extern void set_times (const char *, const struct stat *); - --extern int smart_rename (const char *, const char *, int, struct stat *, int); -+extern int smart_rename (const char *, const char *, struct stat *); - - - /* In libiberty. */ -diff --git a/binutils/objcopy.c b/binutils/objcopy.c -index 54a59430f1b4..abbcb7c51907 100644 ---- a/binutils/objcopy.c -+++ b/binutils/objcopy.c -@@ -4837,7 +4837,6 @@ strip_main (int argc, char *argv[]) - struct stat statbuf; - char *tmpname; - int tmpfd = -1; -- int copyfd = -1; - - if (get_file_size (argv[i]) < 1) - { -@@ -4851,12 +4850,7 @@ strip_main (int argc, char *argv[]) - else - tmpname = output_file; - -- if (tmpname == NULL --#if !defined (_WIN32) || defined (__CYGWIN32__) -- /* Retain a copy of TMPFD since we will need it for SMART_RENAME. */ -- || (tmpfd >= 0 && (copyfd = dup (tmpfd)) == -1) --#endif -- ) -+ if (tmpname == NULL) - { - bfd_nonfatal_message (argv[i], NULL, NULL, - _("could not create temporary file to hold stripped copy")); -@@ -4869,23 +4863,15 @@ strip_main (int argc, char *argv[]) - output_target, NULL); - if (status == 0) - { -- if (preserve_dates) -- set_times (tmpname, &statbuf); - if (output_file != tmpname) - status = (smart_rename (tmpname, - output_file ? output_file : argv[i], -- copyfd, &statbuf, preserve_dates) != 0); -+ preserve_dates ? &statbuf : NULL) != 0); - if (status == 0) - status = hold_status; - } - else -- { --#if !defined (_WIN32) || defined (__CYGWIN32__) -- if (copyfd >= 0) -- close (copyfd); --#endif -- unlink_if_ordinary (tmpname); -- } -+ unlink_if_ordinary (tmpname); - if (output_file != tmpname) - free (tmpname); - } -@@ -5093,7 +5079,6 @@ copy_main (int argc, char *argv[]) - bfd_boolean use_globalize = FALSE; - bfd_boolean use_keep_global = FALSE; - int c, tmpfd = -1; -- int copyfd = -1; - struct stat statbuf; - const bfd_arch_info_type *input_arch = NULL; - -@@ -5938,12 +5923,7 @@ copy_main (int argc, char *argv[]) - else - tmpname = output_filename; - -- if (tmpname == NULL --#if !defined (_WIN32) || defined (__CYGWIN32__) -- /* Retain a copy of TMPFD since we will need it for SMART_RENAME. */ -- || (tmpfd >= 0 && (copyfd = dup (tmpfd)) == -1) --#endif -- ) -+ if (tmpname == NULL) - { - fatal (_("warning: could not create temporary file whilst copying '%s', (error: %s)"), - input_filename, strerror (errno)); -@@ -5953,20 +5933,12 @@ copy_main (int argc, char *argv[]) - output_target, input_arch); - if (status == 0) - { -- if (preserve_dates) -- set_times (tmpname, &statbuf); - if (tmpname != output_filename) -- status = (smart_rename (tmpname, input_filename, copyfd, &statbuf, -- preserve_dates) != 0); -+ status = (smart_rename (tmpname, input_filename, -+ preserve_dates ? &statbuf : NULL) != 0); - } - else -- { --#if !defined (_WIN32) || defined (__CYGWIN32__) -- if (copyfd >= 0) -- close (copyfd); --#endif -- unlink_if_ordinary (tmpname); -- } -+ unlink_if_ordinary (tmpname); - - if (tmpname != output_filename) - free (tmpname); -diff --git a/binutils/rename.c b/binutils/rename.c -index e36b75132ded..2ff092ee22b5 100644 ---- a/binutils/rename.c -+++ b/binutils/rename.c -@@ -122,61 +122,13 @@ set_times (const char *destination, const struct stat *statbuf) - non_fatal (_("%s: cannot set time: %s"), destination, strerror (errno)); - } - --#ifndef S_ISLNK --#ifdef S_IFLNK --#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) --#else --#define S_ISLNK(m) 0 --#define lstat stat --#endif --#endif -- --#if !defined (_WIN32) || defined (__CYGWIN32__) --/* Try to preserve the permission bits and ownership of an existing file when -- rename overwrites it. FD is the file being renamed and TARGET_STAT has the -- status of the file that was overwritten. */ --static void --try_preserve_permissions (int fd, struct stat *target_stat) --{ -- struct stat from_stat; -- int ret = 0; -- -- if (fstat (fd, &from_stat) != 0) -- return; -- -- int from_mode = from_stat.st_mode & 0777; -- int to_mode = target_stat->st_mode & 0777; -- -- /* Fix up permissions before we potentially lose ownership with fchown. -- Clear the setxid bits because in case the fchown below fails then we don't -- want to end up with a sxid file owned by the invoking user. If the user -- hasn't changed or if fchown succeeded, we add back the sxid bits at the -- end. */ -- if (from_mode != to_mode) -- fchmod (fd, to_mode); -- -- /* Fix up ownership, this will clear the setxid bits. */ -- if (from_stat.st_uid != target_stat->st_uid -- || from_stat.st_gid != target_stat->st_gid) -- ret = fchown (fd, target_stat->st_uid, target_stat->st_gid); -- -- /* Fix up the sxid bits if either the fchown wasn't needed or it -- succeeded. */ -- if (ret == 0) -- fchmod (fd, target_stat->st_mode & 07777); --} --#endif -- --/* Rename FROM to TO, copying if TO is either a link or is not a regular file. -- FD is an open file descriptor pointing to FROM that we can use to safely fix -- up permissions of the file after renaming. TARGET_STAT has the file status -- that is used to fix up permissions and timestamps after rename. Return 0 if -- ok, -1 if error and FD is closed before returning. */ -+/* Rename FROM to TO, copying if TO exists. TARGET_STAT has the file status -+ that, if non-NULL, is used to fix up timestamps after rename. Return 0 if -+ ok, -1 if error. */ - - int --smart_rename (const char *from, const char *to, int fd ATTRIBUTE_UNUSED, -- struct stat *target_stat ATTRIBUTE_UNUSED, -- int preserve_dates ATTRIBUTE_UNUSED) -+smart_rename (const char *from, const char *to, -+ struct stat *target_stat ATTRIBUTE_UNUSED) - { - int ret = 0; - struct stat to_stat; -@@ -199,37 +151,10 @@ smart_rename (const char *from, const char *to, int fd ATTRIBUTE_UNUSED, - unlink (from); - } - #else -- /* Avoid a full copy and use rename if we can fix up permissions of the -- file after renaming, i.e.: -- -- - TO is not a symbolic link -- - TO is a regular file with only one hard link -- - We have permission to write to TO -- - FD is available to safely fix up permissions to be the same as the file -- we overwrote with the rename. -- -- Note though that the actual file on disk that TARGET_STAT describes may -- have changed and we're only trying to preserve the status we know about. -- At no point do we try to interact with the new file changes, so there can -- only be two outcomes, i.e. either the external file change survives -- without knowledge of our change (if it happens after the rename syscall) -- or our rename and permissions fixup survive without any knowledge of the -- external change. */ -- if (! exists -- || (fd >= 0 -- && !S_ISLNK (to_stat.st_mode) -- && S_ISREG (to_stat.st_mode) -- && (to_stat.st_mode & S_IWUSR) -- && to_stat.st_nlink == 1) -- ) -+ /* Avoid a full copy and use rename if TO does not exist. */ -+ if (!exists) - { -- ret = rename (from, to); -- if (ret == 0) -- { -- if (exists && target_stat != NULL) -- try_preserve_permissions (fd, target_stat); -- } -- else -+ if ((ret = rename (from, to)) != 0) - { - /* We have to clean up here. */ - non_fatal (_("unable to rename '%s'; reason: %s"), to, strerror (errno)); -@@ -242,12 +167,10 @@ smart_rename (const char *from, const char *to, int fd ATTRIBUTE_UNUSED, - if (ret != 0) - non_fatal (_("unable to copy file '%s'; reason: %s"), to, strerror (errno)); - -- if (preserve_dates && target_stat != NULL) -+ if (target_stat != NULL) - set_times (to, target_stat); - unlink (from); - } -- if (fd >= 0) -- close (fd); - #endif /* _WIN32 && !__CYGWIN32__ */ - - return ret; diff --git a/binutils-2.36.1.tar.xz b/binutils-2.37.tar.xz similarity index 69% rename from binutils-2.36.1.tar.xz rename to binutils-2.37.tar.xz index 5172b1d85408903c38e497fe754369ebc572eee5..03742902dfa1664eed5be3d51eadac9b950002ad 100644 Binary files a/binutils-2.36.1.tar.xz and b/binutils-2.37.tar.xz differ diff --git a/binutils.spec b/binutils.spec index 90e55be23385cc7b15e95705b0de7188bfb4de4b..9e3d2784b02994108528f5f5ff9ea4731e33816a 100644 --- a/binutils.spec +++ b/binutils.spec @@ -1,7 +1,7 @@ Summary: Binary utilities Name: binutils -Version: 2.36.1 -Release: 4 +Version: 2.37 +Release: 1 License: GPLv3+ URL: https://sourceware.org/binutils @@ -25,17 +25,10 @@ Patch3: binutils-2.27-aarch64-ifunc.patch Patch4: CVE-2019-1010204.patch Patch5: Fix-a-potential-use-of-an-uninitialised-value-in-the.patch -Patch6: backport-0003-CVE-2021-20197.patch -Patch7: backport-Fix-a-build-problem-when-using-FreeBSD-12.patch -Patch8: backport-0004-CVE-2021-20197.patch -Patch9: backport-CVE-2021-3549.patch -Patch10: backport-PR27345-binutils-arsup.c-lstat-not-available-on-all.patch -Patch11: backport-PR27349-ar-breaks-symlinks.patch -Patch12: backport-binutils-Avoid-renaming-over-existing-files.patch -Patch13: backport-PR27456-lstat-in-rename.c-on-MinGW.patch -Patch14: backport-Use-make_tempname-file-descriptor-in-smart_rename.patch -Patch15: backport-Fix-demangle-style-usage-info.patch -Patch16: backport-CVE-2021-45078.patch +Patch6: backport-CVE-2021-45078.patch +Patch7: backport-0001-CVE-2021-42574.patch +Patch8: backport-0002-CVE-2021-42574.patch +Patch9: backport-0003-CVE-2021-42574.patch Provides: bundled(libiberty) @@ -349,6 +342,12 @@ fi %{_infodir}/bfd*info* %changelog +* Wed Jan 19 2022 panxiaohe - 2.37-1 +- Type:enhancement +- ID:CVE-2021-42574 +- SUG:NA +- DESC:update to 2.37 and fix CVE-2021-42574 + * Fri Dec 24 2021 yangzhuangzhuang - 2.36.1-4 - Type:CVE - ID:CVE-2021-45078 diff --git a/export-demangle.h-in-devel-package.patch b/export-demangle.h-in-devel-package.patch index 3e6223a2f4e07d4ba61b7090115b413aa586a139..489fe1f8a8601453b92e69f8cd0234c1563ed206 100644 --- a/export-demangle.h-in-devel-package.patch +++ b/export-demangle.h-in-devel-package.patch @@ -16,8 +16,8 @@ index 6a39ef5..ddc3b54 100644 bfdincludedir = @bfdincludedir@ bfdlib_LTLIBRARIES = libbfd.la bfdinclude_HEADERS = $(BFD_H) $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h \ -- bfd_stdint.h $(INCDIR)/diagnostics.h $(INCDIR)/bfdlink.h -+ bfd_stdint.h $(INCDIR)/diagnostics.h $(INCDIR)/bfdlink.h $(INCDIR)/demangle.h +- $(INCDIR)/diagnostics.h $(INCDIR)/bfdlink.h ++ $(INCDIR)/diagnostics.h $(INCDIR)/bfdlink.h $(INCDIR)/demangle.h else !INSTALL_LIBBFD # Empty these so that the respective installation directories will not be created. bfdlibdir = @@ -28,7 +28,7 @@ index 80499d6..09a93b9 100644 @@ -249,7 +249,7 @@ am__can_run_installinfo = \ esac am__bfdinclude_HEADERS_DIST = $(INCDIR)/plugin-api.h bfd.h \ - $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h bfd_stdint.h \ + $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h \ - $(INCDIR)/diagnostics.h $(INCDIR)/bfdlink.h + $(INCDIR)/diagnostics.h $(INCDIR)/bfdlink.h $(INCDIR)/demangle.h HEADERS = $(bfdinclude_HEADERS) @@ -38,8 +38,8 @@ index 80499d6..09a93b9 100644 @INSTALL_LIBBFD_FALSE@bfdinclude_HEADERS = $(am__append_2) @INSTALL_LIBBFD_TRUE@bfdinclude_HEADERS = $(BFD_H) \ @INSTALL_LIBBFD_TRUE@ $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h \ --@INSTALL_LIBBFD_TRUE@ bfd_stdint.h $(INCDIR)/diagnostics.h \ -+@INSTALL_LIBBFD_TRUE@ bfd_stdint.h $(INCDIR)/diagnostics.h $(INCDIR)/demangle.h \ +-@INSTALL_LIBBFD_TRUE@ $(INCDIR)/diagnostics.h \ ++@INSTALL_LIBBFD_TRUE@ $(INCDIR)/diagnostics.h $(INCDIR)/demangle.h \ @INSTALL_LIBBFD_TRUE@ $(INCDIR)/bfdlink.h $(am__append_2) @INSTALL_LIBBFD_FALSE@rpath_bfdlibdir = @bfdlibdir@ @INSTALL_LIBBFD_FALSE@noinst_LTLIBRARIES = libbfd.la