aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2020-03-24 17:26:40 +1030
committerAlan Modra <amodra@gmail.com>2020-03-24 19:00:35 +1030
commit65109548f8fb13ac4a6c3311ea46a8b69c548576 (patch)
treecc7539657dcfe380b7090334d733e9ec4a4bbd98 /bfd/archive.c
parentreadelf memory leak in process_mips_specific (diff)
downloadbinutils-gdb-65109548f8fb13ac4a6c3311ea46a8b69c548576.tar.gz
binutils-gdb-65109548f8fb13ac4a6c3311ea46a8b69c548576.tar.bz2
binutils-gdb-65109548f8fb13ac4a6c3311ea46a8b69c548576.zip
Overlarge allocation in _bfd_generic_read_ar_hdr_mag
* archive.c (_bfd_generic_read_ar_hdr_mag): Sanity check extended name size. Use bfd_malloc rather than bfd_zmalloc, clearing just struct areltdata.
Diffstat (limited to 'bfd/archive.c')
-rw-r--r--bfd/archive.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/bfd/archive.c b/bfd/archive.c
index 0c009f10de8..3423a336956 100644
--- a/bfd/archive.c
+++ b/bfd/archive.c
@@ -488,6 +488,7 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
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;
@@ -538,11 +539,19 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
{
/* 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
@@ -586,13 +595,13 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
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;