X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=binutils%2Fresbin.c;h=cd562a550e9dc82a0a72085b02510bf3e940865d;hb=1769380a11463b907263ef5443de5d14559f2095;hp=ad819069ed0b218023c6e4a721053dd15e68085e;hpb=aa820537ead0135a7c38c619039dce8a6fc74ed1;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/resbin.c b/binutils/resbin.c index ad819069ed..cd562a550e 100644 --- a/binutils/resbin.c +++ b/binutils/resbin.c @@ -1,6 +1,5 @@ /* resbin.c -- manipulate the Windows binary resource format. - Copyright 1997, 1998, 1999, 2002, 2003, 2005, 2006, 2007 - Free Software Foundation, Inc. + Copyright (C) 1997-2019 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support. Rewritten by Kai Tietz, Onevision. @@ -227,7 +226,7 @@ bin_to_res_menu (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) { rc_res_resource *r; rc_menu *m; - rc_uint_type version, read; + rc_uint_type version, got; r = (rc_res_resource *) res_alloc (sizeof *r); r->type = RES_TYPE_MENU; @@ -245,7 +244,7 @@ bin_to_res_menu (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) if (length < 4) toosmall (_("menu header")); m->help = 0; - m->items = bin_to_res_menuitems (wrbfd, data + 4, length - 4, &read); + m->items = bin_to_res_menuitems (wrbfd, data + 4, length - 4, &got); } else if (version == 1) { @@ -258,7 +257,7 @@ bin_to_res_menu (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) if (offset + 4 >= length) toosmall (_("menuex offset")); m->items = bin_to_res_menuexitems (wrbfd, data + 4 + offset, - length - (4 + offset), &read); + length - (4 + offset), &got); } else fatal (_("unsupported menu version %d"), (int) version); @@ -270,14 +269,14 @@ bin_to_res_menu (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) static rc_menuitem * bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length, - rc_uint_type *read) + rc_uint_type *got) { rc_menuitem *first, **pp; first = NULL; pp = &first; - *read = 0; + *got = 0; while (length > 0) { @@ -334,7 +333,7 @@ bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type len data += itemlen; length -= itemlen; - *read += itemlen; + *got += itemlen; if ((flags & MENUITEM_ENDMENU) != 0) return first; @@ -347,14 +346,14 @@ bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type len static rc_menuitem * bin_to_res_menuexitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length, - rc_uint_type *read) + rc_uint_type *got) { rc_menuitem *first, **pp; first = NULL; pp = &first; - *read = 0; + *got = 0; while (length > 0) { @@ -408,7 +407,7 @@ bin_to_res_menuexitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type l data += itemlen; length -= itemlen; - *read += itemlen; + *got += itemlen; if ((flags & 0x80) != 0) return first; @@ -575,8 +574,6 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length dc->data = NULL; else { - off = (off + 3) &~ 3; - if (length < off + datalen) toosmall (_("dialog control data")); @@ -909,7 +906,7 @@ get_version_header (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt if (length < 8) toosmall (key); - *len = windres_get_16 (wrbfd, data, 2); + *len = (windres_get_16 (wrbfd, data, 2) + 3) & ~3; *vallen = windres_get_16 (wrbfd, data + 2, 2); *type = windres_get_16 (wrbfd, data + 4, 2); @@ -962,9 +959,10 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt get_version_header (wrbfd, data, length, "VS_VERSION_INFO", (unichar **) NULL, &verlen, &vallen, &type, &off); - if ((unsigned int) verlen != length) - fatal (_("version length %d does not match resource length %lu"), - (int) verlen, (unsigned long) length); + /* 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); if (type != 0) fatal (_("unexpected version type %d"), (int) type); @@ -1027,7 +1025,7 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt if (ch == 'S') { - rc_ver_stringinfo **ppvs; + rc_ver_stringtable **ppvst; vi->type = VERINFO_STRING; @@ -1041,60 +1039,78 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt data += off; length -= off; - get_version_header (wrbfd, data, length, (const char *) NULL, - &vi->u.string.language, &verlen, &vallen, - &type, &off); + verlen -= off; - if (vallen != 0) - fatal (_("unexpected version stringtable value length %ld"), (long) vallen); + vi->u.string.stringtables = NULL; + ppvst = &vi->u.string.stringtables; - data += off; - length -= off; - verlen -= off; + while (verlen > 0) + { + rc_ver_stringtable *vst; + rc_uint_type stverlen; + rc_ver_stringinfo **ppvs; - vi->u.string.strings = NULL; - ppvs = &vi->u.string.strings; + if (length < 8) + toosmall (_("version stringtable")); - /* It's convenient to round verlen to a 4 byte alignment, - since we round the subvariables in the loop. */ - verlen = (verlen + 3) &~ 3; + vst = (rc_ver_stringtable *) res_alloc (sizeof (rc_ver_stringtable)); - while (verlen > 0) + get_version_header (wrbfd, data, length, (const char *) NULL, + &vst->language, &stverlen, &vallen, &type, &off); + + if (vallen != 0) + fatal (_("unexpected version stringtable value length %ld"), (long) vallen); + + data += off; + length -= off; + verlen -= off; + + stverlen -= off; + + vst->strings = NULL; + ppvs = &vst->strings; + + while (stverlen > 0) { rc_ver_stringinfo *vs; - rc_uint_type subverlen, vslen, valoff; + rc_uint_type sverlen, vslen, valoff; - vs = (rc_ver_stringinfo *) res_alloc (sizeof *vs); + if (length < 8) + toosmall (_("version string")); - get_version_header (wrbfd, data, length, - (const char *) NULL, &vs->key, &subverlen, - &vallen, &type, &off); + vs = (rc_ver_stringinfo *) res_alloc (sizeof (rc_ver_stringinfo)); - subverlen = (subverlen + 3) &~ 3; + 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; + valoff = (valoff + 3) & ~3; - if (off + valoff != subverlen) + if (off + valoff != sverlen) fatal (_("unexpected version string length %ld != %ld + %ld"), - (long) subverlen, (long) off, (long) valoff); - - vs->next = NULL; - *ppvs = vs; - ppvs = &vs->next; + (long) sverlen, (long) off, (long) valoff); data += valoff; length -= valoff; - if (verlen < subverlen) + if (stverlen < sverlen) fatal (_("unexpected version string length %ld < %ld"), - (long) verlen, (long) subverlen); + (long) verlen, (long) sverlen); + stverlen -= sverlen; + verlen -= sverlen; - verlen -= subverlen; + vs->next = NULL; + *ppvs = vs; + ppvs = &vs->next; + } + + vst->next = NULL; + *ppvst = vst; + ppvst = &vst->next; } } else if (ch == 'V') @@ -1147,8 +1163,15 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt vallen -= 4; } } + else if (ch == 0) + { + if (length == 8) + /* Padding - skip. */ + break; + fatal (_("nul bytes found in version string")); + } else - fatal (_("unexpected version string")); + fatal (_("unexpected version string character: %x"), ch); vi->next = NULL; *pp = vi; @@ -1301,7 +1324,7 @@ resid_to_bin (windres_bfd *wrbfd, rc_uint_type off, rc_res_id id) if (wrbfd) { struct bin_res_id bri; - + windres_put_16 (wrbfd, bri.sig, 0xffff); windres_put_16 (wrbfd, bri.id, id.u.id); set_windres_bfd_content (wrbfd, &bri, off, BIN_RES_ID); @@ -1357,12 +1380,8 @@ static rc_uint_type res_to_bin_accelerator (windres_bfd *wrbfd, rc_uint_type off, const rc_accelerator *accelerators) { - bindata *first, **pp; const rc_accelerator *a; - first = NULL; - pp = &first; - for (a = accelerators; a != NULL; a = a->next) { if (wrbfd) @@ -1543,7 +1562,7 @@ res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog windres_put_32 (wrbfd, bdc.id, dc->id); set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOGEX_CONTROL_SIZE); } - } + } off += (dialogex != 0 ? BIN_DIALOGEX_CONTROL_SIZE : BIN_DIALOG_CONTROL_SIZE); off = resid_to_bin (wrbfd, off, dc->class); @@ -1561,7 +1580,6 @@ res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog { rc_uint_type saved_off = off; rc_uint_type old_off; - off += (4 - ((off - off_delta) & 3)) & 3; old_off = off; off = res_to_bin_rcdata (wrbfd, off, dc->data); @@ -1569,10 +1587,10 @@ res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog old_off = off = saved_off; if (wrbfd) windres_put_16 (wrbfd, dc_rclen, off - old_off); - } + } if (wrbfd) set_windres_bfd_content (wrbfd, dc_rclen, marker, 2); - } + } if (wrbfd) { @@ -1871,6 +1889,7 @@ res_to_bin_stringtable (windres_bfd *wrbfd, rc_uint_type off, unichar *s; slen = (rc_uint_type) st->strings[i].length; + if (slen == 0xffffffff) slen = 0; s = st->strings[i].string; length = 2 + slen * 2; @@ -2008,52 +2027,62 @@ res_to_bin_versioninfo (windres_bfd *wrbfd, rc_uint_type off, abort (); case VERINFO_STRING: { - struct bin_ver_info bvsd; - rc_uint_type vs_off; - const rc_ver_stringinfo *vs; + const rc_ver_stringtable *vst; off = string_to_unicode_bin (wrbfd, off, "StringFileInfo"); - off += (4 - ((off - off_delta) & 3)) & 3; - - vs_off = off; - - off += BIN_VER_INFO_SIZE; - off = unicode_to_bin (wrbfd, off, vi->u.string.language); + if (!vi->u.string.stringtables) + off += (4 - ((off - off_delta) & 3)) & 3; - for (vs = vi->u.string.strings; vs != NULL; vs = vs->next) + for (vst = vi->u.string.stringtables; vst != NULL; vst = vst->next) { - struct bin_ver_info bvss; - rc_uint_type vss_off,str_off; + struct bin_ver_info bvst; + rc_uint_type vst_off; + const rc_ver_stringinfo *vs; off += (4 - ((off - off_delta) & 3)) & 3; - vss_off = off; + vst_off = off; off += BIN_VER_INFO_SIZE; - off = unicode_to_bin (wrbfd, off, vs->key); + off = unicode_to_bin (wrbfd, off, vst->language); - off += (4 - ((off - off_delta) & 3)) & 3; + for (vs = vst->strings; vs != NULL; vs = vs->next) + { + struct bin_ver_info bvs; + rc_uint_type vs_off, str_off; + + off += (4 - ((off - off_delta) & 3)) & 3; + + vs_off = off; + off += BIN_VER_INFO_SIZE; + + off = unicode_to_bin (wrbfd, off, vs->key); + + off += (4 - ((off - off_delta) & 3)) & 3; + + str_off = off; + off = unicode_to_bin (wrbfd, off, vs->value); + + if (wrbfd) + { + windres_put_16 (wrbfd, bvs.size, off - vs_off); + windres_put_16 (wrbfd, bvs.sig1, (off - str_off) / 2); + windres_put_16 (wrbfd, bvs.sig2, 1); + set_windres_bfd_content (wrbfd, &bvs, vs_off, + BIN_VER_INFO_SIZE); + } + } - str_off = off; - off = unicode_to_bin (wrbfd, off, vs->value); if (wrbfd) { - windres_put_16 (wrbfd, bvss.size, off - vss_off); - windres_put_16 (wrbfd, bvss.sig1, (off - str_off) / 2); - windres_put_16 (wrbfd, bvss.sig2, 1); - set_windres_bfd_content (wrbfd, &bvss, vss_off, - BIN_VER_INFO_SIZE); + windres_put_16 (wrbfd, bvst.size, off - vst_off); + windres_put_16 (wrbfd, bvst.sig1, 0); + windres_put_16 (wrbfd, bvst.sig2, 1); + set_windres_bfd_content (wrbfd, &bvst, vst_off, + BIN_VER_INFO_SIZE); } } - if (wrbfd) - { - windres_put_16 (wrbfd, bvsd.size, off - vs_off); - windres_put_16 (wrbfd, bvsd.sig1, 0); - windres_put_16 (wrbfd, bvsd.sig2, 0); - set_windres_bfd_content (wrbfd, &bvsd, vs_off, - BIN_VER_INFO_SIZE); - } break; } @@ -2103,9 +2132,9 @@ res_to_bin_versioninfo (windres_bfd *wrbfd, rc_uint_type off, if (wrbfd) { - windres_put_16 (wrbfd, bv.size, off-bv_off); + windres_put_16 (wrbfd, bv.size, off - bv_off); windres_put_16 (wrbfd, bv.sig1, 0); - windres_put_16 (wrbfd, bv.sig2, 0); + windres_put_16 (wrbfd, bv.sig2, 1); set_windres_bfd_content (wrbfd, &bv, bv_off, BIN_VER_INFO_SIZE); }