diff options
-rw-r--r-- | binutils/resbin.c | 426 | ||||
-rw-r--r-- | binutils/rescoff.c | 216 | ||||
-rw-r--r-- | binutils/resrc.c | 9 | ||||
-rw-r--r-- | binutils/resres.c | 42 | ||||
-rw-r--r-- | binutils/windres.c | 30 | ||||
-rw-r--r-- | binutils/windres.h | 6 |
6 files changed, 549 insertions, 180 deletions
diff --git a/binutils/resbin.c b/binutils/resbin.c index a42a846..1698e14 100644 --- a/binutils/resbin.c +++ b/binutils/resbin.c @@ -55,7 +55,7 @@ static rc_res_resource *bin_to_res_group_icon (windres_bfd *, const bfd_byte *, 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 *, rc_uint_type); -static void get_version_header (windres_bfd *, const bfd_byte *, rc_uint_type, const char *, +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 *); @@ -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,7 +132,10 @@ 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; @@ -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; } } @@ -204,7 +215,10 @@ 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->xhotspot = windres_get_16 (wrbfd, data, 2); @@ -235,32 +249,51 @@ bin_to_res_menu (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) 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; } @@ -285,7 +318,10 @@ 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->state = 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; @@ -324,6 +367,8 @@ bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type len mi->id = 0; mi->popup = bin_to_res_menuitems (wrbfd, data + itemlen, length - itemlen, &subread); + if (mi->popup == NULL) + return NULL; itemlen += subread; } @@ -362,7 +407,10 @@ 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->type = windres_get_32 (wrbfd, data, 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,12 +481,16 @@ 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)); @@ -447,7 +508,10 @@ 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->help = windres_get_32 (wrbfd, data + 4, 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; } @@ -526,7 +607,10 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length 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,7 +672,10 @@ 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))); @@ -615,7 +715,10 @@ bin_to_res_string (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length 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,7 +728,10 @@ 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)); st->strings[i].string = s; @@ -655,7 +761,10 @@ bin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt rc_res_resource *r; if (length < 2) - toosmall (_("fontdir header")); + { + toosmall (_("fontdir header")); + return NULL; + } c = windres_get_16 (wrbfd, data, 2); @@ -669,7 +778,10 @@ 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); @@ -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; @@ -732,7 +850,10 @@ 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)); @@ -791,11 +912,17 @@ bin_to_res_group_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type 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,7 +937,10 @@ 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); @@ -846,11 +976,17 @@ bin_to_res_group_icon (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type le 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,7 +1001,10 @@ 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)); @@ -897,14 +1036,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 +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 +1062,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 +1071,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,6 +1093,7 @@ 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. */ @@ -956,16 +1107,23 @@ 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. */ length = verlen; @@ -980,18 +1138,31 @@ 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)); @@ -1020,7 +1191,10 @@ 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)); @@ -1032,12 +1206,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,15 +1233,24 @@ 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)); - 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; @@ -1079,30 +1267,42 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt rc_uint_type sverlen, vslen, valoff; if (length < 8) - toosmall (_("version string")); + { + toosmall (_("version string")); + return NULL; + } 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); + 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) - fatal (_("unexpected version string length %ld != %ld + %ld"), - (long) sverlen, (long) off, (long) valoff); + { + non_fatal (_("unexpected version string length %ld != %ld + %ld"), + (long) sverlen, (long) off, (long) valoff); + return NULL; + } data += valoff; length -= valoff; if (stverlen < sverlen) - fatal (_("unexpected version string length %ld < %ld"), - (long) verlen, (long) sverlen); + { + non_fatal (_("unexpected version string length %ld < %ld"), + (long) verlen, (long) sverlen); + return NULL; + } stverlen -= sverlen; verlen -= sverlen; @@ -1122,18 +1322,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,7 +1353,10 @@ 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)); @@ -1161,7 +1371,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,10 +1385,14 @@ 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; @@ -1224,7 +1442,10 @@ bin_to_res_toolbar (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type i; if (length < 12) - toosmall (_("toolbar")); + { + toosmall (_("toolbar")); + return NULL; + } ri = (rc_toolbar *) res_alloc (sizeof (rc_toolbar)); ri->button_width = windres_get_32 (wrbfd, data, 4); ri->button_height = windres_get_32 (wrbfd, data + 4, 4); @@ -1747,11 +1968,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); @@ -1862,22 +2084,22 @@ 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++) + 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; @@ -1909,10 +2131,10 @@ res_to_bin_stringtable (windres_bfd *wrbfd, rc_uint_type off, hp = (bfd_byte *) 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; diff --git a/binutils/rescoff.c b/binutils/rescoff.c index f9a1e70..98e5eb0 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,16 @@ 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")); + { + overrun (flaginfo, _("directory")); + return NULL; + } erd = (const struct extern_res_directory *) data; @@ -230,7 +250,10 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, int length, j; if ((const bfd_byte *) ere >= flaginfo->data_end) - overrun (flaginfo, _("named directory entry")); + { + overrun (flaginfo, _("named directory entry")); + return NULL; + } name = windres_get_32 (wrbfd, ere->name, 4); rva = windres_get_32 (wrbfd, ere->rva, 4); @@ -239,7 +262,10 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, name &=~ 0x80000000; if (name > (rc_uint_type) (flaginfo->data_end - flaginfo->data)) - overrun (flaginfo, _("directory entry name")); + { + overrun (flaginfo, _("directory entry name")); + return NULL; + } ers = flaginfo->data + name; @@ -252,8 +278,12 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, 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")); + if (length < 0 || ers >= flaginfo->data_end + || ers + j * 2 + 4 >= flaginfo->data_end) + { + overrun (flaginfo, _("resource name")); + return NULL; + } re->id.u.n.name[j] = windres_get_16 (wrbfd, ers + j * 2 + 2, 2); } @@ -264,7 +294,10 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, { rva &=~ 0x80000000; if (rva >= (rc_uint_type) (flaginfo->data_end - flaginfo->data)) - overrun (flaginfo, _("named subdirectory")); + { + overrun (flaginfo, _("named subdirectory")); + return NULL; + } re->subdir = 1; re->u.dir = read_coff_res_dir (wrbfd, flaginfo->data + rva, flaginfo, type, level + 1); @@ -272,7 +305,10 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, else { if (rva >= (rc_uint_type) (flaginfo->data_end - flaginfo->data)) - overrun (flaginfo, _("named resource")); + { + overrun (flaginfo, _("named resource")); + return NULL; + } re->subdir = 0; re->u.res = read_coff_data_entry (wrbfd, flaginfo->data + rva, flaginfo, type); } @@ -287,7 +323,10 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, rc_res_entry *re; if ((const bfd_byte *) ere >= flaginfo->data_end) - overrun (flaginfo, _("ID directory entry")); + { + overrun (flaginfo, _("ID directory entry")); + return NULL; + } name = windres_get_32 (wrbfd, ere->name, 4); rva = windres_get_32 (wrbfd, ere->rva, 4); @@ -304,7 +343,10 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, { rva &=~ 0x80000000; if (rva >= (rc_uint_type) (flaginfo->data_end - flaginfo->data)) - overrun (flaginfo, _("ID subdirectory")); + { + overrun (flaginfo, _("ID subdirectory")); + return NULL; + } re->subdir = 1; re->u.dir = read_coff_res_dir (wrbfd, flaginfo->data + rva, flaginfo, type, level + 1); @@ -312,7 +354,10 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, else { if (rva >= (rc_uint_type) (flaginfo->data_end - flaginfo->data)) - overrun (flaginfo, _("ID resource")); + { + overrun (flaginfo, _("ID resource")); + return NULL; + } re->subdir = 0; re->u.res = read_coff_data_entry (wrbfd, flaginfo->data + rva, flaginfo, type); } @@ -337,10 +382,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 +399,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 +481,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 +494,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 +507,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 +621,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 +647,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 +658,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 +676,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 +745,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 +806,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 +843,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 +866,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 +883,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/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); |