diff options
Diffstat (limited to 'binutils')
-rw-r--r-- | binutils/doc/binutils.texi | 8 | ||||
-rw-r--r-- | binutils/nm.c | 29 | ||||
-rw-r--r-- | binutils/objcopy.c | 5 | ||||
-rw-r--r-- | binutils/resbin.c | 768 | ||||
-rw-r--r-- | binutils/rescoff.c | 262 | ||||
-rw-r--r-- | binutils/resrc.c | 9 | ||||
-rw-r--r-- | binutils/resres.c | 42 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/nm-coff-1.s | 26 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/nm-coff-sdef-1.s | 26 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/nm.exp | 6 | ||||
-rw-r--r-- | binutils/windres.c | 30 | ||||
-rw-r--r-- | binutils/windres.h | 6 |
12 files changed, 855 insertions, 362 deletions
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index b291670..c74526e 100644 --- a/binutils/doc/binutils.texi +++ b/binutils/doc/binutils.texi @@ -2701,6 +2701,14 @@ but the result again may not be as you expect. For RISC-V, the following options are supported: @table @code +@item max +Disassemble without checking architecture string. This is a best effort mode, so +for overlapping ISA extensions the first match (possibly incorrect in a given +context) will be used to decode the instruction. It's useful, if the ELF file +doesn't expose ISA string, preventing automatic ISA subset deduction, and the +default fallback ISA string (@code{rv64gc}) doesn't cover all instructions in +the binary. + @item numeric Print numeric register names, rather than ABI names (e.g., print @code{x2} instead of @code{sp}). diff --git a/binutils/nm.c b/binutils/nm.c index 4e86057..7ef5d61 100644 --- a/binutils/nm.c +++ b/binutils/nm.c @@ -79,7 +79,15 @@ struct extended_symbol_info #define SYM_STAB_DESC(sym) (sym->sinfo->stab_desc) #define SYM_STAB_OTHER(sym) (sym->sinfo->stab_other) #define SYM_SIZE(sym) \ - (sym->elfinfo ? sym->elfinfo->internal_elf_sym.st_size: sym->ssize) + (sym->elfinfo \ + && sym->elfinfo->internal_elf_sym.st_size \ + ? sym->elfinfo->internal_elf_sym.st_size \ + : sym->coffinfo \ + && ISFCN (sym->coffinfo->native->u.syment.n_type) \ + && sym->coffinfo->native->u.syment.n_numaux \ + && sym->coffinfo->native[1].u.auxent.x_sym.x_misc.x_fsize \ + ? sym->coffinfo->native[1].u.auxent.x_sym.x_misc.x_fsize \ + : sym->ssize) /* The output formatting functions. */ static void print_object_filename_bsd (const char *); @@ -1036,9 +1044,9 @@ size_forward2 (const void *P_x, const void *P_y) return sorters[0][reverse_sort] (x->minisym, y->minisym); } -/* Sort the symbols by size. ELF provides a size but for other formats - we have to make a guess by assuming that the difference between the - address of a symbol and the address of the next higher symbol is the +/* Sort the symbols by size. ELF and COFF may provide a size but for other + formats we have to make a guess by assuming that the difference between + the address of a symbol and the address of the next higher symbol is the size. */ static long @@ -1081,6 +1089,8 @@ sort_symbols_by_size (bfd *abfd, bool is_dynamic, void *minisyms, asection *sec; bfd_vma sz; asymbol *temp; + const elf_symbol_type *elfsym; + const coff_symbol_type *coffsym; if (from + size < fromend) { @@ -1100,8 +1110,15 @@ sort_symbols_by_size (bfd *abfd, bool is_dynamic, void *minisyms, we can't rely on that information for the symbol size. Ditto for bfd/section.c:global_syms like *ABS*. */ if ((sym->flags & (BSF_SECTION_SYM | BSF_SYNTHETIC)) == 0 - && bfd_get_flavour (abfd) == bfd_target_elf_flavour) - sz = ((elf_symbol_type *) sym)->internal_elf_sym.st_size; + && (elfsym = elf_symbol_from (sym)) != NULL + && elfsym->internal_elf_sym.st_size != 0) + sz = elfsym->internal_elf_sym.st_size; + else if ((sym->flags & (BSF_SECTION_SYM | BSF_SYNTHETIC)) == 0 + && (coffsym = coff_symbol_from (sym)) != NULL + && ISFCN (coffsym->native->u.syment.n_type) + && coffsym->native->u.syment.n_numaux != 0 + && coffsym->native[1].u.auxent.x_sym.x_misc.x_fsize != 0) + sz = coffsym->native[1].u.auxent.x_sym.x_misc.x_fsize; else if ((sym->flags & (BSF_SECTION_SYM | BSF_SYNTHETIC)) == 0 && bfd_is_com_section (sec)) sz = sym->value; diff --git a/binutils/objcopy.c b/binutils/objcopy.c index 5048648..31933e1 100644 --- a/binutils/objcopy.c +++ b/binutils/objcopy.c @@ -5943,6 +5943,11 @@ copy_main (int argc, char *argv[]) case OPTION_FILE_ALIGNMENT: pe_file_alignment = parse_vma (optarg, "--file-alignment"); + if (power_of_two (pe_file_alignment) == -1) + { + non_fatal (_("--file-alignment argument is not a power of two: %s - ignoring"), optarg); + pe_file_alignment = (bfd_vma) -1; + } break; case OPTION_HEAP: diff --git a/binutils/resbin.c b/binutils/resbin.c index 388b016..98dd68b 100644 --- a/binutils/resbin.c +++ b/binutils/resbin.c @@ -54,8 +54,8 @@ static rc_res_resource *bin_to_res_group_cursor (windres_bfd *, const bfd_byte * static rc_res_resource *bin_to_res_group_icon (windres_bfd *, const bfd_byte *, rc_uint_type); static rc_res_resource *bin_to_res_version (windres_bfd *, const bfd_byte *, rc_uint_type); static rc_res_resource *bin_to_res_userdata (windres_bfd *, const bfd_byte *, rc_uint_type); -static rc_res_resource *bin_to_res_toolbar (windres_bfd *, const bfd_byte *); -static void get_version_header (windres_bfd *, const bfd_byte *, rc_uint_type, const char *, +static rc_res_resource *bin_to_res_toolbar (windres_bfd *, const bfd_byte *, rc_uint_type); +static bool get_version_header (windres_bfd *, const bfd_byte *, rc_uint_type, const char *, unichar **, rc_uint_type *, rc_uint_type *, rc_uint_type *, rc_uint_type *); @@ -105,7 +105,7 @@ bin_to_res (windres_bfd *wrbfd, rc_res_id type, const bfd_byte *data, case RT_VERSION: return bin_to_res_version (wrbfd, data, length); case RT_TOOLBAR: - return bin_to_res_toolbar (wrbfd, data); + return bin_to_res_toolbar (wrbfd, data, length); } } @@ -116,7 +116,7 @@ bin_to_res (windres_bfd *wrbfd, rc_res_id type, const bfd_byte *data, static void toosmall (const char *msg) { - fatal (_("%s: not enough binary data"), msg); + non_fatal (_("%s: not enough binary data"), msg); } /* Swap in a NULL terminated unicode string. */ @@ -132,13 +132,16 @@ get_unicode (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length, while (1) { if (length < c * 2 + 2) - toosmall (_("null terminated unicode string")); + { + toosmall (_("null terminated unicode string")); + return NULL; + } if (windres_get_16 (wrbfd, data + c * 2, 2) == 0) break; ++c; } - ret = (unichar *) res_alloc ((c + 1) * sizeof (unichar)); + ret = res_alloc ((c + 1) * sizeof (unichar)); for (i = 0; i < c; i++) ret[i] = windres_get_16 (wrbfd, data + i * 2, 2); @@ -159,13 +162,19 @@ get_resid (windres_bfd *wrbfd, rc_res_id *id, const bfd_byte *data, rc_uint_type first; if (length < 2) - toosmall (_("resource ID")); + { + toosmall (_("resource ID")); + return -1; + } first = windres_get_16 (wrbfd, data, 2); if (first == 0xffff) { if (length < 4) - toosmall (_("resource ID")); + { + toosmall (_("resource ID")); + return -1; + } id->named = 0; id->u.id = windres_get_16 (wrbfd, data + 2, 2); return 4; @@ -174,6 +183,8 @@ get_resid (windres_bfd *wrbfd, rc_res_id *id, const bfd_byte *data, { id->named = 1; id->u.n.name = get_unicode (wrbfd, data, length, &id->u.n.length); + if (id->u.n.name == NULL) + return -1; return id->u.n.length * 2 + 2; } } @@ -187,7 +198,7 @@ bin_to_res_generic (windres_bfd *wrbfd ATTRIBUTE_UNUSED, enum rc_res_type type, { rc_res_resource *r; - r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource)); + r = res_alloc (sizeof (rc_res_resource)); r->type = type; r->u.data.data = data; r->u.data.length = length; @@ -204,15 +215,18 @@ bin_to_res_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length rc_res_resource *r; if (length < 4) - toosmall (_("cursor")); + { + toosmall (_("cursor")); + return NULL; + } - c = (rc_cursor *) res_alloc (sizeof (rc_cursor)); + c = res_alloc (sizeof (rc_cursor)); c->xhotspot = windres_get_16 (wrbfd, data, 2); c->yhotspot = windres_get_16 (wrbfd, data + 2, 2); c->length = length - 4; c->data = data + 4; - r = (rc_res_resource *) res_alloc (sizeof *r); + r = res_alloc (sizeof *r); r->type = RES_TYPE_CURSOR; r->u.cursor = c; @@ -228,39 +242,58 @@ bin_to_res_menu (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) rc_menu *m; rc_uint_type version, got; - r = (rc_res_resource *) res_alloc (sizeof *r); + r = res_alloc (sizeof *r); r->type = RES_TYPE_MENU; - m = (rc_menu *) res_alloc (sizeof (rc_menu)); + m = res_alloc (sizeof (rc_menu)); r->u.menu = m; if (length < 2) - toosmall (_("menu header")); + { + toosmall (_("menu header")); + return NULL; + } version = windres_get_16 (wrbfd, data, 2); if (version == 0) { if (length < 4) - toosmall (_("menu header")); + { + toosmall (_("menu header")); + return NULL; + } m->help = 0; m->items = bin_to_res_menuitems (wrbfd, data + 4, length - 4, &got); + if (m->items == NULL) + return NULL; } else if (version == 1) { rc_uint_type offset; if (length < 8) - toosmall (_("menuex header")); + { + toosmall (_("menuex header")); + return NULL; + } m->help = windres_get_32 (wrbfd, data + 4, 4); offset = windres_get_16 (wrbfd, data + 2, 2); if (offset + 4 >= length) - toosmall (_("menuex offset")); + { + toosmall (_("menuex offset")); + return NULL; + } m->items = bin_to_res_menuexitems (wrbfd, data + 4 + offset, length - (4 + offset), &got); + if (m->items == NULL) + return NULL; } else - fatal (_("unsupported menu version %d"), (int) version); + { + non_fatal (_("unsupported menu version %d"), (int) version); + return NULL; + } return r; } @@ -268,8 +301,8 @@ bin_to_res_menu (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) /* Convert menu items from binary. */ static rc_menuitem * -bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length, - rc_uint_type *got) +bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, + rc_uint_type length, rc_uint_type *got) { rc_menuitem *first, **pp; @@ -285,9 +318,12 @@ bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type len rc_menuitem *mi; if (length < 4) - toosmall (_("menuitem header")); + { + toosmall (_("menuitem header")); + return NULL; + } - mi = (rc_menuitem *) res_alloc (sizeof *mi); + mi = res_alloc (sizeof *mi); mi->state = 0; mi->help = 0; @@ -300,7 +336,10 @@ bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type len stroff = 2; if (length < stroff + 2) - toosmall (_("menuitem header")); + { + toosmall (_("menuitem header")); + return NULL; + } if (windres_get_16 (wrbfd, data + stroff, 2) == 0) { @@ -308,7 +347,11 @@ bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type len mi->text = NULL; } else - mi->text = get_unicode (wrbfd, data + stroff, length - stroff, &slen); + { + mi->text = get_unicode (wrbfd, data + stroff, length - stroff, &slen); + if (mi->text == NULL) + return NULL; + } itemlen = stroff + slen * 2 + 2; @@ -322,8 +365,10 @@ bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type len rc_uint_type subread; mi->id = 0; - mi->popup = bin_to_res_menuitems (wrbfd, data + itemlen, length - itemlen, - &subread); + mi->popup = bin_to_res_menuitems (wrbfd, data + itemlen, + length - itemlen, &subread); + if (mi->popup == NULL) + return NULL; itemlen += subread; } @@ -345,8 +390,8 @@ bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type len /* Convert menuex items from binary. */ static rc_menuitem * -bin_to_res_menuexitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length, - rc_uint_type *got) +bin_to_res_menuexitems (windres_bfd *wrbfd, const bfd_byte *data, + rc_uint_type length, rc_uint_type *got) { rc_menuitem *first, **pp; @@ -362,9 +407,12 @@ bin_to_res_menuexitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type l rc_menuitem *mi; if (length < 16) - toosmall (_("menuitem header")); + { + toosmall (_("menuitem header")); + return NULL; + } - mi = (rc_menuitem *) res_alloc (sizeof (rc_menuitem)); + mi = res_alloc (sizeof (rc_menuitem)); mi->type = windres_get_32 (wrbfd, data, 4); mi->state = windres_get_32 (wrbfd, data + 4, 4); mi->id = windres_get_32 (wrbfd, data + 8, 4); @@ -377,7 +425,11 @@ bin_to_res_menuexitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type l mi->text = NULL; } else - mi->text = get_unicode (wrbfd, data + 14, length - 14, &slen); + { + mi->text = get_unicode (wrbfd, data + 14, length - 14, &slen); + if (mi->text == NULL) + return NULL; + } itemlen = 14 + slen * 2 + 2; itemlen = (itemlen + 3) &~ 3; @@ -392,12 +444,17 @@ bin_to_res_menuexitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type l rc_uint_type subread; if (length < itemlen + 4) - toosmall (_("menuitem")); + { + toosmall (_("menuitem")); + return NULL; + } mi->help = windres_get_32 (wrbfd, data + itemlen, 4); itemlen += 4; mi->popup = bin_to_res_menuexitems (wrbfd, data + itemlen, length - itemlen, &subread); + if (mi->popup == NULL) + return NULL; itemlen += subread; } @@ -424,14 +481,18 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length rc_uint_type signature; rc_dialog *d; rc_uint_type c, sublen, i; + int ilen; rc_uint_type off; rc_dialog_control **pp; rc_res_resource *r; if (length < 18) - toosmall (_("dialog header")); + { + toosmall (_("dialog header")); + return NULL; + } - d = (rc_dialog *) res_alloc (sizeof (rc_dialog)); + d = res_alloc (sizeof (rc_dialog)); signature = windres_get_16 (wrbfd, data + 2, 2); if (signature != 0xffff) @@ -447,9 +508,12 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length version = windres_get_16 (wrbfd, data, 2); if (version != 1) - fatal (_("unexpected DIALOGEX version %d"), version); + { + non_fatal (_("unexpected DIALOGEX version %d"), version); + return NULL; + } - d->ex = (rc_dialog_ex *) res_alloc (sizeof (rc_dialog_ex)); + d->ex = res_alloc (sizeof (rc_dialog_ex)); d->ex->help = windres_get_32 (wrbfd, data + 4, 4); d->exstyle = windres_get_32 (wrbfd, data + 8, 4); d->style = windres_get_32 (wrbfd, data + 12, 4); @@ -457,7 +521,10 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length } if (length < off + 10) - toosmall (_("dialog header")); + { + toosmall (_("dialog header")); + return NULL; + } c = windres_get_16 (wrbfd, data + off, 2); d->x = windres_get_16 (wrbfd, data + off + 2, 2); @@ -467,13 +534,19 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length off += 10; - sublen = get_resid (wrbfd, &d->menu, data + off, length - off); - off += sublen; + ilen = get_resid (wrbfd, &d->menu, data + off, length - off); + if (ilen == -1) + return NULL; + off += ilen; - sublen = get_resid (wrbfd, &d->class, data + off, length - off); - off += sublen; + ilen = get_resid (wrbfd, &d->class, data + off, length - off); + if (ilen == -1) + return NULL; + off += ilen; d->caption = get_unicode (wrbfd, data + off, length - off, &sublen); + if (d->caption == NULL) + return NULL; off += sublen * 2 + 2; if (sublen == 0) d->caption = NULL; @@ -492,7 +565,10 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length else { if (length < off + 2) - toosmall (_("dialog font point size")); + { + toosmall (_("dialog font point size")); + return NULL; + } d->pointsize = windres_get_16 (wrbfd, data + off, 2); off += 2; @@ -500,7 +576,10 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length if (d->ex != NULL) { if (length < off + 4) - toosmall (_("dialogex font information")); + { + toosmall (_("dialogex font information")); + return NULL; + } d->ex->weight = windres_get_16 (wrbfd, data + off, 2); d->ex->italic = windres_get_8 (wrbfd, data + off + 2, 1); d->ex->charset = windres_get_8 (wrbfd, data + off + 3, 1); @@ -508,6 +587,8 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length } d->font = get_unicode (wrbfd, data + off, length - off, &sublen); + if (d->font == NULL) + return NULL; off += sublen * 2 + 2; } @@ -521,12 +602,15 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length off = (off + 3) &~ 3; - dc = (rc_dialog_control *) res_alloc (sizeof (rc_dialog_control)); + dc = res_alloc (sizeof (rc_dialog_control)); if (d->ex == NULL) { if (length < off + 8) - toosmall (_("dialog control")); + { + toosmall (_("dialog control")); + return NULL; + } dc->style = windres_get_32 (wrbfd, data + off, 4); dc->exstyle = windres_get_32 (wrbfd, data + off + 4, 4); @@ -536,7 +620,10 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length else { if (length < off + 12) - toosmall (_("dialogex control")); + { + toosmall (_("dialogex control")); + return NULL; + } dc->help = windres_get_32 (wrbfd, data + off, 4); dc->exstyle = windres_get_32 (wrbfd, data + off + 4, 4); dc->style = windres_get_32 (wrbfd, data + off + 8, 4); @@ -544,7 +631,10 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length } if (length < off + (d->ex != NULL ? 2 : 0) + 10) - toosmall (_("dialog control")); + { + toosmall (_("dialog control")); + return NULL; + } dc->x = windres_get_16 (wrbfd, data + off, 2); dc->y = windres_get_16 (wrbfd, data + off + 2, 2); @@ -558,14 +648,21 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length off += 10 + (d->ex != NULL ? 2 : 0); - sublen = get_resid (wrbfd, &dc->class, data + off, length - off); - off += sublen; + ilen = get_resid (wrbfd, &dc->class, data + off, length - off); + if (ilen == -1) + return NULL; + off += ilen; - sublen = get_resid (wrbfd, &dc->text, data + off, length - off); - off += sublen; + ilen = get_resid (wrbfd, &dc->text, data + off, length - off); + if (ilen == -1) + return NULL; + off += ilen; if (length < off + 2) - toosmall (_("dialog control end")); + { + toosmall (_("dialog control end")); + return NULL; + } datalen = windres_get_16 (wrbfd, data + off, 2); off += 2; @@ -575,10 +672,12 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length else { if (length < off + datalen) - toosmall (_("dialog control data")); + { + toosmall (_("dialog control data")); + return NULL; + } - dc->data = ((rc_rcdata_item *) - res_alloc (sizeof (rc_rcdata_item))); + dc->data = res_alloc (sizeof (rc_rcdata_item)); dc->data->next = NULL; dc->data->type = RCDATA_BUFFER; dc->data->u.buffer.length = datalen; @@ -592,7 +691,7 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length pp = &dc->next; } - r = (rc_res_resource *) res_alloc (sizeof *r); + r = res_alloc (sizeof *r); r->type = RES_TYPE_DIALOG; r->u.dialog = d; @@ -608,14 +707,17 @@ bin_to_res_string (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length int i; rc_res_resource *r; - st = (rc_stringtable *) res_alloc (sizeof (rc_stringtable)); + st = res_alloc (sizeof (rc_stringtable)); for (i = 0; i < 16; i++) { unsigned int slen; if (length < 2) - toosmall (_("stringtable string length")); + { + toosmall (_("stringtable string length")); + return NULL; + } slen = windres_get_16 (wrbfd, data, 2); st->strings[i].length = slen; @@ -625,9 +727,12 @@ bin_to_res_string (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length unsigned int j; if (length < 2 + 2 * slen) - toosmall (_("stringtable string")); + { + toosmall (_("stringtable string")); + return NULL; + } - s = (unichar *) res_alloc (slen * sizeof (unichar)); + s = res_alloc (slen * sizeof (unichar)); st->strings[i].string = s; for (j = 0; j < slen; j++) @@ -638,7 +743,7 @@ bin_to_res_string (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length length -= 2 + 2 * slen; } - r = (rc_res_resource *) res_alloc (sizeof *r); + r = res_alloc (sizeof *r); r->type = RES_TYPE_STRINGTABLE; r->u.stringtable = st; @@ -648,14 +753,18 @@ bin_to_res_string (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length /* Convert a fontdir resource from binary. */ static rc_res_resource * -bin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) +bin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, + rc_uint_type length) { rc_uint_type c, i; rc_fontdir *first, **pp; rc_res_resource *r; if (length < 2) - toosmall (_("fontdir header")); + { + toosmall (_("fontdir header")); + return NULL; + } c = windres_get_16 (wrbfd, data, 2); @@ -669,10 +778,13 @@ bin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt unsigned int off; if (length < 56) - toosmall (_("fontdir")); + { + toosmall (_("fontdir")); + return NULL; + } bfi = (const struct bin_fontdir_item *) data; - fd = (rc_fontdir *) res_alloc (sizeof *fd); + fd = res_alloc (sizeof *fd); fd->index = windres_get_16 (wrbfd, bfi->index, 2); /* To work out the length of the fontdir data, we must get the @@ -686,13 +798,19 @@ bin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt while (off < length && data[off] != '\0') ++off; if (off >= length) - toosmall (_("fontdir device name")); + { + toosmall (_("fontdir device name")); + return NULL; + } ++off; while (off < length && data[off] != '\0') ++off; if (off >= length) - toosmall (_("fontdir face name")); + { + toosmall (_("fontdir face name")); + return NULL; + } ++off; fd->length = off; @@ -709,7 +827,7 @@ bin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt length -= off; } - r = (rc_res_resource *) res_alloc (sizeof *r); + r = res_alloc (sizeof *r); r->type = RES_TYPE_FONTDIR; r->u.fontdir = first; @@ -719,7 +837,8 @@ bin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt /* Convert an accelerators resource from binary. */ static rc_res_resource * -bin_to_res_accelerators (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) +bin_to_res_accelerators (windres_bfd *wrbfd, const bfd_byte *data, + rc_uint_type length) { rc_accelerator *first, **pp; rc_res_resource *r; @@ -732,9 +851,12 @@ bin_to_res_accelerators (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type rc_accelerator *a; if (length < 8) - toosmall (_("accelerator")); + { + toosmall (_("accelerator")); + return NULL; + } - a = (rc_accelerator *) res_alloc (sizeof (rc_accelerator)); + a = res_alloc (sizeof (rc_accelerator)); a->flags = windres_get_16 (wrbfd, data, 2); a->key = windres_get_16 (wrbfd, data + 2, 2); @@ -751,7 +873,7 @@ bin_to_res_accelerators (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length -= 8; } - r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource)); + r = res_alloc (sizeof (rc_res_resource)); r->type = RES_TYPE_ACCELERATOR; r->u.acc = first; @@ -767,14 +889,14 @@ bin_to_res_rcdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data, rc_rcdata_item *ri; rc_res_resource *r; - ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item)); + ri = res_alloc (sizeof (rc_rcdata_item)); ri->next = NULL; ri->type = RCDATA_BUFFER; ri->u.buffer.length = length; ri->u.buffer.data = data; - r = (rc_res_resource *) res_alloc (sizeof *r); + r = res_alloc (sizeof *r); r->type = rctyp; r->u.rcdata = ri; @@ -784,18 +906,25 @@ bin_to_res_rcdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data, /* Convert a group cursor resource from binary. */ static rc_res_resource * -bin_to_res_group_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) +bin_to_res_group_cursor (windres_bfd *wrbfd, const bfd_byte *data, + rc_uint_type length) { int type, c, i; rc_group_cursor *first, **pp; rc_res_resource *r; if (length < 6) - toosmall (_("group cursor header")); + { + toosmall (_("group cursor header")); + return NULL; + } type = windres_get_16 (wrbfd, data + 2, 2); if (type != 2) - fatal (_("unexpected group cursor type %d"), type); + { + non_fatal (_("unexpected group cursor type %d"), type); + return NULL; + } c = windres_get_16 (wrbfd, data + 4, 2); @@ -810,9 +939,12 @@ bin_to_res_group_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type rc_group_cursor *gc; if (length < 14) - toosmall (_("group cursor")); + { + toosmall (_("group cursor")); + return NULL; + } - gc = (rc_group_cursor *) res_alloc (sizeof *gc); + gc = res_alloc (sizeof *gc); gc->width = windres_get_16 (wrbfd, data, 2); gc->height = windres_get_16 (wrbfd, data + 2, 2); @@ -829,7 +961,7 @@ bin_to_res_group_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length -= 14; } - r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource)); + r = res_alloc (sizeof (rc_res_resource)); r->type = RES_TYPE_GROUP_CURSOR; r->u.group_cursor = first; @@ -839,18 +971,25 @@ bin_to_res_group_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type /* Convert a group icon resource from binary. */ static rc_res_resource * -bin_to_res_group_icon (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) +bin_to_res_group_icon (windres_bfd *wrbfd, const bfd_byte *data, + rc_uint_type length) { int type, c, i; rc_group_icon *first, **pp; rc_res_resource *r; if (length < 6) - toosmall (_("group icon header")); + { + toosmall (_("group icon header")); + return NULL; + } type = windres_get_16 (wrbfd, data + 2, 2); if (type != 1) - fatal (_("unexpected group icon type %d"), type); + { + non_fatal (_("unexpected group icon type %d"), type); + return NULL; + } c = windres_get_16 (wrbfd, data + 4, 2); @@ -865,9 +1004,12 @@ bin_to_res_group_icon (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type le rc_group_icon *gi; if (length < 14) - toosmall (_("group icon")); + { + toosmall (_("group icon")); + return NULL; + } - gi = (rc_group_icon *) res_alloc (sizeof (rc_group_icon)); + gi = res_alloc (sizeof (rc_group_icon)); gi->width = windres_get_8 (wrbfd, data, 1); gi->height = windres_get_8 (wrbfd, data + 1, 1); @@ -885,7 +1027,7 @@ bin_to_res_group_icon (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type le length -= 14; } - r = (rc_res_resource *) res_alloc (sizeof *r); + r = res_alloc (sizeof *r); r->type = RES_TYPE_GROUP_ICON; r->u.group_icon = first; @@ -897,14 +1039,17 @@ bin_to_res_group_icon (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type le sets *LEN to the total length, *VALLEN to the value length, *TYPE to the type, and *OFF to the offset to the children. */ -static void -get_version_header (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length, - const char *key, unichar **pkey, +static bool +get_version_header (windres_bfd *wrbfd, const bfd_byte *data, + rc_uint_type length, const char *key, unichar **pkey, rc_uint_type *len, rc_uint_type *vallen, rc_uint_type *type, rc_uint_type *off) { if (length < 8) - toosmall (key); + { + toosmall (key); + return false; + } *len = (windres_get_16 (wrbfd, data, 2) + 3) & ~3; *vallen = windres_get_16 (wrbfd, data + 2, 2); @@ -920,6 +1065,8 @@ get_version_header (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt rc_uint_type sublen; *pkey = get_unicode (wrbfd, data, length, &sublen); + if (*pkey == NULL) + return false; *off += (sublen + 1) * sizeof (unichar); } else @@ -927,9 +1074,15 @@ get_version_header (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt while (1) { if (length < 2) - toosmall (key); + { + toosmall (key); + return false; + } if (windres_get_16 (wrbfd, data, 2) != (bfd_byte) *key) - fatal (_("unexpected version string")); + { + non_fatal (_("unexpected version string")); + return false; + } *off += 2; length -= 2; @@ -943,12 +1096,14 @@ get_version_header (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt } *off = (*off + 3) &~ 3; + return true; } /* Convert a version resource from binary. */ static rc_res_resource * -bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) +bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, + rc_uint_type length) { rc_uint_type verlen, vallen, type, off; rc_fixed_versioninfo *fi; @@ -956,18 +1111,26 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt rc_versioninfo *v; rc_res_resource *r; - get_version_header (wrbfd, data, length, "VS_VERSION_INFO", - (unichar **) NULL, &verlen, &vallen, &type, &off); + if (!get_version_header (wrbfd, data, length, "VS_VERSION_INFO", + (unichar **) NULL, &verlen, &vallen, &type, &off)) + return NULL; /* PR 17512: The verlen field does not include padding length. */ if (verlen > length) - fatal (_("version length %lu greater than resource length %lu"), - (unsigned long) verlen, (unsigned long) length); + { + non_fatal (_("version length %lu greater than resource length %lu"), + (unsigned long) verlen, (unsigned long) length); + return NULL; + } if (type != 0) - fatal (_("unexpected version type %d"), (int) type); + { + non_fatal (_("unexpected version type %d"), (int) type); + return NULL; + } - /* PR 27686: Ignore any padding bytes after the end of the version structure. */ + /* PR 27686: Ignore any padding bytes after the end of the version + structure. */ length = verlen; data += off; @@ -980,20 +1143,33 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt unsigned long signature, fiv; if (vallen != 52) - fatal (_("unexpected fixed version information length %ld"), (long) vallen); + { + non_fatal (_("unexpected fixed version information length %ld"), + (long) vallen); + return NULL; + } if (length < 52) - toosmall (_("fixed version info")); + { + toosmall (_("fixed version info")); + return NULL; + } signature = windres_get_32 (wrbfd, data, 4); if (signature != 0xfeef04bd) - fatal (_("unexpected fixed version signature %lu"), signature); + { + non_fatal (_("unexpected fixed version signature %lu"), signature); + return NULL; + } fiv = windres_get_32 (wrbfd, data + 4, 4); if (fiv != 0 && fiv != 0x10000) - fatal (_("unexpected fixed version info version %lu"), fiv); + { + non_fatal (_("unexpected fixed version info version %lu"), fiv); + return NULL; + } - fi = (rc_fixed_versioninfo *) res_alloc (sizeof (rc_fixed_versioninfo)); + fi = res_alloc (sizeof (rc_fixed_versioninfo)); fi->file_version_ms = windres_get_32 (wrbfd, data + 8, 4); fi->file_version_ls = windres_get_32 (wrbfd, data + 12, 4); @@ -1020,9 +1196,12 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt int ch; if (length < 8) - toosmall (_("version var info")); + { + toosmall (_("version var info")); + return NULL; + } - vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info)); + vi = res_alloc (sizeof (rc_ver_info)); ch = windres_get_16 (wrbfd, data + 6, 2); @@ -1032,12 +1211,17 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt vi->type = VERINFO_STRING; - get_version_header (wrbfd, data, length, "StringFileInfo", - (unichar **) NULL, &verlen, &vallen, &type, - &off); + if (!get_version_header (wrbfd, data, length, "StringFileInfo", + (unichar **) NULL, &verlen, &vallen, &type, + &off)) + return NULL; if (vallen != 0) - fatal (_("unexpected stringfileinfo value length %ld"), (long) vallen); + { + non_fatal (_("unexpected stringfileinfo value length %ld"), + (long) vallen); + return NULL; + } data += off; length -= off; @@ -1054,66 +1238,88 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt rc_ver_stringinfo **ppvs; if (length < 8) - toosmall (_("version stringtable")); + { + toosmall (_("version stringtable")); + return NULL; + } - vst = (rc_ver_stringtable *) res_alloc (sizeof (rc_ver_stringtable)); + vst = res_alloc (sizeof (rc_ver_stringtable)); - get_version_header (wrbfd, data, length, (const char *) NULL, - &vst->language, &stverlen, &vallen, &type, &off); + if (!get_version_header (wrbfd, data, length, (const char *) NULL, + &vst->language, &stverlen, &vallen, + &type, &off)) + return NULL; if (vallen != 0) - fatal (_("unexpected version stringtable value length %ld"), (long) vallen); + { + non_fatal (_("unexpected version stringtable value length %ld"), + (long) vallen); + return NULL; + } data += off; length -= off; verlen -= off; - stverlen -= off; - - vst->strings = NULL; - ppvs = &vst->strings; - - while (stverlen > 0) - { - rc_ver_stringinfo *vs; - rc_uint_type sverlen, vslen, valoff; - - if (length < 8) - toosmall (_("version string")); - - vs = (rc_ver_stringinfo *) res_alloc (sizeof (rc_ver_stringinfo)); - - get_version_header (wrbfd, data, length, (const char *) NULL, - &vs->key, &sverlen, &vallen, &type, &off); - - data += off; - length -= off; - - vs->value = get_unicode (wrbfd, data, length, &vslen); - valoff = vslen * 2 + 2; - valoff = (valoff + 3) & ~3; - - if (off + valoff != sverlen) - fatal (_("unexpected version string length %ld != %ld + %ld"), - (long) sverlen, (long) off, (long) valoff); - - data += valoff; - length -= valoff; - - if (stverlen < sverlen) - fatal (_("unexpected version string length %ld < %ld"), - (long) verlen, (long) sverlen); - stverlen -= sverlen; - verlen -= sverlen; - - vs->next = NULL; - *ppvs = vs; - ppvs = &vs->next; - } - - vst->next = NULL; - *ppvst = vst; - ppvst = &vst->next; + stverlen -= off; + + vst->strings = NULL; + ppvs = &vst->strings; + + while (stverlen > 0) + { + rc_ver_stringinfo *vs; + rc_uint_type sverlen, vslen, valoff; + + if (length < 8) + { + toosmall (_("version string")); + return NULL; + } + + vs = res_alloc (sizeof (rc_ver_stringinfo)); + + if (!get_version_header (wrbfd, data, length, + (const char *) NULL, &vs->key, + &sverlen, &vallen, &type, &off)) + return NULL; + + data += off; + length -= off; + + vs->value = get_unicode (wrbfd, data, length, &vslen); + if (vs->value == NULL) + return NULL; + valoff = vslen * 2 + 2; + valoff = (valoff + 3) & ~3; + + if (off + valoff != sverlen) + { + non_fatal (_("unexpected version string length %ld != %ld + %ld"), + (long) sverlen, (long) off, (long) valoff); + return NULL; + } + + data += valoff; + length -= valoff; + + if (stverlen < sverlen) + { + non_fatal (_("unexpected version string length %ld < %ld"), + (long) verlen, (long) sverlen); + return NULL; + } + stverlen -= sverlen; + verlen -= sverlen; + + vs->next = NULL; + *ppvs = vs; + ppvs = &vs->next; + } + + vst->next = NULL; + *ppvst = vst; + ppvst = &vst->next; } } else if (ch == 'V') @@ -1122,18 +1328,25 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt vi->type = VERINFO_VAR; - get_version_header (wrbfd, data, length, "VarFileInfo", - (unichar **) NULL, &verlen, &vallen, &type, - &off); + if (!get_version_header (wrbfd, data, length, "VarFileInfo", + (unichar **) NULL, &verlen, &vallen, + &type, &off)) + return NULL; if (vallen != 0) - fatal (_("unexpected varfileinfo value length %ld"), (long) vallen); + { + non_fatal (_("unexpected varfileinfo value length %ld"), + (long) vallen); + return NULL; + } data += off; length -= off; - get_version_header (wrbfd, data, length, (const char *) NULL, - &vi->u.var.key, &verlen, &vallen, &type, &off); + if (!get_version_header (wrbfd, data, length, (const char *) NULL, + &vi->u.var.key, &verlen, &vallen, + &type, &off)) + return NULL; data += off; length -= off; @@ -1146,9 +1359,12 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt rc_ver_varinfo *vv; if (length < 4) - toosmall (_("version varfileinfo")); + { + toosmall (_("version varfileinfo")); + return NULL; + } - vv = (rc_ver_varinfo *) res_alloc (sizeof (rc_ver_varinfo)); + vv = res_alloc (sizeof (rc_ver_varinfo)); vv->language = windres_get_16 (wrbfd, data, 2); vv->charset = windres_get_16 (wrbfd, data + 2, 2); @@ -1161,7 +1377,11 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt length -= 4; if (vallen < 4) - fatal (_("unexpected version value length %ld"), (long) vallen); + { + non_fatal (_("unexpected version value length %ld"), + (long) vallen); + return NULL; + } vallen -= 4; } @@ -1171,21 +1391,25 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt if (length == 8) /* Padding - skip. */ break; - fatal (_("nul bytes found in version string")); + non_fatal (_("nul bytes found in version string")); + return NULL; } else - fatal (_("unexpected version string character: %x"), ch); + { + non_fatal (_("unexpected version string character: %x"), ch); + return NULL; + } vi->next = NULL; *pp = vi; pp = &vi->next; } - v = (rc_versioninfo *) res_alloc (sizeof (rc_versioninfo)); + v = res_alloc (sizeof (rc_versioninfo)); v->fixed = fi; v->var = first; - r = (rc_res_resource *) res_alloc (sizeof *r); + r = res_alloc (sizeof *r); r->type = RES_TYPE_VERSIONINFO; r->u.versioninfo = v; @@ -1201,14 +1425,14 @@ bin_to_res_userdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data, rc_rcdata_item *ri; rc_res_resource *r; - ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item)); + ri = res_alloc (sizeof (rc_rcdata_item)); ri->next = NULL; ri->type = RCDATA_BUFFER; ri->u.buffer.length = length; ri->u.buffer.data = data; - r = (rc_res_resource *) res_alloc (sizeof *r); + r = res_alloc (sizeof *r); r->type = RES_TYPE_USERDATA; r->u.rcdata = ri; @@ -1216,38 +1440,51 @@ bin_to_res_userdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data, } static rc_res_resource * -bin_to_res_toolbar (windres_bfd *wrbfd, const bfd_byte *data) +bin_to_res_toolbar (windres_bfd *wrbfd, const bfd_byte *data, + rc_uint_type length) { rc_toolbar *ri; rc_res_resource *r; rc_uint_type i; - ri = (rc_toolbar *) res_alloc (sizeof (rc_toolbar)); + if (length < 12) + { + toosmall (_("toolbar")); + return NULL; + } + ri = res_alloc (sizeof (rc_toolbar)); ri->button_width = windres_get_32 (wrbfd, data, 4); ri->button_height = windres_get_32 (wrbfd, data + 4, 4); ri->nitems = windres_get_32 (wrbfd, data + 8, 4); ri->items = NULL; data += 12; - for (i=0 ; i < ri->nitems; i++) - { - rc_toolbar_item *it; - it = (rc_toolbar_item *) res_alloc (sizeof (rc_toolbar_item)); - it->id.named = 0; - it->id.u.id = (int) windres_get_32 (wrbfd, data, 4); - it->prev = it->next = NULL; - data += 4; - if(ri->items) { - rc_toolbar_item *ii = ri->items; - while (ii->next != NULL) - ii = ii->next; - it->prev = ii; - ii->next = it; - } - else - ri->items = it; - } - r = (rc_res_resource *) res_alloc (sizeof *r); + length -= 12; + for (i = 0; i < ri->nitems; i++) + { + rc_toolbar_item *it; + it = res_alloc (sizeof (rc_toolbar_item)); + it->id.named = 0; + if (length < 4) + { + toosmall (_("toolbar item")); + return NULL; + } + it->id.u.id = (int) windres_get_32 (wrbfd, data, 4); + it->prev = it->next = NULL; + data += 4; + length -= 4; + if(ri->items) { + rc_toolbar_item *ii = ri->items; + while (ii->next != NULL) + ii = ii->next; + it->prev = ii; + ii->next = it; + } + else + ri->items = it; + } + r = res_alloc (sizeof *r); r->type = RES_TYPE_TOOLBAR; r->u.toolbar = ri; return r; @@ -1286,7 +1523,8 @@ res_to_bin (windres_bfd *wrbfd, rc_uint_type off, const rc_res_resource *res) case RES_TYPE_FONT: case RES_TYPE_ICON: case RES_TYPE_MESSAGETABLE: - return res_to_bin_generic (wrbfd, off, res->u.data.length, res->u.data.data); + return res_to_bin_generic (wrbfd, off, res->u.data.length, + res->u.data.data); case RES_TYPE_ACCELERATOR: return res_to_bin_accelerator (wrbfd, off, res->u.acc); case RES_TYPE_CURSOR: @@ -1337,13 +1575,13 @@ resid_to_bin (windres_bfd *wrbfd, rc_uint_type off, rc_res_id id) rc_uint_type len = (id.u.n.name ? unichar_len (id.u.n.name) : 0); if (wrbfd) { - bfd_byte *d = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar)); + bfd_byte *d = reswr_alloc ((len + 1) * sizeof (unichar)); rc_uint_type i; for (i = 0; i < len; i++) windres_put_16 (wrbfd, d + (i * sizeof (unichar)), id.u.n.name[i]); windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0); set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar)); - } + } off += (rc_uint_type) ((len + 1) * sizeof (unichar)); } return off; @@ -1364,7 +1602,7 @@ unicode_to_bin (windres_bfd *wrbfd, rc_uint_type off, const unichar *str) { bfd_byte *d; rc_uint_type i; - d = (bfd_byte *) reswr_alloc ( (len + 1) * sizeof (unichar)); + d = reswr_alloc ((len + 1) * sizeof (unichar)); for (i = 0; i < len; i++) windres_put_16 (wrbfd, d + (i * sizeof (unichar)), str[i]); windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0); @@ -1389,12 +1627,13 @@ res_to_bin_accelerator (windres_bfd *wrbfd, rc_uint_type off, { struct bin_accelerator ba; - windres_put_16 (wrbfd, ba.flags, a->flags | (a->next != NULL ? 0 : ACC_LAST)); + windres_put_16 (wrbfd, ba.flags, + a->flags | (a->next != NULL ? 0 : ACC_LAST)); windres_put_16 (wrbfd, ba.key, a->key); windres_put_16 (wrbfd, ba.id, a->id); windres_put_16 (wrbfd, ba.pad, 0); set_windres_bfd_content (wrbfd, &ba, off, BIN_ACCELERATOR_SIZE); - } + } off += BIN_ACCELERATOR_SIZE; } return off; @@ -1413,7 +1652,8 @@ res_to_bin_cursor (windres_bfd *wrbfd, rc_uint_type off, const rc_cursor *c) windres_put_16 (wrbfd, bc.yhotspot, c->yhotspot); set_windres_bfd_content (wrbfd, &bc, off, BIN_CURSOR_SIZE); if (c->length) - set_windres_bfd_content (wrbfd, c->data, off + BIN_CURSOR_SIZE, c->length); + set_windres_bfd_content (wrbfd, c->data, off + BIN_CURSOR_SIZE, + c->length); } off = (off + BIN_CURSOR_SIZE + (rc_uint_type) c->length); return off; @@ -1443,8 +1683,9 @@ res_to_bin_group_cursor (windres_bfd *wrbfd, rc_uint_type off, windres_put_16 (wrbfd, bgci.bits, gc->bits); windres_put_32 (wrbfd, bgci.bytes, gc->bytes); windres_put_16 (wrbfd, bgci.index, gc->index); - set_windres_bfd_content (wrbfd, &bgci, off, BIN_GROUP_CURSOR_ITEM_SIZE); - } + set_windres_bfd_content (wrbfd, &bgci, off, + BIN_GROUP_CURSOR_ITEM_SIZE); + } off += BIN_GROUP_CURSOR_ITEM_SIZE; } @@ -1477,17 +1718,17 @@ res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog if (wrbfd) { - if (! dialogex) - { + if (! dialogex) + { windres_put_32 (wrbfd, bd.style, dialog->style); windres_put_32 (wrbfd, bd.exstyle, dialog->exstyle); windres_put_16 (wrbfd, bd.x, dialog->x); windres_put_16 (wrbfd, bd.y, dialog->y); windres_put_16 (wrbfd, bd.width, dialog->width); windres_put_16 (wrbfd, bd.height, dialog->height); - } - else - { + } + else + { windres_put_16 (wrbfd, bdx.sig1, 1); windres_put_16 (wrbfd, bdx.sig2, 0xffff); windres_put_32 (wrbfd, bdx.help, (dialog->ex ? dialog->ex->help : 0)); @@ -1520,9 +1761,12 @@ res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog { struct bin_dialogexfont bdxf; windres_put_16 (wrbfd, bdxf.pointsize, dialog->pointsize); - windres_put_16 (wrbfd, bdxf.weight, (dialog->ex == NULL ? 0 : dialog->ex->weight)); - windres_put_8 (wrbfd, bdxf.italic, (dialog->ex == NULL ? 0 : dialog->ex->italic)); - windres_put_8 (wrbfd, bdxf.charset, (dialog->ex == NULL ? 1 : dialog->ex->charset)); + windres_put_16 (wrbfd, bdxf.weight, + dialog->ex == NULL ? 0 : dialog->ex->weight); + windres_put_8 (wrbfd, bdxf.italic, + dialog->ex == NULL ? 0 : dialog->ex->italic); + windres_put_8 (wrbfd, bdxf.charset, + dialog->ex == NULL ? 1 : dialog->ex->charset); set_windres_bfd_content (wrbfd, &bdxf, off, BIN_DIALOGEXFONT_SIZE); } } @@ -1536,8 +1780,8 @@ res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog off += (4 - ((off - off_delta) & 3)) & 3; if (wrbfd) { - if (! dialogex) - { + if (! dialogex) + { struct bin_dialog_control bdc; windres_put_32 (wrbfd, bdc.style, dc->style); @@ -1547,10 +1791,11 @@ res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog windres_put_16 (wrbfd, bdc.width, dc->width); windres_put_16 (wrbfd, bdc.height, dc->height); windres_put_16 (wrbfd, bdc.id, dc->id); - set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOG_CONTROL_SIZE); - } - else - { + set_windres_bfd_content (wrbfd, &bdc, off, + BIN_DIALOG_CONTROL_SIZE); + } + else + { struct bin_dialogex_control bdc; windres_put_32 (wrbfd, bdc.help, dc->help); @@ -1561,11 +1806,11 @@ res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog windres_put_16 (wrbfd, bdc.width, dc->width); windres_put_16 (wrbfd, bdc.height, dc->height); windres_put_32 (wrbfd, bdc.id, dc->id); - set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOGEX_CONTROL_SIZE); + set_windres_bfd_content (wrbfd, &bdc, off, + BIN_DIALOGEX_CONTROL_SIZE); } } - off += (dialogex != 0 ? BIN_DIALOGEX_CONTROL_SIZE : BIN_DIALOG_CONTROL_SIZE); - + off += dialogex != 0 ? BIN_DIALOGEX_CONTROL_SIZE : BIN_DIALOG_CONTROL_SIZE; off = resid_to_bin (wrbfd, off, dc->class); off = resid_to_bin (wrbfd, off, dc->text); @@ -1607,7 +1852,8 @@ res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog /* Convert a fontdir resource to binary. */ static rc_uint_type -res_to_bin_fontdir (windres_bfd *wrbfd, rc_uint_type off, const rc_fontdir *fontdirs) +res_to_bin_fontdir (windres_bfd *wrbfd, rc_uint_type off, + const rc_fontdir *fontdirs) { rc_uint_type start; int c; @@ -1641,7 +1887,8 @@ res_to_bin_fontdir (windres_bfd *wrbfd, rc_uint_type off, const rc_fontdir *font /* Convert a group icon resource to binary. */ static rc_uint_type -res_to_bin_group_icon (windres_bfd *wrbfd, rc_uint_type off, const rc_group_icon *group_icons) +res_to_bin_group_icon (windres_bfd *wrbfd, rc_uint_type off, + const rc_group_icon *group_icons) { rc_uint_type start; struct bin_group_icon bgi; @@ -1691,21 +1938,21 @@ res_to_bin_menu (windres_bfd *wrbfd, rc_uint_type off, const rc_menu *menu) if (wrbfd) { - if (! menuex) - { + if (! menuex) + { struct bin_menu bm; windres_put_16 (wrbfd, bm.sig1, 0); windres_put_16 (wrbfd, bm.sig2, 0); set_windres_bfd_content (wrbfd, &bm, off, BIN_MENU_SIZE); - } - else - { + } + else + { struct bin_menuex bm; windres_put_16 (wrbfd, bm.sig1, 1); windres_put_16 (wrbfd, bm.sig2, 4); windres_put_32 (wrbfd, bm.help, menu->help); set_windres_bfd_content (wrbfd, &bm, off, BIN_MENUEX_SIZE); - } + } } off += (menuex != 0 ? BIN_MENUEX_SIZE : BIN_MENU_SIZE); if (! menuex) @@ -1722,7 +1969,8 @@ res_to_bin_menu (windres_bfd *wrbfd, rc_uint_type off, const rc_menu *menu) /* Convert menu items to binary. */ static rc_uint_type -res_to_bin_menuitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items) +res_to_bin_menuitems (windres_bfd *wrbfd, rc_uint_type off, + const rc_menuitem *items) { const rc_menuitem *mi; @@ -1740,11 +1988,12 @@ res_to_bin_menuitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *i if (wrbfd) { windres_put_16 (wrbfd, bmi.flags, flags); - if (mi->popup == NULL) + if (mi->popup == NULL) windres_put_16 (wrbfd, bmi.id, mi->id); set_windres_bfd_content (wrbfd, &bmi, off, - mi->popup == NULL ? BIN_MENUITEM_SIZE - : BIN_MENUITEM_POPUP_SIZE); + (mi->popup == NULL + ? BIN_MENUITEM_SIZE + : BIN_MENUITEM_POPUP_SIZE)); } off += (mi->popup == NULL ? BIN_MENUITEM_SIZE : BIN_MENUITEM_POPUP_SIZE); @@ -1761,7 +2010,8 @@ res_to_bin_menuitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *i /* Convert menuex items to binary. */ static rc_uint_type -res_to_bin_menuexitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items) +res_to_bin_menuexitems (windres_bfd *wrbfd, rc_uint_type off, + const rc_menuitem *items) { rc_uint_type off_delta = off; const rc_menuitem *mi; @@ -1814,7 +2064,8 @@ res_to_bin_menuexitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem to binary. */ static rc_uint_type -res_to_bin_rcdata (windres_bfd *wrbfd, rc_uint_type off, const rc_rcdata_item *items) +res_to_bin_rcdata (windres_bfd *wrbfd, rc_uint_type off, + const rc_rcdata_item *items) { const rc_rcdata_item *ri; @@ -1855,22 +2106,23 @@ res_to_bin_rcdata (windres_bfd *wrbfd, rc_uint_type off, const rc_rcdata_item *i break; case RCDATA_STRING: hp = (bfd_byte *) ri->u.string.s; - break; - case RCDATA_WSTRING: - { + break; + case RCDATA_WSTRING: + { rc_uint_type i; - hp = (bfd_byte *) reswr_alloc (len); - for (i = 0; i < ri->u.wstring.length; i++) - windres_put_16 (wrbfd, hp + i * sizeof (unichar), ri->u.wstring.w[i]); - } + hp = reswr_alloc (len); + for (i = 0; i < ri->u.wstring.length; i++) + windres_put_16 (wrbfd, hp + i * sizeof (unichar), + ri->u.wstring.w[i]); + } break; - case RCDATA_BUFFER: + case RCDATA_BUFFER: hp = (bfd_byte *) ri->u.buffer.data; - break; - } + break; + } set_windres_bfd_content (wrbfd, hp, off, len); - } + } off += len; } return off; @@ -1899,13 +2151,13 @@ res_to_bin_stringtable (windres_bfd *wrbfd, rc_uint_type off, bfd_byte *hp; rc_uint_type j; - hp = (bfd_byte *) reswr_alloc (length); + hp = reswr_alloc (length); windres_put_16 (wrbfd, hp, slen); - for (j = 0; j < slen; j++) + for (j = 0; j < slen; j++) windres_put_16 (wrbfd, hp + 2 + j * 2, s[j]); set_windres_bfd_content (wrbfd, hp, off, length); - } + } off += length; } return off; @@ -1926,7 +2178,7 @@ string_to_unicode_bin (windres_bfd *wrbfd, rc_uint_type off, const char *s) rc_uint_type i; bfd_byte *hp; - hp = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar)); + hp = reswr_alloc ((len + 1) * sizeof (unichar)); for (i = 0; i < len; i++) windres_put_16 (wrbfd, hp + i * 2, s[i]); @@ -1953,7 +2205,7 @@ res_to_bin_toolbar (windres_bfd *wrbfd, rc_uint_type off, rc_toolbar *tb) bfd_byte *ids; rc_uint_type i = 0; - ids = (bfd_byte *) reswr_alloc (tb->nitems * 4); + ids = reswr_alloc (tb->nitems * 4); it=tb->items; while(it != NULL) { @@ -1992,7 +2244,7 @@ res_to_bin_versioninfo (windres_bfd *wrbfd, rc_uint_type off, struct bin_fixed_versioninfo bfv; const rc_fixed_versioninfo *fi; - fi = versioninfo->fixed; + fi = versioninfo->fixed; windres_put_32 (wrbfd, bfv.sig1, 0xfeef04bd); windres_put_32 (wrbfd, bfv.sig2, 0x10000); windres_put_32 (wrbfd, bfv.file_version, fi->file_version_ms); @@ -2119,13 +2371,13 @@ res_to_bin_versioninfo (windres_bfd *wrbfd, rc_uint_type off, off += 4; } if (wrbfd) - { + { windres_put_16 (wrbfd, bvvd.size, off - vvd_off); windres_put_16 (wrbfd, bvvd.sig1, off - vvvd_off); windres_put_16 (wrbfd, bvvd.sig2, 0); set_windres_bfd_content (wrbfd, &bvvd, vvd_off, BIN_VER_INFO_SIZE); - } + } break; } @@ -2146,7 +2398,7 @@ res_to_bin_versioninfo (windres_bfd *wrbfd, rc_uint_type off, windres_put_16 (wrbfd, bvi.size, off - start); windres_put_16 (wrbfd, bvi.fixed_size, versioninfo->fixed == NULL ? 0 - : BIN_FIXED_VERSIONINFO_SIZE); + : BIN_FIXED_VERSIONINFO_SIZE); windres_put_16 (wrbfd, bvi.sig2, 0); set_windres_bfd_content (wrbfd, &bvi, start, BIN_VER_INFO_SIZE); } diff --git a/binutils/rescoff.c b/binutils/rescoff.c index f9a1e70..88b5f34 100644 --- a/binutils/rescoff.c +++ b/binutils/rescoff.c @@ -120,27 +120,38 @@ read_coff_rsrc (const char *filename, const char *target) struct coff_file_info flaginfo; if (filename == NULL) - fatal (_("filename required for COFF input")); + { + non_fatal (_("filename required for COFF input")); + return NULL; + } abfd = bfd_openr (filename, target); if (abfd == NULL) - bfd_fatal (filename); + { + bfd_nonfatal (filename); + return NULL; + } if (! bfd_check_format_matches (abfd, bfd_object, &matching)) { bfd_nonfatal (bfd_get_filename (abfd)); if (bfd_get_error () == bfd_error_file_ambiguously_recognized) list_matching_formats (matching); - xexit (1); + free (matching); + return NULL; } if (bfd_get_flavour (abfd) != bfd_target_coff_flavour || !obj_pe (abfd)) - fatal (_("%s: not a PE file"), filename); + { + non_fatal (_("%s: not a PE file"), filename); + return NULL; + } sec = bfd_get_section_by_name (abfd, ".rsrc"); if (sec == NULL) { - fatal (_("%s: no resource section"), filename); + non_fatal (_("%s: no resource section"), filename); + return NULL; } set_windres_bfd (&wrbfd, abfd, sec, WR_KIND_BFD); @@ -150,7 +161,10 @@ read_coff_rsrc (const char *filename, const char *target) but there is no other way to determine if the section size is reasonable. */ if (size > (bfd_size_type) get_file_size (filename)) - fatal (_("%s: .rsrc section is bigger than the file!"), filename); + { + non_fatal (_("%s: .rsrc section is bigger than the file!"), filename); + return NULL; + } data = (bfd_byte *) res_alloc (size); get_windres_bfd_content (&wrbfd, data, 0, size); @@ -178,7 +192,7 @@ read_coff_rsrc (const char *filename, const char *target) static void overrun (const struct coff_file_info *flaginfo, const char *msg) { - fatal (_("%s: %s: address out of bounds"), flaginfo->filename, msg); + non_fatal (_("%s: %s: address out of bounds"), flaginfo->filename, msg); } /* Read a resource directory. */ @@ -199,10 +213,17 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, Microsoft only defines 3 levels. Corrupt files however might claim to use more. */ if (level > 4) - fatal (_("%s: resources nest too deep"), flaginfo->filename); + { + non_fatal (_("%s: resources nest too deep"), flaginfo->filename); + return NULL; + } - if ((size_t) (flaginfo->data_end - data) < sizeof (struct extern_res_directory)) - overrun (flaginfo, _("directory")); + size_t data_len = flaginfo->data_end - data; + if (data_len < sizeof (struct extern_res_directory)) + { + overrun (flaginfo, _("directory")); + return NULL; + } erd = (const struct extern_res_directory *) data; @@ -229,8 +250,12 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, const bfd_byte *ers; int length, j; - if ((const bfd_byte *) ere >= flaginfo->data_end) - overrun (flaginfo, _("named directory entry")); + if ((const bfd_byte *) ere > flaginfo->data_end + || flaginfo->data_end - (const bfd_byte *) ere < 8) + { + overrun (flaginfo, _("named directory entry")); + return NULL; + } name = windres_get_32 (wrbfd, ere->name, 4); rva = windres_get_32 (wrbfd, ere->rva, 4); @@ -238,24 +263,32 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, /* For some reason the high bit in NAME is set. */ name &=~ 0x80000000; - if (name > (rc_uint_type) (flaginfo->data_end - flaginfo->data)) - overrun (flaginfo, _("directory entry name")); + if (name > data_len) + { + overrun (flaginfo, _("directory entry name")); + return NULL; + } ers = flaginfo->data + name; - + if (flaginfo->data_end - ers < 2) + { + overrun (flaginfo, _("resource name")); + return NULL; + } + length = windres_get_16 (wrbfd, ers, 2); + /* PR 17512: file: 05dc4a16. */ + if (length * 2 + 4 > flaginfo->data_end - ers) + { + overrun (flaginfo, _("resource name")); + return NULL; + } re = (rc_res_entry *) res_alloc (sizeof *re); re->next = NULL; re->id.named = 1; - length = windres_get_16 (wrbfd, ers, 2); re->id.u.n.length = length; re->id.u.n.name = (unichar *) res_alloc (length * sizeof (unichar)); for (j = 0; j < length; j++) - { - /* PR 17512: file: 05dc4a16. */ - if (length < 0 || ers >= flaginfo->data_end || ers + j * 2 + 4 >= flaginfo->data_end) - overrun (flaginfo, _("resource name")); - re->id.u.n.name[j] = windres_get_16 (wrbfd, ers + j * 2 + 2, 2); - } + re->id.u.n.name[j] = windres_get_16 (wrbfd, ers + j * 2 + 2, 2); if (level == 0) type = &re->id; @@ -263,18 +296,25 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, if ((rva & 0x80000000) != 0) { rva &=~ 0x80000000; - if (rva >= (rc_uint_type) (flaginfo->data_end - flaginfo->data)) - overrun (flaginfo, _("named subdirectory")); + if (rva >= data_len) + { + overrun (flaginfo, _("named subdirectory")); + return NULL; + } re->subdir = 1; - re->u.dir = read_coff_res_dir (wrbfd, flaginfo->data + rva, flaginfo, type, - level + 1); + re->u.dir = read_coff_res_dir (wrbfd, flaginfo->data + rva, flaginfo, + type, level + 1); } else { - if (rva >= (rc_uint_type) (flaginfo->data_end - flaginfo->data)) - overrun (flaginfo, _("named resource")); + if (rva >= data_len) + { + overrun (flaginfo, _("named resource")); + return NULL; + } re->subdir = 0; - re->u.res = read_coff_data_entry (wrbfd, flaginfo->data + rva, flaginfo, type); + re->u.res = read_coff_data_entry (wrbfd, flaginfo->data + rva, + flaginfo, type); } *pp = re; @@ -286,8 +326,12 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, unsigned long name, rva; rc_res_entry *re; - if ((const bfd_byte *) ere >= flaginfo->data_end) - overrun (flaginfo, _("ID directory entry")); + if ((const bfd_byte *) ere > flaginfo->data_end + || flaginfo->data_end - (const bfd_byte *) ere < 8) + { + overrun (flaginfo, _("ID directory entry")); + return NULL; + } name = windres_get_32 (wrbfd, ere->name, 4); rva = windres_get_32 (wrbfd, ere->rva, 4); @@ -303,18 +347,25 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, if ((rva & 0x80000000) != 0) { rva &=~ 0x80000000; - if (rva >= (rc_uint_type) (flaginfo->data_end - flaginfo->data)) - overrun (flaginfo, _("ID subdirectory")); + if (rva >= data_len) + { + overrun (flaginfo, _("ID subdirectory")); + return NULL; + } re->subdir = 1; - re->u.dir = read_coff_res_dir (wrbfd, flaginfo->data + rva, flaginfo, type, - level + 1); + re->u.dir = read_coff_res_dir (wrbfd, flaginfo->data + rva, flaginfo, + type, level + 1); } else { - if (rva >= (rc_uint_type) (flaginfo->data_end - flaginfo->data)) - overrun (flaginfo, _("ID resource")); + if (rva >= data_len) + { + overrun (flaginfo, _("ID resource")); + return NULL; + } re->subdir = 0; - re->u.res = read_coff_data_entry (wrbfd, flaginfo->data + rva, flaginfo, type); + re->u.res = read_coff_data_entry (wrbfd, flaginfo->data + rva, + flaginfo, type); } *pp = re; @@ -337,10 +388,16 @@ read_coff_data_entry (windres_bfd *wrbfd, const bfd_byte *data, const bfd_byte *resdata; if (type == NULL) - fatal (_("resource type unknown")); + { + non_fatal (_("resource type unknown")); + return NULL; + } if ((size_t) (flaginfo->data_end - data) < sizeof (struct extern_res_data)) - overrun (flaginfo, _("data entry")); + { + overrun (flaginfo, _("data entry")); + return NULL; + } erd = (const struct extern_res_data *) data; @@ -348,18 +405,26 @@ read_coff_data_entry (windres_bfd *wrbfd, const bfd_byte *data, rva = windres_get_32 (wrbfd, erd->rva, 4); if (rva < flaginfo->secaddr || rva - flaginfo->secaddr >= (rc_uint_type) (flaginfo->data_end - flaginfo->data)) - overrun (flaginfo, _("resource data")); + { + overrun (flaginfo, _("resource data")); + return NULL; + } resdata = flaginfo->data + (rva - flaginfo->secaddr); if (size > (rc_uint_type) (flaginfo->data_end - resdata)) - overrun (flaginfo, _("resource data size")); + { + overrun (flaginfo, _("resource data size")); + return NULL; + } r = bin_to_res (wrbfd, *type, resdata, size); - - memset (&r->res_info, 0, sizeof (rc_res_res_info)); - r->coff_info.codepage = windres_get_32 (wrbfd, erd->codepage, 4); - r->coff_info.reserved = windres_get_32 (wrbfd, erd->reserved, 4); + if (r != NULL) + { + memset (&r->res_info, 0, sizeof (rc_res_res_info)); + r->coff_info.codepage = windres_get_32 (wrbfd, erd->codepage, 4); + r->coff_info.reserved = windres_get_32 (wrbfd, erd->reserved, 4); + } return r; } @@ -422,9 +487,9 @@ struct coff_write_info static void coff_bin_sizes (const rc_res_directory *, struct coff_write_info *); static bfd_byte *coff_alloc (struct bindata_build *, rc_uint_type); -static void coff_to_bin +static bool coff_to_bin (const rc_res_directory *, struct coff_write_info *); -static void coff_res_to_bin +static bool coff_res_to_bin (const rc_res_resource *, struct coff_write_info *); /* Write resources to a COFF file. RESOURCES should already be @@ -435,7 +500,7 @@ static void coff_res_to_bin would require doing the basic work of objcopy, just modifying or adding the .rsrc section. */ -void +bool write_coff_file (const char *filename, const char *target, const rc_res_directory *resources) { @@ -448,44 +513,77 @@ write_coff_file (const char *filename, const char *target, unsigned long length, offset; if (filename == NULL) - fatal (_("filename required for COFF output")); + { + non_fatal (_("filename required for COFF output")); + return false; + } abfd = bfd_openw (filename, target); if (abfd == NULL) - bfd_fatal (filename); + { + bfd_nonfatal (filename); + return false; + } if (! bfd_set_format (abfd, bfd_object)) - bfd_fatal ("bfd_set_format"); + { + bfd_nonfatal ("bfd_set_format"); + return false; + } #if defined DLLTOOL_SH if (! bfd_set_arch_mach (abfd, bfd_arch_sh, 0)) - bfd_fatal ("bfd_set_arch_mach(sh)"); + { + bfd_nonfatal ("bfd_set_arch_mach(sh)"); + return false; + } #elif defined DLLTOOL_MIPS if (! bfd_set_arch_mach (abfd, bfd_arch_mips, 0)) - bfd_fatal ("bfd_set_arch_mach(mips)"); + { + bfd_nonfatal ("bfd_set_arch_mach(mips)"); + return false; + } #elif defined DLLTOOL_ARM if (! bfd_set_arch_mach (abfd, bfd_arch_arm, 0)) - bfd_fatal ("bfd_set_arch_mach(arm)"); + { + bfd_nonfatal ("bfd_set_arch_mach(arm)"); + return false; + } #elif defined DLLTOOL_AARCH64 if (! bfd_set_arch_mach (abfd, bfd_arch_aarch64, 0)) - bfd_fatal ("bfd_set_arch_mach(aarch64)"); + { + bfd_nonfatal ("bfd_set_arch_mach(aarch64)"); + return false; + } #else /* FIXME: This is obviously i386 specific. */ if (! bfd_set_arch_mach (abfd, bfd_arch_i386, 0)) - bfd_fatal ("bfd_set_arch_mach(i386)"); + { + bfd_nonfatal ("bfd_set_arch_mach(i386)"); + return false; + } #endif if (! bfd_set_file_flags (abfd, HAS_SYMS | HAS_RELOC)) - bfd_fatal ("bfd_set_file_flags"); + { + bfd_nonfatal ("bfd_set_file_flags"); + return false; + } sec = bfd_make_section_with_flags (abfd, ".rsrc", (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY)); if (sec == NULL) - bfd_fatal ("bfd_make_section"); + { + bfd_nonfatal ("bfd_make_section"); + return false; + } if (! bfd_set_symtab (abfd, &sec->symbol, 1)) - bfd_fatal ("bfd_set_symtab"); + { + bfd_nonfatal ("bfd_set_symtab"); + return false; + } /* Requiring this is probably a bug in BFD. */ sec->output_section = sec; @@ -529,7 +627,8 @@ write_coff_file (const char *filename, const char *target, cwi.dirstrsize = (cwi.dirstrsize + 7) & ~7; /* Actually convert the resources to binary. */ - coff_to_bin (resources, &cwi); + if (!coff_to_bin (resources, &cwi)) + return false; /* Add another few bytes to the directory strings if needed for alignment. */ @@ -554,7 +653,10 @@ write_coff_file (const char *filename, const char *target, + cwi.resources.length); if (!bfd_set_section_size (sec, length)) - bfd_fatal ("bfd_set_section_size"); + { + bfd_nonfatal ("bfd_set_section_size"); + return false; + } bfd_set_reloc (abfd, sec, cwi.relocs, cwi.reloc_count); @@ -562,7 +664,10 @@ write_coff_file (const char *filename, const char *target, for (d = cwi.dirs.d; d != NULL; d = d->next) { if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length)) - bfd_fatal ("bfd_set_section_contents"); + { + bfd_nonfatal ("bfd_set_section_contents"); + return false; + } offset += d->length; } for (d = cwi.dirstrs.d; d != NULL; d = d->next) @@ -577,17 +682,23 @@ write_coff_file (const char *filename, const char *target, } for (rd = cwi.resources.d; rd != NULL; rd = rd->next) { - res_to_bin (cwi.wrbfd, (rc_uint_type) offset, rd->res); + if (res_to_bin (cwi.wrbfd, (rc_uint_type) offset, rd->res) + == (rc_uint_type) -1) + return false; offset += rd->length; } assert (offset == length); if (! bfd_close (abfd)) - bfd_fatal ("bfd_close"); + { + bfd_nonfatal ("bfd_close"); + return false; + } /* We allocated the relocs array using malloc. */ free (cwi.relocs); + return true; } /* Work out the sizes of the various fixed size resource directory @@ -640,7 +751,7 @@ coff_alloc (struct bindata_build *bb, rc_uint_type size) /* Convert the resource directory RESDIR to binary. */ -static void +static bool coff_to_bin (const rc_res_directory *resdir, struct coff_write_info *cwi) { struct extern_res_directory *erd; @@ -701,21 +812,24 @@ coff_to_bin (const rc_res_directory *resdir, struct coff_write_info *cwi) if (e->subdir) { windres_put_32 (cwi->wrbfd, ere->rva, 0x80000000 | cwi->dirs.length); - coff_to_bin (e->u.dir, cwi); + if (!coff_to_bin (e->u.dir, cwi)) + return false; } else { windres_put_32 (cwi->wrbfd, ere->rva, - cwi->dirsize + cwi->dirstrsize + cwi->dataents.length); + cwi->dirsize + cwi->dirstrsize + cwi->dataents.length); - coff_res_to_bin (e->u.res, cwi); + if (!coff_res_to_bin (e->u.res, cwi)) + return false; } } + return true; } /* Convert the resource RES to binary. */ -static void +static bool coff_res_to_bin (const rc_res_resource *res, struct coff_write_info *cwi) { arelent *r; @@ -735,7 +849,10 @@ coff_res_to_bin (const rc_res_resource *res, struct coff_write_info *cwi) r->addend = 0; r->howto = bfd_reloc_type_lookup (WR_BFD (cwi->wrbfd), BFD_RELOC_RVA); if (r->howto == NULL) - bfd_fatal (_("can't get BFD_RELOC_RVA relocation type")); + { + bfd_nonfatal (_("can't get BFD_RELOC_RVA relocation type")); + return false; + } cwi->relocs = xrealloc (cwi->relocs, (cwi->reloc_count + 2) * sizeof (arelent *)); @@ -755,6 +872,8 @@ coff_res_to_bin (const rc_res_resource *res, struct coff_write_info *cwi) d = (coff_res_data *) reswr_alloc (sizeof (coff_res_data)); d->length = res_to_bin (NULL, (rc_uint_type) 0, res); + if (d->length == (rc_uint_type) -1) + return false; d->res = res; d->next = NULL; @@ -770,4 +889,5 @@ coff_res_to_bin (const rc_res_resource *res, struct coff_write_info *cwi) /* Force the next resource to have 64 bit alignment. */ d->length = (d->length + 7) & ~7; + return true; } diff --git a/binutils/resrc.c b/binutils/resrc.c index d265818..8f9451b 100644 --- a/binutils/resrc.c +++ b/binutils/resrc.c @@ -1938,7 +1938,7 @@ indent (FILE *e, int c) refer to that file, we use the user-data model for that to express it binary without the need to store it somewhere externally. */ -void +bool write_rc_file (const char *filename, const rc_res_directory *res_dir) { FILE *e; @@ -1950,12 +1950,17 @@ write_rc_file (const char *filename, const rc_res_directory *res_dir) { e = fopen (filename, FOPEN_WT); if (e == NULL) - fatal (_("can't open `%s' for output: %s"), filename, strerror (errno)); + { + non_fatal (_("can't open `%s' for output: %s"), + filename, strerror (errno)); + return false; + } } language = (rc_uint_type) ((bfd_signed_vma) -1); write_rc_directory (e, res_dir, (const rc_res_id *) NULL, (const rc_res_id *) NULL, &language, 1); + return true; } /* Write out a directory. E is the file to write to. RD is the diff --git a/binutils/resres.c b/binutils/resres.c index ab5aa66..d96fb14 100644 --- a/binutils/resres.c +++ b/binutils/resres.c @@ -109,14 +109,14 @@ read_res_file (const char *fn) } /* Write resource file */ -void +bool write_res_file (const char *fn,const rc_res_directory *resdir) { asection *sec; rc_uint_type language; bfd *abfd; windres_bfd wrbfd; - unsigned long sec_length = 0,sec_length_wrote; + rc_uint_type sec_length = 0, sec_length_wrote; static const bfd_byte sign[] = {0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, @@ -130,7 +130,10 @@ write_res_file (const char *fn,const rc_res_directory *resdir) (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA)); if (sec == NULL) - bfd_fatal ("bfd_make_section"); + { + bfd_nonfatal ("bfd_make_section"); + return false; + } /* Requiring this is probably a bug in BFD. */ sec->output_section = sec; @@ -142,8 +145,13 @@ write_res_file (const char *fn,const rc_res_directory *resdir) sec_length = write_res_directory ((windres_bfd *) NULL, 0x20UL, resdir, (const rc_res_id *) NULL, (const rc_res_id *) NULL, &language, 1); + if (sec_length == (rc_uint_type) -1) + return false; if (!bfd_set_section_size (sec, (sec_length + 3) & ~3)) - bfd_fatal ("bfd_set_section_size"); + { + bfd_nonfatal ("bfd_set_section_size"); + return false; + } if ((sec_length & 3) != 0) set_windres_bfd_content (&wrbfd, sign, sec_length, 4-(sec_length & 3)); set_windres_bfd_content (&wrbfd, sign, 0, sizeof (sign)); @@ -152,12 +160,16 @@ write_res_file (const char *fn,const rc_res_directory *resdir) (const rc_res_id *) NULL, (const rc_res_id *) NULL, &language, 1); + if (sec_length_wrote == (rc_uint_type) -1) + return false; if (sec_length != sec_length_wrote) - fatal ("res write failed with different sizes (%lu/%lu).", - (unsigned long) sec_length, (unsigned long) sec_length_wrote); + { + non_fatal ("res write failed with different sizes (%lu/%lu).", + (unsigned long) sec_length, (unsigned long) sec_length_wrote); + return false; + } - bfd_close (abfd); - return; + return bfd_close (abfd); } /* Read a resource entry, returns 0 when all resources are read */ @@ -252,8 +264,12 @@ write_res_directory (windres_bfd *wrbfd, rc_uint_type off, const rc_res_director } if (re->subdir) - off = write_res_directory (wrbfd, off, re->u.dir, type, name, language, - level + 1); + { + off = write_res_directory (wrbfd, off, re->u.dir, type, name, language, + level + 1); + if (off == (rc_uint_type) -1) + return off; + } else { if (level == 3) @@ -265,12 +281,16 @@ write_res_directory (windres_bfd *wrbfd, rc_uint_type off, const rc_res_director resource itself records if anything. */ off = write_res_resource (wrbfd, off, type, name, re->u.res, language); + if (off == (rc_uint_type) -1) + return off; } else { fprintf (stderr, "// Resource at unexpected level %d\n", level); off = write_res_resource (wrbfd, off, type, (rc_res_id *) NULL, re->u.res, language); + if (off == (rc_uint_type) -1) + return off; } } } @@ -378,6 +398,8 @@ write_res_bin (windres_bfd *wrbfd, rc_uint_type off, const rc_res_resource *res, rc_uint_type datasize = 0; noff = res_to_bin ((windres_bfd *) NULL, off, res); + if (noff == (rc_uint_type) -1) + return noff; datasize = noff - off; off = write_res_header (wrbfd, off, datasize, type, name, resinfo); diff --git a/binutils/testsuite/binutils-all/nm-coff-1.s b/binutils/testsuite/binutils-all/nm-coff-1.s new file mode 100644 index 0000000..3efc10e --- /dev/null +++ b/binutils/testsuite/binutils-all/nm-coff-1.s @@ -0,0 +1,26 @@ + .globl text_symbol1 + .globl text_symbol2 + .globl text_symbol3 + .macro ENDFN name:req + .def \name + .type 0x20 /* DT_FUNC */ + .scl 2 /* C_EXT */ + .endef + .def \name + .scl 0xff /* C_EFCN */ + .val . + .endef + .endm + .text +text_symbol1: + .long 0 + .long 0 + .long 0 + ENDFN text_symbol1 +text_symbol2: + .long 0 + .long 0 + ENDFN text_symbol2 +text_symbol3: + .long 0 + ENDFN text_symbol3 diff --git a/binutils/testsuite/binutils-all/nm-coff-sdef-1.s b/binutils/testsuite/binutils-all/nm-coff-sdef-1.s new file mode 100644 index 0000000..f1a10bb --- /dev/null +++ b/binutils/testsuite/binutils-all/nm-coff-sdef-1.s @@ -0,0 +1,26 @@ + .globl text_symbol1 + .globl text_symbol2 + .globl text_symbol3 + .macro ENDFN name:req + .sdef \name + .type 0x20 /* DT_FUNC */ + .scl 2 /* C_EXT */ + .endef + .sdef \name + .scl 0xff /* C_EFCN */ + .val . + .endef + .endm + .text +text_symbol1: + .byte 0,0,0,0 + .byte 0,0,0,0 + .byte 0,0,0,0 + ENDFN text_symbol1 +text_symbol2: + .byte 0,0,0,0 + .byte 0,0,0,0 + ENDFN text_symbol2 +text_symbol3: + .byte 0,0,0,0 + ENDFN text_symbol3 diff --git a/binutils/testsuite/binutils-all/nm.exp b/binutils/testsuite/binutils-all/nm.exp index e1b2d16..b81126b 100644 --- a/binutils/testsuite/binutils-all/nm.exp +++ b/binutils/testsuite/binutils-all/nm.exp @@ -163,6 +163,12 @@ if { [is_elf_format] || [istarget wasm32-*-*] || [istarget bpf-*-*]} { set nm_1_src "nm-elf-1.s" +} elseif {[is_coff_format] && ![istarget arm*-*-*]} { + if {[istarget *c4x-*-*] || [istarget *c54x-*-*]} { + set nm_1_src "nm-coff-sdef-1.s" + } else { + set nm_1_src "nm-coff-1.s" + } } else { set nm_1_src "nm-1.s" } diff --git a/binutils/windres.c b/binutils/windres.c index 18062f5..b41353b 100644 --- a/binutils/windres.c +++ b/binutils/windres.c @@ -1056,23 +1056,24 @@ main (int argc, char **argv) /* Write the output file. */ reswr_init (); + bool ok; switch (output_format) { default: abort (); case RES_FORMAT_RC: - write_rc_file (output_filename, resources); + ok = write_rc_file (output_filename, resources); break; case RES_FORMAT_RES: - write_res_file (output_filename, resources); + ok = write_res_file (output_filename, resources); break; case RES_FORMAT_COFF: - write_coff_file (output_filename, target, resources); + ok = write_coff_file (output_filename, target, resources); break; } - xexit (0); - return 0; + xexit (ok ? 0 : 1); + return ok ? 0 : 1; } static void @@ -1094,13 +1095,18 @@ windres_open_as_binary (const char *filename, int rdmode) { bfd *abfd; - abfd = (rdmode ? bfd_openr (filename, "binary") : bfd_openw (filename, "binary")); - if (! abfd) - fatal ("can't open `%s' for %s", filename, (rdmode ? "input" : "output")); - - if (rdmode && ! bfd_check_format (abfd, bfd_object)) - fatal ("can't open `%s' for input.", filename); - + if (rdmode) + { + abfd = bfd_openr (filename, "binary"); + if (abfd == NULL || !bfd_check_format (abfd, bfd_object)) + fatal ("can't open `%s' for input", filename); + } + else + { + abfd = bfd_openw (filename, "binary"); + if (abfd == NULL || !bfd_set_format (abfd, bfd_object)) + fatal ("can't open `%s' for output", filename); + } return abfd; } diff --git a/binutils/windres.h b/binutils/windres.h index 309564e..15c6ad0 100644 --- a/binutils/windres.h +++ b/binutils/windres.h @@ -35,9 +35,9 @@ extern int verbose; extern rc_res_directory *read_rc_file (const char *, const char *, const char *, int, int); extern rc_res_directory *read_res_file (const char *); extern rc_res_directory *read_coff_rsrc (const char *, const char *); -extern void write_rc_file (const char *, const rc_res_directory *); -extern void write_res_file (const char *, const rc_res_directory *); -extern void write_coff_file (const char *, const char *, const rc_res_directory *); +extern bool write_rc_file (const char *, const rc_res_directory *); +extern bool write_res_file (const char *, const rc_res_directory *); +extern bool write_coff_file (const char *, const char *, const rc_res_directory *); extern rc_res_resource *bin_to_res (windres_bfd *, rc_res_id, const bfd_byte *, rc_uint_type); |