From acb56a83016611bcb5f0a32368fddc8c213f7dd0 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Mon, 19 Jun 2017 14:06:53 +0100 Subject: [PATCH] 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. --- 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 6aa4c9099f7..e7185172c1d 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,15 @@ +2017-06-19 Nick Clifton + + 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 PR binutils/21611 diff --git a/bfd/ieee.c b/bfd/ieee.c index d5220b6ab15..08d08d4eecb 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 ace4ed3f889..8a07248304a 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; -- 2.30.2