aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2020-02-25 12:48:43 +1030
committerAlan Modra <amodra@gmail.com>2020-02-26 10:37:13 +1030
commitb570b954bc5c1d6a6edb363c7bdba814bc1fd174 (patch)
treea7afa03ea8b4b9383264005d4f29413931a7468d
parent24a15046c0ccc7fb7b95da1bb72fa66ad6bf6382 (diff)
downloadgdb-b570b954bc5c1d6a6edb363c7bdba814bc1fd174.zip
gdb-b570b954bc5c1d6a6edb363c7bdba814bc1fd174.tar.gz
gdb-b570b954bc5c1d6a6edb363c7bdba814bc1fd174.tar.bz2
Limit bogus archive parsed_size
Archive element size is given by data in the archive, and thus is subject to attack by fuzzers. The only harm this allows is allocation of huge amounts of memory, but some systems don't handle that well. So limit archive element size to archive file size. * bfdio.c (bfd_get_file_size): Ignore bogus archive element sizes.
-rw-r--r--bfd/ChangeLog4
-rw-r--r--bfd/bfdio.c18
2 files changed, 20 insertions, 2 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 7e8e454..5855df7 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,7 @@
+2020-02-26 Alan Modra <amodra@gmail.com>
+
+ * bfdio.c (bfd_get_file_size): Ignore bogus archive element sizes.
+
2020-02-25 H.J. Lu <hongjiu.lu@intel.com>
PR binutils/25584
diff --git a/bfd/bfdio.c b/bfd/bfdio.c
index 49e0958..71ac17e 100644
--- a/bfd/bfdio.c
+++ b/bfd/bfdio.c
@@ -25,6 +25,7 @@
#include <limits.h>
#include "bfd.h"
#include "libbfd.h"
+#include "aout/ar.h"
#ifndef S_IXUSR
#define S_IXUSR 0100 /* Execute by owner. */
@@ -460,11 +461,24 @@ DESCRIPTION
ufile_ptr
bfd_get_file_size (bfd *abfd)
{
+ ufile_ptr file_size, archive_size = (ufile_ptr) -1;
+
if (abfd->my_archive != NULL
&& !bfd_is_thin_archive (abfd->my_archive))
- return arelt_size (abfd);
+ {
+ struct areltdata *adata = (struct areltdata *) abfd->arelt_data;
+ archive_size = adata->parsed_size;
+ /* If the archive is compressed we can't compare against file size. */
+ if (memcmp (((struct ar_hdr *) adata->arch_header)->ar_fmag,
+ "Z\012", 2) == 0)
+ return archive_size;
+ abfd = abfd->my_archive;
+ }
- return bfd_get_size (abfd);
+ file_size = bfd_get_size (abfd);
+ if (archive_size < file_size)
+ return archive_size;
+ return file_size;
}
/*