gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / binutils / resbin.c
index fbd8b9b6f327cd59228c07885f79a6e392a1d519..79d5ffde1f17bf7d9ab05835ba701fe7dee698c8 100644 (file)
@@ -1,6 +1,5 @@
 /* resbin.c -- manipulate the Windows binary resource format.
-   Copyright 1997, 1998, 1999, 2002, 2003, 2007
-   Free Software Foundation, Inc.
+   Copyright (C) 1997-2020 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);
        }
This page took 0.028789 seconds and 4 git commands to generate.