/* BFD back-end for archive files (libraries).
- Copyright (C) 1990-2019 Free Software Foundation, Inc.
+ Copyright (C) 1990-2020 Free Software Foundation, Inc.
Written by Cygnus Support. Mostly Gumby Henkel-Wallace's fault.
This file is part of BFD, the Binary File Descriptor library.
bfd_boolean
_bfd_generic_mkarchive (bfd *abfd)
{
- bfd_size_type amt = sizeof (struct artdata);
+ size_t amt = sizeof (struct artdata);
abfd->tdata.aout_ar_data = (struct artdata *) bfd_zalloc (abfd, amt);
if (bfd_ardata (abfd) == NULL)
bfd *abfd;
/* PR 15140: Don't allow a nested archive pointing to itself. */
- if (filename_cmp (filename, arch_bfd->filename) == 0)
+ if (filename_cmp (filename, bfd_get_filename (arch_bfd)) == 0)
{
bfd_set_error (bfd_error_malformed_archive);
return NULL;
abfd != NULL;
abfd = abfd->archive_next)
{
- if (filename_cmp (filename, abfd->filename) == 0)
+ if (filename_cmp (filename, bfd_get_filename (abfd)) == 0)
return abfd;
}
abfd = open_nested_file (filename, arch_bfd);
bfd_size_type parsed_size;
struct areltdata *ared;
char *filename = NULL;
+ ufile_ptr filesize;
bfd_size_type namelen = 0;
bfd_size_type allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr);
char *allocptr = 0;
{
/* BSD-4.4 extended name */
namelen = atoi (&hdr.ar_name[3]);
+ filesize = bfd_get_file_size (abfd);
+ if (namelen > parsed_size
+ || namelen > -allocsize - 2
+ || (filesize != 0 && namelen > filesize))
+ {
+ bfd_set_error (bfd_error_malformed_archive);
+ return NULL;
+ }
allocsize += namelen + 1;
parsed_size -= namelen;
extra_size = namelen;
- allocptr = (char *) bfd_zmalloc (allocsize);
+ allocptr = (char *) bfd_malloc (allocsize);
if (allocptr == NULL)
return NULL;
filename = (allocptr
if (!allocptr)
{
- allocptr = (char *) bfd_zmalloc (allocsize);
+ allocptr = (char *) bfd_malloc (allocsize);
if (allocptr == NULL)
return NULL;
}
+ memset (allocptr, 0, sizeof (struct areltdata));
ared = (struct areltdata *) allocptr;
-
ared->arch_header = allocptr + sizeof (struct areltdata);
memcpy (ared->arch_header, &hdr, sizeof (struct ar_hdr));
ared->parsed_size = parsed_size;
char *
_bfd_append_relative_path (bfd *arch, char *elt_name)
{
- const char *arch_name = arch->filename;
+ const char *arch_name = bfd_get_filename (arch);
const char *base_name = lbasename (arch_name);
size_t prefix_len;
char *filename;
return (bfd *) _bfd_ptr_bfd_null_error (archive);
}
-const bfd_target *
+bfd_cleanup
bfd_generic_archive_p (bfd *abfd)
{
struct artdata *tdata_hold;
char armag[SARMAG + 1];
- bfd_size_type amt;
+ size_t amt;
if (bfd_bread (armag, SARMAG, abfd) != SARMAG)
{
return NULL;
}
- bfd_is_thin_archive (abfd) = (strncmp (armag, ARMAGT, SARMAG) == 0);
+ bfd_set_thin_archive (abfd, strncmp (armag, ARMAGT, SARMAG) == 0);
if (strncmp (armag, ARMAG, SARMAG) != 0
&& ! bfd_is_thin_archive (abfd))
}
}
- return abfd->xvec;
+ return _bfd_no_cleanup;
}
/* Some constants for a 32 bit BSD archive structure. We do not
do_slurp_bsd_armap (bfd *abfd)
{
struct areltdata *mapdata;
- unsigned int counter;
+ size_t counter;
bfd_byte *raw_armap, *rbase;
struct artdata *ardata = bfd_ardata (abfd);
char *stringbase;
- bfd_size_type parsed_size, amt;
+ bfd_size_type parsed_size;
+ size_t amt, string_size;
carsym *set;
mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
free (mapdata);
/* PR 17512: file: 883ff754. */
/* PR 17512: file: 0458885f. */
- if (parsed_size < 4)
- return FALSE;
-
- raw_armap = (bfd_byte *) bfd_zalloc (abfd, parsed_size);
- if (raw_armap == NULL)
- return FALSE;
-
- if (bfd_bread (raw_armap, parsed_size, abfd) != parsed_size)
+ if (parsed_size < BSD_SYMDEF_COUNT_SIZE + BSD_STRING_COUNT_SIZE)
{
- if (bfd_get_error () != bfd_error_system_call)
- bfd_set_error (bfd_error_malformed_archive);
- byebye:
- bfd_release (abfd, raw_armap);
+ bfd_set_error (bfd_error_malformed_archive);
return FALSE;
}
- ardata->symdef_count = H_GET_32 (abfd, raw_armap) / BSD_SYMDEF_SIZE;
- if (ardata->symdef_count * BSD_SYMDEF_SIZE >
- parsed_size - BSD_SYMDEF_COUNT_SIZE)
+ raw_armap = (bfd_byte *) _bfd_alloc_and_read (abfd, parsed_size, parsed_size);
+ if (raw_armap == NULL)
+ return FALSE;
+
+ parsed_size -= BSD_SYMDEF_COUNT_SIZE + BSD_STRING_COUNT_SIZE;
+ amt = H_GET_32 (abfd, raw_armap);
+ if (amt > parsed_size
+ || amt % BSD_SYMDEF_SIZE != 0)
{
/* Probably we're using the wrong byte ordering. */
bfd_set_error (bfd_error_wrong_format);
- goto byebye;
+ goto release_armap;
}
rbase = raw_armap + BSD_SYMDEF_COUNT_SIZE;
- stringbase = ((char *) rbase
- + ardata->symdef_count * BSD_SYMDEF_SIZE
- + BSD_STRING_COUNT_SIZE);
- amt = ardata->symdef_count * sizeof (carsym);
+ stringbase = (char *) rbase + amt + BSD_STRING_COUNT_SIZE;
+ string_size = parsed_size - amt;
+
+ ardata->symdef_count = amt / BSD_SYMDEF_SIZE;
+ if (_bfd_mul_overflow (ardata->symdef_count, sizeof (carsym), &amt))
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto release_armap;
+ }
ardata->symdefs = (struct carsym *) bfd_alloc (abfd, amt);
if (!ardata->symdefs)
- return FALSE;
+ goto release_armap;
for (counter = 0, set = ardata->symdefs;
counter < ardata->symdef_count;
counter++, set++, rbase += BSD_SYMDEF_SIZE)
{
- set->name = H_GET_32 (abfd, rbase) + stringbase;
+ unsigned nameoff = H_GET_32 (abfd, rbase);
+ if (nameoff >= string_size)
+ {
+ bfd_set_error (bfd_error_malformed_archive);
+ goto release_armap;
+ }
+ set->name = stringbase + nameoff;
set->file_offset = H_GET_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE);
}
to be allocated on an objalloc anyway... */
abfd->has_armap = TRUE;
return TRUE;
+
+ release_armap:
+ ardata->symdef_count = 0;
+ ardata->symdefs = NULL;
+ bfd_release (abfd, raw_armap);
+ return FALSE;
}
/* Read a COFF archive symbol table. Returns FALSE on error, TRUE
char *stringend;
bfd_size_type stringsize;
bfd_size_type parsed_size;
+ ufile_ptr filesize;
+ size_t nsymz, carsym_size, ptrsize, i;
carsym *carsyms;
- bfd_size_type nsymz; /* Number of symbols in armap. */
bfd_vma (*swap) (const void *);
- char int_buf[sizeof (long)];
- bfd_size_type carsym_size, ptrsize;
- unsigned int i;
+ char int_buf[4];
+ struct areltdata *tmp;
mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
if (mapdata == NULL)
free (mapdata);
if (bfd_bread (int_buf, 4, abfd) != 4)
- {
- if (bfd_get_error () != bfd_error_system_call)
- bfd_set_error (bfd_error_malformed_archive);
- return FALSE;
- }
+ return FALSE;
+
/* It seems that all numeric information in a coff archive is always
- in big endian format, nomatter the host or target. */
+ in big endian format, no matter the host or target. */
swap = bfd_getb32;
nsymz = bfd_getb32 (int_buf);
- stringsize = parsed_size - (4 * nsymz) - 4;
/* The coff armap must be read sequentially. So we construct a
bsd-style one in core all at once, for simplicity. */
- if (nsymz > ~ (bfd_size_type) 0 / sizeof (carsym))
- return FALSE;
+ if (_bfd_mul_overflow (nsymz, sizeof (carsym), &carsym_size))
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return FALSE;
+ }
+
+ filesize = bfd_get_file_size (abfd);
+ ptrsize = 4 * nsymz;
+ if ((filesize != 0 && parsed_size > filesize)
+ || parsed_size < 4
+ || parsed_size - 4 < ptrsize)
+ {
+ bfd_set_error (bfd_error_malformed_archive);
+ return FALSE;
+ }
- carsym_size = (nsymz * sizeof (carsym));
- ptrsize = (4 * nsymz);
+ stringsize = parsed_size - ptrsize - 4;
if (carsym_size + stringsize + 1 <= carsym_size)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return FALSE;
+ }
+
+ /* Allocate and read in the raw offsets. */
+ raw_armap = (int *) _bfd_malloc_and_read (abfd, ptrsize, ptrsize);
+ if (raw_armap == NULL)
return FALSE;
- ardata->symdefs = (struct carsym *) bfd_zalloc (abfd,
- carsym_size + stringsize + 1);
+ ardata->symdefs = (struct carsym *) bfd_alloc (abfd,
+ carsym_size + stringsize + 1);
if (ardata->symdefs == NULL)
- return FALSE;
+ goto free_armap;
carsyms = ardata->symdefs;
stringbase = ((char *) ardata->symdefs) + carsym_size;
- /* Allocate and read in the raw offsets. */
- raw_armap = (int *) bfd_alloc (abfd, ptrsize);
- if (raw_armap == NULL)
+ if (bfd_bread (stringbase, stringsize, abfd) != stringsize)
goto release_symdefs;
- if (bfd_bread (raw_armap, ptrsize, abfd) != ptrsize
- || (bfd_bread (stringbase, stringsize, abfd) != stringsize))
- {
- if (bfd_get_error () != bfd_error_system_call)
- bfd_set_error (bfd_error_malformed_archive);
- goto release_raw_armap;
- }
/* OK, build the carsyms. */
stringend = stringbase + stringsize;
ardata->first_file_filepos = bfd_tell (abfd);
/* Pad to an even boundary if you have to. */
ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
+ if (bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET) != 0)
+ goto release_symdefs;
abfd->has_armap = TRUE;
- bfd_release (abfd, raw_armap);
+ free (raw_armap);
/* Check for a second archive header (as used by PE). */
- {
- struct areltdata *tmp;
-
- bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET);
- tmp = (struct areltdata *) _bfd_read_ar_hdr (abfd);
- if (tmp != NULL)
- {
- if (tmp->arch_header[0] == '/'
- && tmp->arch_header[1] == ' ')
- {
- ardata->first_file_filepos +=
- (tmp->parsed_size + sizeof (struct ar_hdr) + 1) & ~(unsigned) 1;
- }
- free (tmp);
- }
- }
+ tmp = (struct areltdata *) _bfd_read_ar_hdr (abfd);
+ if (tmp != NULL)
+ {
+ if (tmp->arch_header[0] == '/'
+ && tmp->arch_header[1] == ' ')
+ ardata->first_file_filepos
+ += (tmp->parsed_size + sizeof (struct ar_hdr) + 1) & ~(unsigned) 1;
+ free (tmp);
+ }
return TRUE;
-release_raw_armap:
- bfd_release (abfd, raw_armap);
-release_symdefs:
+ release_symdefs:
bfd_release (abfd, (ardata)->symdefs);
+ free_armap:
+ free (raw_armap);
return FALSE;
}
_bfd_slurp_extended_name_table (bfd *abfd)
{
char nextname[17];
- struct areltdata *namedata;
- bfd_size_type amt;
/* FIXME: Formatting sucks here, and in case of failure of BFD_READ,
we probably don't want to return TRUE. */
if (bfd_bread (nextname, 16, abfd) == 16)
{
+ struct areltdata *namedata;
+ bfd_size_type amt;
+ ufile_ptr filesize;
+
if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
return FALSE;
if (namedata == NULL)
return FALSE;
+ filesize = bfd_get_file_size (abfd);
amt = namedata->parsed_size;
- if (amt + 1 == 0)
- goto byebye;
+ if (amt + 1 == 0 || (filesize != 0 && amt > filesize))
+ {
+ bfd_set_error (bfd_error_malformed_archive);
+ goto byebye;
+ }
bfd_ardata (abfd)->extended_names_size = amt;
- bfd_ardata (abfd)->extended_names = (char *) bfd_zalloc (abfd, amt + 1);
+ bfd_ardata (abfd)->extended_names = (char *) bfd_alloc (abfd, amt + 1);
if (bfd_ardata (abfd)->extended_names == NULL)
{
byebye:
bfd_ardata (abfd)->extended_names = NULL;
goto byebye;
}
+ bfd_ardata (abfd)->extended_names[amt] = 0;
/* Since the archive is supposed to be printable if it contains
text, the entries in the list are newline-padded, not null
const char *last;
char *copy;
+ if (abfd->flags & BFD_ARCHIVE_FULL_PATH)
+ return file;
+
first = file + strlen (file) - 1;
last = first + 1;
#else
static const char *
-normalize (bfd *abfd ATTRIBUTE_UNUSED, const char *file)
+normalize (bfd *abfd, const char *file)
{
+ if (abfd->flags & BFD_ARCHIVE_FULL_PATH)
+ return file;
return lbasename (file);
}
#endif
if (bfd_is_thin_archive (abfd))
{
- const char *filename = current->filename;
+ const char *filename = bfd_get_filename (current);
/* If the element being added is a member of another archive
(i.e., we are flattening), use the containing archive's name. */
if (current->my_archive
&& ! bfd_is_thin_archive (current->my_archive))
- filename = current->my_archive->filename;
+ filename = bfd_get_filename (current->my_archive);
/* If the path is the same as the previous path seen,
reuse it. This can happen when flattening a thin
/* If the path is relative, adjust it relative to
the containing archive. */
if (! IS_ABSOLUTE_PATH (filename)
- && ! IS_ABSOLUTE_PATH (abfd->filename))
- normal = adjust_relative_path (filename, abfd->filename);
+ && ! IS_ABSOLUTE_PATH (bfd_get_filename (abfd)))
+ normal = adjust_relative_path (filename, bfd_get_filename (abfd));
else
normal = filename;
continue;
}
- normal = normalize (current, current->filename);
+ normal = normalize (abfd, bfd_get_filename (current));
if (normal == NULL)
return FALSE;
if (total_namelen == 0)
return TRUE;
- *tabloc = (char *) bfd_zalloc (abfd, total_namelen);
+ *tabloc = (char *) bfd_alloc (abfd, total_namelen);
if (*tabloc == NULL)
return FALSE;
const char *normal;
unsigned int thislen;
long stroff;
- const char *filename = current->filename;
+ const char *filename = bfd_get_filename (current);
if (bfd_is_thin_archive (abfd))
{
(i.e., we are flattening), use the containing archive's name. */
if (current->my_archive
&& ! bfd_is_thin_archive (current->my_archive))
- filename = current->my_archive->filename;
+ filename = bfd_get_filename (current->my_archive);
/* If the path is the same as the previous path seen,
reuse it. This can happen when flattening a thin
archive that contains other archives.
if (last_filename && filename_cmp (last_filename, filename) == 0)
normal = last_filename;
else if (! IS_ABSOLUTE_PATH (filename)
- && ! IS_ABSOLUTE_PATH (abfd->filename))
- normal = adjust_relative_path (filename, abfd->filename);
+ && ! IS_ABSOLUTE_PATH (bfd_get_filename (abfd)))
+ normal = adjust_relative_path (filename, bfd_get_filename (abfd));
else
normal = filename;
}
else
{
- normal = normalize (current, filename);
+ normal = normalize (abfd, filename);
if (normal == NULL)
return FALSE;
}
stroff = last_stroff;
else
{
- strcpy (strptr, normal);
- if (! trailing_slash)
- strptr[thislen] = ARFMAG[1];
- else
- {
- strptr[thislen] = '/';
- strptr[thislen + 1] = ARFMAG[1];
- }
+ last_filename = filename;
stroff = strptr - *tabloc;
last_stroff = stroff;
+ memcpy (strptr, normal, thislen);
+ strptr += thislen;
+ if (trailing_slash)
+ *strptr++ = '/';
+ *strptr++ = ARFMAG[1];
}
hdr->ar_name[0] = ar_padchar (current);
if (bfd_is_thin_archive (abfd) && current->origin > 0)
}
else
_bfd_ar_spacepad (hdr->ar_name + 1, maxname - 1, "%-ld", stroff);
- if (normal != last_filename)
- {
- strptr += thislen + 1;
- if (trailing_slash)
- ++strptr;
- last_filename = filename;
- }
}
}
current != NULL;
current = current->archive_next)
{
- const char *normal = normalize (current, current->filename);
+ const char *normal = normalize (abfd, bfd_get_filename (current));
int has_space = 0;
unsigned int len;
if (is_bsd44_extended_name (hdr->ar_name))
{
/* This is a BSD 4.4 extended name. */
- const char *fullname = normalize (abfd, abfd->filename);
+ const char *fullname = normalize (abfd, bfd_get_filename (abfd));
unsigned int len = strlen (fullname);
unsigned int padded_len = (len + 3) & ~3;
struct stat status;
struct areltdata *ared;
struct ar_hdr *hdr;
- bfd_size_type amt;
+ size_t amt;
if (member && (member->flags & BFD_IN_MEMORY) != 0)
{
if (!current->arelt_data)
{
current->arelt_data =
- bfd_ar_hdr_from_filesystem (arch, current->filename, current);
+ bfd_ar_hdr_from_filesystem (arch, bfd_get_filename (current),
+ current);
if (!current->arelt_data)
goto input_err;
/* Put in the file name. */
BFD_SEND (arch, _bfd_truncate_arname,
- (arch, current->filename, (char *) arch_hdr (current)));
+ (arch, bfd_get_filename (current),
+ (char *) arch_hdr (current)));
}
if (makemap && ! hasobjects)
while (remaining)
{
- unsigned int amt = DEFAULT_BUFFERSIZE;
+ size_t amt = DEFAULT_BUFFERSIZE;
if (amt > remaining)
amt = remaining;
errno = 0;
if (bfd_bread (buffer, amt, current) != amt)
- {
- if (bfd_get_error () != bfd_error_system_call)
- bfd_set_error (bfd_error_file_truncated);
- goto input_err;
- }
+ goto input_err;
if (bfd_bwrite (buffer, amt, arch) != amt)
return FALSE;
remaining -= amt;
asymbol **syms = NULL;
long syms_max = 0;
bfd_boolean ret;
- bfd_size_type amt;
+ size_t amt;
static bfd_boolean report_plugin_err = TRUE;
/* Dunno if this is the best place for this info... */
/* Drop all the files called __.SYMDEF, we're going to make our own. */
while (arch->archive_head
- && strcmp (arch->archive_head->filename, "__.SYMDEF") == 0)
+ && strcmp (bfd_get_filename (arch->archive_head), "__.SYMDEF") == 0)
arch->archive_head = arch->archive_head->archive_next;
/* Map over each element. */
{
struct stat statbuf;
- if (stat (arch->filename, &statbuf) == 0)
+ if (stat (bfd_get_filename (arch), &statbuf) == 0)
bfd_ardata (arch)->armap_timestamp = (statbuf.st_mtime
+ ARMAP_TIME_OFFSET);
uid = getuid();