diff options
author | Nick Clifton <nickc@redhat.com> | 2011-10-11 15:56:29 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2011-10-11 15:56:29 +0000 |
commit | bfb6c1ab1ed502faa7c3764722a1f1661f6d44e8 (patch) | |
tree | 1d8de29dde516f5b030ce2a485fa33e458477bd5 /binutils/resbin.c | |
parent | 941b2081b1fd085fff7d323448672cedf18258db (diff) | |
download | gdb-bfb6c1ab1ed502faa7c3764722a1f1661f6d44e8.zip gdb-bfb6c1ab1ed502faa7c3764722a1f1661f6d44e8.tar.gz gdb-bfb6c1ab1ed502faa7c3764722a1f1661f6d44e8.tar.bz2 |
PR binutils/13051
Fix a syntax error bug when compiling rc files with the VERSIONINFO resource
containing more than one language block inside a single StringFileInfo block.
* windint.h (rc_ver_stringtable): New structure definition.
(rc_ver_info): Use it.
* rcparse.y (verstringtable): New variable.
(verstringtables): New type.
(verstringtables:): New rule declaration.
(verblocks:): Use it.
* resrc.c (append_ver_stringtable): New function.
(append_ver_stringfileinfo): Update to use stringtables.
* windres.h (append_ver_stringfileinfo): Update declaration.
(append_ver_stringtable): New declaration.
* resrc.c (write_rc_versioninfo): Update to support multiple blocks.
* resbin.c (bin_to_res_version): Likewise.
(res_to_bin_versioninfo): Likewise.
* binutils-all\windres\version.rsd: Regenerate.
* binutils-all\windres\version_cat.rsd: Regenerate.
* binutils-all\windres\version_mlang.rc: Add new test.
* binutils-all\windres\version_mlang.rsd: Likewise.
Diffstat (limited to 'binutils/resbin.c')
-rw-r--r-- | binutils/resbin.c | 158 |
1 files changed, 95 insertions, 63 deletions
diff --git a/binutils/resbin.c b/binutils/resbin.c index b3682f7..b5dcd9b 100644 --- a/binutils/resbin.c +++ b/binutils/resbin.c @@ -1,5 +1,5 @@ /* resbin.c -- manipulate the Windows binary resource format. - Copyright 1997, 1998, 1999, 2002, 2003, 2005, 2006, 2007, 2009, 2010 + Copyright 1997, 1998, 1999, 2002, 2003, 2005, 2006, 2007, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support. Rewritten by Kai Tietz, Onevision. @@ -1027,7 +1027,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,36 +1041,54 @@ 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); - - if (vallen != 0) - fatal (_("unexpected version stringtable value length %ld"), (long) vallen); - - data += off; - length -= off; - verlen -= off; - - vi->u.string.strings = NULL; - ppvs = &vi->u.string.strings; - /* It's convenient to round verlen to a 4 byte alignment, since we round the subvariables in the loop. */ + verlen = (verlen + 3) &~ 3; + vi->u.string.stringtables = NULL; + ppvst = &vi->u.string.stringtables; + while (verlen > 0) { + rc_ver_stringtable *vst; + rc_uint_type stverlen; + rc_ver_stringinfo **ppvs; + + if (length < 8) + toosmall (_("version stringtable")); + + 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 (vallen != 0) + fatal (_("unexpected version stringtable value length %ld"), (long) vallen); + + data += off; + length -= off; + verlen -= off; + + stverlen = (stverlen + 3) &~ 3; + + 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; + + if (length < 8) + toosmall (_("version string")); - vs = (rc_ver_stringinfo *) res_alloc (sizeof *vs); + vs = (rc_ver_stringinfo *) res_alloc (sizeof (rc_ver_stringinfo)); - get_version_header (wrbfd, data, length, - (const char *) NULL, &vs->key, &subverlen, - &vallen, &type, &off); + get_version_header (wrbfd, data, length, (const char *) NULL, + &vs->key, &sverlen, &vallen, &type, &off); - subverlen = (subverlen + 3) &~ 3; + sverlen = (sverlen + 3) &~ 3; data += off; length -= off; @@ -1079,22 +1097,26 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt valoff = vslen * 2 + 2; 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; + + vs->next = NULL; + *ppvs = vs; + ppvs = &vs->next; + } - verlen -= subverlen; + vst->next = NULL; + *ppvst = vst; + ppvst = &vst->next; } } else if (ch == 'V') @@ -2005,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; } @@ -2100,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); } |