/* resbin.c -- manipulate the Windows binary resource format.
- Copyright 1997, 1998, 1999, 2002, 2003, 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.
{
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;
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)
{
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);
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)
{
data += itemlen;
length -= itemlen;
- *read += itemlen;
+ *got += itemlen;
if ((flags & MENUITEM_ENDMENU) != 0)
return first;
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)
{
data += itemlen;
length -= itemlen;
- *read += itemlen;
+ *got += itemlen;
if ((flags & 0x80) != 0)
return first;
dc->data = NULL;
else
{
- off = (off + 3) &~ 3;
-
if (length < off + datalen)
toosmall (_("dialog control data"));
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);
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);
if (ch == 'S')
{
- rc_ver_stringinfo **ppvs;
+ rc_ver_stringtable **ppvst;
vi->type = VERINFO_STRING;
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')
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;
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);
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)
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);
{
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);
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)
{
unichar *s;
slen = (rc_uint_type) st->strings[i].length;
+ if (slen == 0xffffffff) slen = 0;
s = st->strings[i].string;
length = 2 + slen * 2;
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;
}
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);
}