From 4978e369fb75a8b7756bf4201668b2a9d9556286 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 18 Nov 2015 22:12:23 +1030 Subject: [PATCH] Prevent looping in archives PR 19256 * archive.c (bfd_generic_openr_next_archived_file): Don't allow backward file movement via "negative" sizes. * coff-alpha.c (alpha_ecoff_openr_next_archived_file): Likewise. --- bfd/ChangeLog | 7 +++++++ bfd/archive.c | 24 ++++++++++++++++-------- bfd/coff-alpha.c | 8 +++++++- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 46a2cafdc8..b70456dcee 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2015-11-18 Alan Modra + + PR 19256 + * archive.c (bfd_generic_openr_next_archived_file): Don't allow + backward file movement via "negative" sizes. + * coff-alpha.c (alpha_ecoff_openr_next_archived_file): Likewise. + 2015-11-18 Tristan Gingold * mach-o.h (struct mach_o_data_struct): Add hdr_offset field. diff --git a/bfd/archive.c b/bfd/archive.c index 1715474ea6..b3d03d36da 100644 --- a/bfd/archive.c +++ b/bfd/archive.c @@ -786,21 +786,29 @@ bfd_openr_next_archived_file (bfd *archive, bfd *last_file) bfd * bfd_generic_openr_next_archived_file (bfd *archive, bfd *last_file) { - file_ptr filestart; + ufile_ptr filestart; if (!last_file) filestart = bfd_ardata (archive)->first_file_filepos; else { - bfd_size_type size = arelt_size (last_file); - filestart = last_file->proxy_origin; if (! bfd_is_thin_archive (archive)) - filestart += size; - /* Pad to an even boundary... - Note that last_file->origin can be odd in the case of - BSD-4.4-style element with a long odd size. */ - filestart += filestart % 2; + { + bfd_size_type size = arelt_size (last_file); + + filestart += size; + /* Pad to an even boundary... + Note that last_file->origin can be odd in the case of + BSD-4.4-style element with a long odd size. */ + filestart += filestart % 2; + if (filestart <= last_file->proxy_origin) + { + /* Prevent looping. See PR19256. */ + bfd_set_error (bfd_error_malformed_archive); + return NULL; + } + } } return _bfd_get_elt_at_filepos (archive, filestart); diff --git a/bfd/coff-alpha.c b/bfd/coff-alpha.c index 58d4e1d1fb..7478f2f320 100644 --- a/bfd/coff-alpha.c +++ b/bfd/coff-alpha.c @@ -2187,7 +2187,7 @@ alpha_ecoff_get_elt_at_filepos (bfd *archive, file_ptr filepos) static bfd * alpha_ecoff_openr_next_archived_file (bfd *archive, bfd *last_file) { - file_ptr filestart; + ufile_ptr filestart; if (last_file == NULL) filestart = bfd_ardata (archive)->first_file_filepos; @@ -2208,6 +2208,12 @@ alpha_ecoff_openr_next_archived_file (bfd *archive, bfd *last_file) BSD-4.4-style element with a long odd size. */ filestart = last_file->proxy_origin + size; filestart += filestart % 2; + if (filestart <= last_file->proxy_origin) + { + /* Prevent looping. See PR19256. */ + bfd_set_error (bfd_error_malformed_archive); + return NULL; + } } return alpha_ecoff_get_elt_at_filepos (archive, filestart); -- 2.34.1