From 1d73eefe2817e0ad82a902a26f8ca9ad46afc19b Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 11 Oct 2011 15:56:27 +0000 Subject: 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. --- binutils/resbin.c | 158 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 95 insertions(+), 63 deletions(-) (limited to 'binutils/resbin.c') diff --git a/binutils/resbin.c b/binutils/resbin.c index b3682f72ad..b5dcd9b5f2 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); } -- cgit v1.2.1