X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=binutils%2Fresres.c;h=c6004ddf653c68b0435d629b51432787e9161cf5;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=39264f445a22749999ffaa1ed29bdfc5edb1ba21;hpb=ed288bb597072176e84fc8279707a3f2f475779b;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/resres.c b/binutils/resres.c index 39264f445a..c6004ddf65 100644 --- a/binutils/resres.c +++ b/binutils/resres.c @@ -1,13 +1,13 @@ /* resres.c: read_res_file and write_res_file implementation for windres. - - Copyright 1998, 1999 Free Software Foundation, Inc. + Copyright (C) 1998-2020 Free Software Foundation, Inc. Written by Anders Norlander . + Rewritten by Kai Tietz, Onevision. This file is part of GNU Binutils. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -17,165 +17,192 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* FIXME: This file does not work correctly in a cross configuration. + It assumes that it can use fread and fwrite to read and write + integers. It does no swapping. */ +#include "sysdep.h" #include "bfd.h" #include "bucomm.h" #include "libiberty.h" #include "windres.h" #include -#include - -struct res_hdr - { - unsigned long data_size; - unsigned long header_size; - }; - -static void write_res_directory - PARAMS ((const struct res_directory *, - const struct res_id *, const struct res_id *, - int *, int)); -static void write_res_resource - PARAMS ((const struct res_id *, const struct res_id *, - const struct res_resource *, int *)); -static void write_res_bin - PARAMS ((const struct res_resource *, const struct res_id *, - const struct res_id *, const struct res_res_info *)); - -static void write_res_id PARAMS ((const struct res_id *)); -static void write_res_info PARAMS ((const struct res_res_info *)); -static void write_res_data PARAMS ((const void *, size_t, int)); -static void write_res_header - PARAMS ((unsigned long, const struct res_id *, const struct res_id *, - const struct res_res_info *)); - -static int read_resource_entry PARAMS ((void)); -static void read_res_data PARAMS ((void *, size_t, int)); -static void read_res_id PARAMS ((struct res_id *)); -static unichar *read_unistring PARAMS ((int *)); -static void skip_null_resource PARAMS ((void)); - -static unsigned long get_id_size PARAMS ((const struct res_id *)); -static void res_align_file PARAMS ((void)); -static void - res_add_resource - PARAMS ((struct res_resource *, const struct res_id *, - const struct res_id *, int, int)); +static rc_uint_type write_res_directory (windres_bfd *, rc_uint_type, + const rc_res_directory *, const rc_res_id *, + const rc_res_id *, rc_uint_type *, int); +static rc_uint_type write_res_resource (windres_bfd *, rc_uint_type,const rc_res_id *, + const rc_res_id *, const rc_res_resource *, + rc_uint_type *); +static rc_uint_type write_res_bin (windres_bfd *, rc_uint_type, const rc_res_resource *, + const rc_res_id *, const rc_res_id *, + const rc_res_res_info *); -void - res_append_resource - PARAMS ((struct res_directory **, struct res_resource *, - int, const struct res_id *, int)); +static rc_uint_type write_res_id (windres_bfd *, rc_uint_type, const rc_res_id *); +static rc_uint_type write_res_info (windres_bfd *, rc_uint_type, const rc_res_res_info *); +static rc_uint_type write_res_data_hdr (windres_bfd *, rc_uint_type, res_hdr *); + +static rc_uint_type write_res_header (windres_bfd *, rc_uint_type, rc_uint_type, + const rc_res_id *, const rc_res_id *, + const rc_res_res_info *); + +static int read_resource_entry (windres_bfd *, rc_uint_type *, rc_uint_type); +static void read_res_data (windres_bfd *, rc_uint_type *, rc_uint_type, void *, + rc_uint_type); +static void read_res_data_hdr (windres_bfd *, rc_uint_type *, rc_uint_type, res_hdr *); +static void read_res_id (windres_bfd *, rc_uint_type *, rc_uint_type, rc_res_id *); +static unichar *read_unistring (windres_bfd *, rc_uint_type *, rc_uint_type, rc_uint_type *); +static void skip_null_resource (windres_bfd *, rc_uint_type *, rc_uint_type); +static int probe_binary (windres_bfd *wrbfd, rc_uint_type); + +static unsigned long get_id_size (const rc_res_id *); -static struct res_directory *resources = NULL; +static void res_add_resource (rc_res_resource *, const rc_res_id *, + const rc_res_id *, rc_uint_type, int); + +static void res_append_resource (rc_res_directory **, rc_res_resource *, + int, const rc_res_id *, int); + +static rc_res_directory *resources = NULL; -static FILE *fres; static const char *filename; extern char *program_name; /* Read resource file */ -struct res_directory * -read_res_file (fn) - const char *fn; +rc_res_directory * +read_res_file (const char *fn) { + rc_uint_type off, flen; + windres_bfd wrbfd; + bfd *abfd; + asection *sec; filename = fn; - fres = fopen (filename, "rb"); - if (fres == NULL) - fatal ("can't open `%s' for output: %s", filename, strerror (errno)); - skip_null_resource (); + flen = (rc_uint_type) get_file_size (filename); + if (! flen) + fatal ("can't open '%s' for input.", filename); + abfd = windres_open_as_binary (filename, 1); + sec = bfd_get_section_by_name (abfd, ".data"); + if (sec == NULL) + bfd_fatal ("bfd_get_section_by_name"); + set_windres_bfd (&wrbfd, abfd, sec, + (target_is_bigendian ? WR_KIND_BFD_BIN_B + : WR_KIND_BFD_BIN_L)); + off = 0; + + if (! probe_binary (&wrbfd, flen)) + set_windres_bfd_endianness (&wrbfd, ! target_is_bigendian); + + skip_null_resource (&wrbfd, &off, flen); - while (read_resource_entry ()) + while (read_resource_entry (&wrbfd, &off, flen)) ; - fclose (fres); + bfd_close (abfd); return resources; } /* Write resource file */ void -write_res_file (fn, resdir) - const char *fn; - const struct res_directory *resdir; +write_res_file (const char *fn,const rc_res_directory *resdir) { - int language; - static const unsigned char sign[] = + asection *sec; + rc_uint_type language; + bfd *abfd; + windres_bfd wrbfd; + unsigned long sec_length = 0,sec_length_wrote; + static const bfd_byte sign[] = {0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - long fpos; filename = fn; - fres = fopen (filename, "wb"); - if (fres == NULL) - fatal ("can't open `%s' for output: %s", filename, strerror (errno)); + abfd = windres_open_as_binary (filename, 0); + sec = bfd_make_section_with_flags (abfd, ".data", + (SEC_HAS_CONTENTS | SEC_ALLOC + | SEC_LOAD | SEC_DATA)); + if (sec == NULL) + bfd_fatal ("bfd_make_section"); + /* Requiring this is probably a bug in BFD. */ + sec->output_section = sec; - /* Write 32 bit resource signature */ - write_res_data (sign, sizeof (sign), 1); - - /* write resources */ + set_windres_bfd (&wrbfd, abfd, sec, + (target_is_bigendian ? WR_KIND_BFD_BIN_B + : WR_KIND_BFD_BIN_L)); language = -1; - write_res_directory (resdir, (const struct res_id *) NULL, - (const struct res_id *) NULL, &language, 1); - - /* end file on DWORD boundary */ - fpos = ftell (fres); - if (fpos % 4) - write_res_data (sign, fpos % 4, 1); - - fclose (fres); + sec_length = write_res_directory ((windres_bfd *) NULL, 0x20UL, resdir, + (const rc_res_id *) NULL, + (const rc_res_id *) NULL, &language, 1); + if (!bfd_set_section_size (sec, (sec_length + 3) & ~3)) + bfd_fatal ("bfd_set_section_size"); + if ((sec_length & 3) != 0) + set_windres_bfd_content (&wrbfd, sign, sec_length, 4-(sec_length & 3)); + set_windres_bfd_content (&wrbfd, sign, 0, sizeof (sign)); + language = -1; + sec_length_wrote = write_res_directory (&wrbfd, 0x20UL, resdir, + (const rc_res_id *) NULL, + (const rc_res_id *) NULL, + &language, 1); + if (sec_length != sec_length_wrote) + fatal ("res write failed with different sizes (%lu/%lu).", + (unsigned long) sec_length, (unsigned long) sec_length_wrote); + + bfd_close (abfd); + return; } /* Read a resource entry, returns 0 when all resources are read */ static int -read_resource_entry (void) +read_resource_entry (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax) { - struct res_id type; - struct res_id name; - struct res_res_info resinfo; - struct res_hdr reshdr; - long version; + rc_res_id type; + rc_res_id name; + rc_res_res_info resinfo; + res_hdr reshdr; void *buff; - struct res_resource *r; + rc_res_resource *r; + struct bin_res_info l; - res_align_file (); + off[0] = (off[0] + 3) & ~3; /* Read header */ - if (fread (&reshdr, sizeof (reshdr), 1, fres) != 1) + if ((off[0] + 8) > omax) return 0; + read_res_data_hdr (wrbfd, off, omax, &reshdr); /* read resource type */ - read_res_id (&type); + read_res_id (wrbfd, off, omax, &type); /* read resource id */ - read_res_id (&name); + read_res_id (wrbfd, off, omax, &name); - res_align_file (); + off[0] = (off[0] + 3) & ~3; /* Read additional resource header */ - read_res_data (&resinfo.version, sizeof (resinfo.version), 1); - read_res_data (&resinfo.memflags, sizeof (resinfo.memflags), 1); - read_res_data (&resinfo.language, sizeof (resinfo.language), 1); - read_res_data (&version, sizeof (version), 1); - read_res_data (&resinfo.characteristics, sizeof (resinfo.characteristics), 1); + read_res_data (wrbfd, off, omax, &l, BIN_RES_INFO_SIZE); + resinfo.version = windres_get_32 (wrbfd, l.version, 4); + resinfo.memflags = windres_get_16 (wrbfd, l.memflags, 2); + resinfo.language = windres_get_16 (wrbfd, l.language, 2); + /* resinfo.version2 = windres_get_32 (wrbfd, l.version2, 4); */ + resinfo.characteristics = windres_get_32 (wrbfd, l.characteristics, 4); - res_align_file (); + off[0] = (off[0] + 3) & ~3; /* Allocate buffer for data */ buff = res_alloc (reshdr.data_size); /* Read data */ - read_res_data (buff, reshdr.data_size, 1); + read_res_data (wrbfd, off, omax, buff, reshdr.data_size); /* Convert binary data to resource */ - r = bin_to_res (type, buff, reshdr.data_size, 0); + r = bin_to_res (wrbfd, type, buff, reshdr.data_size); r->res_info = resinfo; /* Add resource to resource directory */ res_add_resource (r, &type, &name, resinfo.language, 0); @@ -184,15 +211,12 @@ read_resource_entry (void) } /* write resource directory to binary resource file */ -static void -write_res_directory (rd, type, name, language, level) - const struct res_directory *rd; - const struct res_id *type; - const struct res_id *name; - int *language; - int level; +static rc_uint_type +write_res_directory (windres_bfd *wrbfd, rc_uint_type off, const rc_res_directory *rd, + const rc_res_id *type, const rc_res_id *name, rc_uint_type *language, + int level) { - const struct res_entry *re; + const rc_res_entry *re; for (re = rd->entries; re != NULL; re = re->next) { @@ -208,15 +232,15 @@ write_res_directory (rd, type, name, language, level) case 2: /* If we're at level 2, the key of this resource is the name - we are going to use in the rc printout. */ + we are going to use in the rc printout. */ name = &re->id; break; case 3: /* If we're at level 3, then this key represents a language. Use it to update the current language. */ - if (!re->id.named - && re->id.u.id != *language + if (! re->id.named + && re->id.u.id != (unsigned long) *language && (re->id.u.id & 0xffff) == re->id.u.id) { *language = re->id.u.id; @@ -228,7 +252,8 @@ write_res_directory (rd, type, name, language, level) } if (re->subdir) - write_res_directory (re->u.dir, type, name, language, level + 1); + off = write_res_directory (wrbfd, off, re->u.dir, type, name, language, + level + 1); else { if (level == 3) @@ -238,25 +263,25 @@ write_res_directory (rd, type, name, language, level) 2, and represents the name to use. We probably just set LANGUAGE, and it will probably match what the resource itself records if anything. */ - write_res_resource (type, name, re->u.res, language); + off = write_res_resource (wrbfd, off, type, name, re->u.res, + language); } else { fprintf (stderr, "// Resource at unexpected level %d\n", level); - write_res_resource (type, (struct res_id *) NULL, re->u.res, - language); + off = write_res_resource (wrbfd, off, type, (rc_res_id *) NULL, + re->u.res, language); } } } + return off; } -static void -write_res_resource (type, name, res, language) - const struct res_id *type; - const struct res_id *name; - const struct res_resource *res; - int *language; +static rc_uint_type +write_res_resource (windres_bfd *wrbfd, rc_uint_type off, const rc_res_id *type, + const rc_res_id *name, const rc_res_resource *res, + rc_uint_type *language ATTRIBUTE_UNUSED) { int rt; @@ -324,11 +349,15 @@ write_res_resource (type, name, res, language) case RES_TYPE_VERSIONINFO: rt = RT_VERSION; break; + + case RES_TYPE_TOOLBAR: + rt = RT_TOOLBAR; + break; } if (rt != 0 && type != NULL - && (type->named || type->u.id != rt)) + && (type->named || type->u.id != (unsigned long) rt)) { fprintf (stderr, "// Unexpected resource type mismatch: "); res_id_print (stderr, *type, 1); @@ -336,35 +365,28 @@ write_res_resource (type, name, res, language) abort (); } - write_res_bin (res, type, name, &res->res_info); - return; + return write_res_bin (wrbfd, off, res, type, name, &res->res_info); } /* Write a resource in binary resource format */ -static void -write_res_bin (res, type, name, resinfo) - const struct res_resource *res; - const struct res_id *type; - const struct res_id *name; - const struct res_res_info *resinfo; +static rc_uint_type +write_res_bin (windres_bfd *wrbfd, rc_uint_type off, const rc_res_resource *res, + const rc_res_id *type, const rc_res_id *name, + const rc_res_res_info *resinfo) { - unsigned long datasize = 0; - const struct bindata *bin_rep, *data; - - bin_rep = res_to_bin (res, 0); - for (data = bin_rep; data != NULL; data = data->next) - datasize += data->length; + rc_uint_type noff; + rc_uint_type datasize = 0; - write_res_header (datasize, type, name, resinfo); + noff = res_to_bin ((windres_bfd *) NULL, off, res); + datasize = noff - off; - for (data = bin_rep; data != NULL; data = data->next) - write_res_data (data->data, data->length, 1); + off = write_res_header (wrbfd, off, datasize, type, name, resinfo); + return res_to_bin (wrbfd, off, res); } /* Get number of bytes needed to store an id in binary format */ static unsigned long -get_id_size (id) - const struct res_id *id; +get_id_size (const rc_res_id *id) { if (id->named) return sizeof (unichar) * (id->u.n.length + 1); @@ -373,106 +395,142 @@ get_id_size (id) } /* Write a resource header */ -static void -write_res_header (datasize, type, name, resinfo) - unsigned long datasize; - const struct res_id *type; - const struct res_id *name; - const struct res_res_info *resinfo; +static rc_uint_type +write_res_header (windres_bfd *wrbfd, rc_uint_type off, rc_uint_type datasize, + const rc_res_id *type, const rc_res_id *name, + const rc_res_res_info *resinfo) { - struct res_hdr reshdr; + res_hdr reshdr; reshdr.data_size = datasize; reshdr.header_size = 24 + get_id_size (type) + get_id_size (name); - res_align_file (); - write_res_data (&reshdr, sizeof (reshdr), 1); - write_res_id (type); - write_res_id (name); + reshdr.header_size = (reshdr.header_size + 3) & ~3; - res_align_file (); + off = (off + 3) & ~3; - write_res_info (resinfo); - res_align_file (); + off = write_res_data_hdr (wrbfd, off, &reshdr); + off = write_res_id (wrbfd, off, type); + off = write_res_id (wrbfd, off, name); + + off = (off + 3) & ~3; + + off = write_res_info (wrbfd, off, resinfo); + off = (off + 3) & ~3; + return off; } +static rc_uint_type +write_res_data_hdr (windres_bfd *wrbfd, rc_uint_type off, res_hdr *hdr) +{ + if (wrbfd) + { + struct bin_res_hdr brh; + windres_put_32 (wrbfd, brh.data_size, hdr->data_size); + windres_put_32 (wrbfd, brh.header_size, hdr->header_size); + set_windres_bfd_content (wrbfd, &brh, off, BIN_RES_HDR_SIZE); + } + return off + BIN_RES_HDR_SIZE; +} -/* Write data to file, abort on failure */ static void -write_res_data (data, size, count) - const void *data; - size_t size; - int count; +read_res_data_hdr (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax, + res_hdr *reshdr) { - if (fwrite (data, size, count, fres) != count) - fatal ("%s: %s: could not write to file", program_name, filename); + struct bin_res_hdr brh; + + if ((off[0] + BIN_RES_HDR_SIZE) > omax) + fatal ("%s: unexpected end of file %ld/%ld", filename,(long) off[0], (long) omax); + + get_windres_bfd_content (wrbfd, &brh, off[0], BIN_RES_HDR_SIZE); + reshdr->data_size = windres_get_32 (wrbfd, brh.data_size, 4); + reshdr->header_size = windres_get_32 (wrbfd, brh.header_size, 4); + off[0] += BIN_RES_HDR_SIZE; } /* Read data from file, abort on failure */ static void -read_res_data (data, size, count) - void *data; - size_t size; - int count; +read_res_data (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax, void *data, + rc_uint_type size) { - if (fread (data, size, count, fres) != count) - fatal ("%s: %s: unexpected end of file", program_name, filename); + if ((off[0] + size) > omax) + fatal ("%s: unexpected end of file %ld/%ld %ld", filename,(long) off[0], + (long) omax, (long) size); + get_windres_bfd_content (wrbfd, data, off[0], size); + off[0] += size; } /* Write a resource id */ -static void -write_res_id (id) - const struct res_id *id; +static rc_uint_type +write_res_id (windres_bfd *wrbfd, rc_uint_type off, const rc_res_id *id) { if (id->named) { - unsigned long len = id->u.n.length; - unichar null_term = 0; - write_res_data (id->u.n.name, len * sizeof (unichar), 1); - write_res_data (&null_term, sizeof (null_term), 1); + rc_uint_type len = (((bfd_signed_vma) id->u.n.length < 0 ? 0 : id->u.n.length) + 1); + if (wrbfd) + { + rc_uint_type i; + bfd_byte *d = (bfd_byte *) xmalloc (len * sizeof (unichar)); + for (i = 0; i < (len - 1); i++) + windres_put_16 (wrbfd, d + (i * sizeof (unichar)), id->u.n.name[i]); + windres_put_16 (wrbfd, d + (i * sizeof (unichar)), 0); + set_windres_bfd_content (wrbfd, d, off, (len * sizeof (unichar))); + } + off += (len * sizeof (unichar)); } else { - unsigned short i = 0xFFFF; - write_res_data (&i, sizeof (i), 1); - i = id->u.id; - write_res_data (&i, sizeof (i), 1); + if (wrbfd) + { + struct bin_res_id bid; + windres_put_16 (wrbfd, bid.sig, 0xffff); + windres_put_16 (wrbfd, bid.id, id->u.id); + set_windres_bfd_content (wrbfd, &bid, off, BIN_RES_ID); + } + off += BIN_RES_ID; } + return off; } /* Write resource info */ -static void -write_res_info (info) - const struct res_res_info *info; +static rc_uint_type +write_res_info (windres_bfd *wrbfd, rc_uint_type off, const rc_res_res_info *info) { - write_res_data (&info->version, sizeof (info->version), 1); - write_res_data (&info->memflags, sizeof (info->memflags), 1); - write_res_data (&info->language, sizeof (info->language), 1); - write_res_data (&info->version, sizeof (info->version), 1); - write_res_data (&info->characteristics, sizeof (info->characteristics), 1); + if (wrbfd) + { + struct bin_res_info l; + + windres_put_32 (wrbfd, l.version, info->version); + windres_put_16 (wrbfd, l.memflags, info->memflags); + windres_put_16 (wrbfd, l.language, info->language); + windres_put_32 (wrbfd, l.version2, info->version); + windres_put_32 (wrbfd, l.characteristics, info->characteristics); + set_windres_bfd_content (wrbfd, &l, off, BIN_RES_INFO_SIZE); + } + return off + BIN_RES_INFO_SIZE; } /* read a resource identifier */ -void -read_res_id (id) - struct res_id *id; +static void +read_res_id (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax, rc_res_id *id) { + struct bin_res_id bid; unsigned short ord; unichar *id_s = NULL; - int len; + rc_uint_type len; - read_res_data (&ord, sizeof (ord), 1); + read_res_data (wrbfd, off, omax, &bid, BIN_RES_ID - 2); + ord = (unsigned short) windres_get_16 (wrbfd, bid.sig, 2); if (ord == 0xFFFF) /* an ordinal id */ { - read_res_data (&ord, sizeof (ord), 1); + read_res_data (wrbfd, off, omax, bid.id, BIN_RES_ID - 2); id->named = 0; - id->u.id = ord; + id->u.id = windres_get_16 (wrbfd, bid.id, 2); } else /* named id */ { - if (fseek (fres, -sizeof (ord), SEEK_CUR) != 0) - fatal ("%s: %s: could not seek in file", program_name, filename); - id_s = read_unistring (&len); + off[0] -= 2; + id_s = read_unistring (wrbfd, off, omax, &len); id->named = 1; id->u.n.length = len; id->u.n.name = id_s; @@ -481,37 +539,62 @@ read_res_id (id) /* Read a null terminated UNICODE string */ static unichar * -read_unistring (len) - int *len; +read_unistring (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax, + rc_uint_type *len) { unichar *s; + bfd_byte d[2]; unichar c; unichar *p; - int l; + rc_uint_type l; + rc_uint_type soff = off[0]; - *len = 0; - l = 0; + do + { + read_res_data (wrbfd, &soff, omax, d, sizeof (unichar)); + c = windres_get_16 (wrbfd, d, 2); + } + while (c != 0); + l = ((soff - off[0]) / sizeof (unichar)); - /* there are hardly any names longer than 256 characters */ - p = s = (unichar *) xmalloc (sizeof (unichar) * 256); + /* there are hardly any names longer than 256 characters, but anyway. */ + p = s = (unichar *) xmalloc (sizeof (unichar) * l); do { - read_res_data (&c, sizeof (c), 1); + read_res_data (wrbfd, off, omax, d, sizeof (unichar)); + c = windres_get_16 (wrbfd, d, 2); *p++ = c; - if (c != 0) - l++; } while (c != 0); - *len = l; + *len = l - 1; return s; } -/* align file on DWORD boundary */ -static void -res_align_file (void) +static int +probe_binary (windres_bfd *wrbfd, rc_uint_type omax) { - if (fseek (fres, ftell (fres) % 4, SEEK_CUR) != 0) - fatal ("%s: %s: unable to align file", program_name, filename); + rc_uint_type off; + res_hdr reshdr; + + off = 0; + read_res_data_hdr (wrbfd, &off, omax, &reshdr); + if (reshdr.data_size != 0) + return 1; + if ((reshdr.header_size != 0x20 && ! target_is_bigendian) + || (reshdr.header_size != 0x20000000 && target_is_bigendian)) + return 1; + + /* Subtract size of HeaderSize. DataSize has to be zero. */ + off += 0x20 - BIN_RES_HDR_SIZE; + if ((off + BIN_RES_HDR_SIZE) >= omax) + return 1; + read_res_data_hdr (wrbfd, &off, omax, &reshdr); + /* off is advanced by BIN_RES_HDR_SIZE in read_res_data_hdr() + which is part of reshdr.header_size. We shouldn't take it + into account twice. */ + if ((off - BIN_RES_HDR_SIZE + reshdr.data_size + reshdr.header_size) > omax) + return 0; + return 1; } /* Check if file is a win32 binary resource file, if so @@ -519,36 +602,35 @@ res_align_file (void) error. */ static void -skip_null_resource (void) +skip_null_resource (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax) { - struct res_hdr reshdr = - {0, 0}; - read_res_data (&reshdr, sizeof (reshdr), 1); - if ((reshdr.data_size != 0) || (reshdr.header_size != 0x20)) + res_hdr reshdr; + read_res_data_hdr (wrbfd, off, omax, &reshdr); + if (reshdr.data_size != 0) + goto skip_err; + if ((reshdr.header_size != 0x20 && ! target_is_bigendian) + || (reshdr.header_size != 0x20000000 && target_is_bigendian)) goto skip_err; - /* Subtract size of HeaderSize and DataSize */ - if (fseek (fres, reshdr.header_size - 8, SEEK_CUR) != 0) + /* Subtract size of HeaderSize. DataSize has to be zero. */ + off[0] += 0x20 - BIN_RES_HDR_SIZE; + if (off[0] >= omax) goto skip_err; return; -skip_err: + skip_err: fprintf (stderr, "%s: %s: Not a valid WIN32 resource file\n", program_name, filename); xexit (1); } /* Add a resource to resource directory */ -void -res_add_resource (r, type, id, language, dupok) - struct res_resource *r; - const struct res_id *type; - const struct res_id *id; - int language; - int dupok; +static void +res_add_resource (rc_res_resource *r, const rc_res_id *type, const rc_res_id *id, + rc_uint_type language, int dupok) { - struct res_id a[3]; + rc_res_id a[3]; a[0] = *type; a[1] = *id; @@ -561,41 +643,33 @@ res_add_resource (r, type, id, language, dupok) This is just copied from define_resource and modified to add an existing resource. */ -void -res_append_resource (resources, resource, cids, ids, dupok) - struct res_directory **resources; - struct res_resource *resource; - int cids; - const struct res_id *ids; - int dupok; +static void +res_append_resource (rc_res_directory **res_dirs, rc_res_resource *resource, + int cids, const rc_res_id *ids, int dupok) { - struct res_entry *re = NULL; + rc_res_entry *re = NULL; int i; assert (cids > 0); for (i = 0; i < cids; i++) { - struct res_entry **pp; + rc_res_entry **pp; - if (*resources == NULL) + if (*res_dirs == NULL) { - static unsigned long timeval; - - /* Use the same timestamp for every resource created in a - single run. */ - if (timeval == 0) - timeval = time (NULL); - - *resources = ((struct res_directory *) - res_alloc (sizeof **resources)); - (*resources)->characteristics = 0; - (*resources)->time = timeval; - (*resources)->major = 0; - (*resources)->minor = 0; - (*resources)->entries = NULL; + *res_dirs = ((rc_res_directory *) + res_alloc (sizeof (rc_res_directory))); + + (*res_dirs)->characteristics = 0; + /* Using a real timestamp only serves to create non-deterministic + results. Use zero instead. */ + (*res_dirs)->time = 0; + (*res_dirs)->major = 0; + (*res_dirs)->minor = 0; + (*res_dirs)->entries = NULL; } - for (pp = &(*resources)->entries; *pp != NULL; pp = &(*pp)->next) + for (pp = &(*res_dirs)->entries; *pp != NULL; pp = &(*pp)->next) if (res_id_cmp ((*pp)->id, ids[i]) == 0) break; @@ -603,7 +677,7 @@ res_append_resource (resources, resource, cids, ids, dupok) re = *pp; else { - re = (struct res_entry *) res_alloc (sizeof *re); + re = (rc_res_entry *) res_alloc (sizeof (rc_res_entry)); re->next = NULL; re->id = ids[i]; if ((i + 1) < cids) @@ -622,7 +696,7 @@ res_append_resource (resources, resource, cids, ids, dupok) if ((i + 1) < cids) { - if (!re->subdir) + if (! re->subdir) { fprintf (stderr, "%s: ", program_name); res_ids_print (stderr, i, ids); @@ -630,7 +704,7 @@ res_append_resource (resources, resource, cids, ids, dupok) xexit (1); } - resources = &re->u.dir; + res_dirs = &re->u.dir; } }