x86-64-biarch
[platform/upstream/binutils.git] / binutils / resbin.c
index 1db98d0..8684ae3 100644 (file)
@@ -1,6 +1,5 @@
 /* resbin.c -- manipulate the Windows binary resource format.
-   Copyright 1997, 1998, 1999, 2002, 2003, 2005, 2006, 2007, 2009
-   Free Software Foundation, Inc.
+   Copyright (C) 1997-2014 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support.
    Rewritten by Kai Tietz, Onevision.
 
@@ -909,7 +908,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);
 
@@ -1027,7 +1026,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 +1040,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;
+
+             vs->next = NULL;
+             *ppvs = vs;
+             ppvs = &vs->next;
+           }
 
-             verlen -= subverlen;
+         vst->next = NULL;
+         *ppvst = vst;
+         ppvst = &vst->next;
            }
        }
       else if (ch == 'V')
@@ -1357,12 +1374,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)
@@ -1871,6 +1884,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 +2022,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;
+           if (!vi->u.string.stringtables)
+             off += (4 - ((off - off_delta) & 3)) & 3;
 
-           off += BIN_VER_INFO_SIZE;
-
-           off = unicode_to_bin (wrbfd, off, vi->u.string.language);
-
-           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 +2127,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);
        }