This is the mail archive of the
binutils-cvs@sourceware.org
mailing list for the binutils project.
[binutils-gdb] Fix access violation when parsing a corrupt IEEE binary.
- From: Nick Clifton <nickc at sourceware dot org>
- To: bfd-cvs at sourceware dot org
- Date: 19 Jun 2017 13:07:22 -0000
- Subject: [binutils-gdb] Fix access violation when parsing a corrupt IEEE binary.
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=acb56a83016611bcb5f0a32368fddc8c213f7dd0
commit acb56a83016611bcb5f0a32368fddc8c213f7dd0
Author: Nick Clifton <nickc@redhat.com>
Date: Mon Jun 19 14:06:53 2017 +0100
Fix access violation when parsing a corrupt IEEE binary.
PR binutils/21612
* libieee.h (struct common_header_type): Add end_p field.
* ieee.c (this_byte_and_next): Do not advance input_p beyond
end_p.
(read_id): Check for a length that exceeds the remaining bytes in
the input buffer.
(ieee_seek): Initialise end_p.
(ieee_archive_p): Likewise.
(ieee_object_p): Likewise.
Diff:
---
bfd/ChangeLog | 12 ++++++++++++
bfd/ieee.c | 23 ++++++++++++++++++++---
bfd/libieee.h | 1 +
3 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 6aa4c90..e718517 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,17 @@
2017-06-19 Nick Clifton <nickc@redhat.com>
+ PR binutils/21612
+ * libieee.h (struct common_header_type): Add end_p field.
+ * ieee.c (this_byte_and_next): Do not advance input_p beyond
+ end_p.
+ (read_id): Check for a length that exceeds the remaining bytes in
+ the input buffer.
+ (ieee_seek): Initialise end_p.
+ (ieee_archive_p): Likewise.
+ (ieee_object_p): Likewise.
+
+2017-06-19 Nick Clifton <nickc@redhat.com>
+
PR binutils/21611
* vms-alpha.c (_bfd_vms_slurp_eihs): Check for invalid offset
before reading the EIHS structure entries.
diff --git a/bfd/ieee.c b/bfd/ieee.c
index d5220b6..08d08d4 100644
--- a/bfd/ieee.c
+++ b/bfd/ieee.c
@@ -170,7 +170,7 @@ ieee_write_id (bfd *abfd, const char *id)
standard requires. */
#define this_byte(ieee) *((ieee)->input_p)
-#define this_byte_and_next(ieee) (*((ieee)->input_p++))
+#define this_byte_and_next(ieee) ((ieee)->input_p < (ieee)->end_p ? *((ieee)->input_p++) : 0)
static bfd_boolean
next_byte (common_header_type * ieee)
@@ -220,6 +220,15 @@ read_id (common_header_type *ieee)
length = (length * 256) + this_byte_and_next (ieee);
}
+ /* PR 21612: Check for an invalid length. */
+ if (ieee->input_p + length >= ieee->end_p)
+ {
+ _bfd_error_handler (_("IEEE parser: string length: %#lx longer than buffer: %#lx"),
+ length, (long) (ieee->end_p - ieee->input_p));
+ bfd_set_error (bfd_error_invalid_operation);
+ return NULL;
+ }
+
/* Buy memory and read string. */
string = bfd_alloc (ieee->abfd, (bfd_size_type) length + 1);
if (!string)
@@ -699,12 +708,12 @@ ieee_seek (ieee_data_type * ieee, file_ptr offset)
if (offset < 0 || (bfd_size_type) offset >= ieee->h.total_amt)
{
ieee->h.input_p = ieee->h.first_byte + ieee->h.total_amt;
- ieee->h.last_byte = ieee->h.input_p;
+ ieee->h.end_p = ieee->h.last_byte = ieee->h.input_p;
return FALSE;
}
ieee->h.input_p = ieee->h.first_byte + offset;
- ieee->h.last_byte = (ieee->h.first_byte + ieee_part_after (ieee, offset));
+ ieee->h.end_p = ieee->h.last_byte = (ieee->h.first_byte + ieee_part_after (ieee, offset));
return TRUE;
}
@@ -1375,6 +1384,8 @@ ieee_archive_p (bfd *abfd)
ieee->h.first_byte = buffer;
ieee->h.input_p = buffer;
+ ieee->h.total_amt = sizeof (buffer);
+ ieee->h.end_p = buffer + sizeof (buffer);
ieee->h.abfd = abfd;
@@ -1442,6 +1453,8 @@ ieee_archive_p (bfd *abfd)
bfd_bread ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd);
ieee->h.first_byte = buffer;
ieee->h.input_p = buffer;
+ ieee->h.total_amt = sizeof (buffer);
+ ieee->h.end_p = buffer + sizeof (buffer);
}
}
@@ -1465,6 +1478,8 @@ ieee_archive_p (bfd *abfd)
bfd_bread ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd);
ieee->h.first_byte = buffer;
ieee->h.input_p = buffer;
+ ieee->h.total_amt = sizeof (buffer);
+ ieee->h.end_p = buffer + sizeof (buffer);
(void) next_byte (&(ieee->h)); /* Drop F8. */
if (! next_byte (&(ieee->h))) /* Drop 14. */
@@ -1890,6 +1905,8 @@ ieee_object_p (bfd *abfd)
ieee->h.input_p = buffer;
ieee->h.total_amt = sizeof (buffer);
+ ieee->h.end_p = buffer + sizeof (buffer);
+
if (this_byte_and_next (&(ieee->h)) != Module_Beginning)
goto got_wrong_format;
diff --git a/bfd/libieee.h b/bfd/libieee.h
index ace4ed3..8a07248 100644
--- a/bfd/libieee.h
+++ b/bfd/libieee.h
@@ -64,6 +64,7 @@ typedef struct ieee_per_section
typedef struct {
unsigned char *input_p;
+ unsigned char *end_p;
unsigned char *first_byte;
unsigned char *last_byte;
bfd_size_type total_amt;