From 97c0a07968a7c64e1de96abff8937d089f09b3e7 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Fri, 2 Aug 2019 12:35:39 +0930 Subject: [PATCH] PR24871, readelf segv in dump_ia64_unwind PR 24871 * readelf.c (ABSADDR): Delete. (dump_ia64_unwind): Expand ABSADDR. Check validity of info.section. --- binutils/ChangeLog | 6 ++++++ binutils/readelf.c | 22 +++++++++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index f3be2641f15..f3dc48c85df 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,9 @@ +2019-08-02 Alan Modra + + PR 24871 + * readelf.c (ABSADDR): Delete. + (dump_ia64_unwind): Expand ABSADDR. Check validity of info.section. + 2019-07-29 Martin Liska PR 24768 diff --git a/binutils/readelf.c b/binutils/readelf.c index 6175b330179..b896ad9f406 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -7415,11 +7415,6 @@ struct absaddr bfd_vma offset; }; -#define ABSADDR(a) \ - ((a).section \ - ? filedata->section_headers [(a).section].sh_addr + (a).offset \ - : (a).offset) - /* Find the nearest symbol at or below ADDR. Returns the symbol name, if found, and the offset from the symbol to ADDR. */ @@ -7565,8 +7560,21 @@ dump_ia64_unwind (Filedata * filedata, struct ia64_unw_aux_info * aux) if (aux->info == NULL) continue; + offset = tp->info.offset; + if (tp->info.section) + { + if (tp->info.section >= filedata->file_header.e_shnum) + { + warn (_("Invalid section %u in table entry %ld\n"), + tp->info.section, (long) (tp - aux->table)); + res = FALSE; + continue; + } + offset += filedata->section_headers[tp->info.section].sh_addr; + } + offset -= aux->info_addr; /* PR 17531: file: 0997b4d1. */ - if ((ABSADDR (tp->info) - aux->info_addr) >= aux->info_size) + if (offset >= aux->info_size) { warn (_("Invalid offset %lx in table entry %ld\n"), (long) tp->info.offset, (long) (tp - aux->table)); @@ -7574,7 +7582,7 @@ dump_ia64_unwind (Filedata * filedata, struct ia64_unw_aux_info * aux) continue; } - head = aux->info + (ABSADDR (tp->info) - aux->info_addr); + head = aux->info + offset; stamp = byte_get ((unsigned char *) head, sizeof (stamp)); printf (" v%u, flags=0x%lx (%s%s), len=%lu bytes\n", -- 2.30.2