diff options
author | Nick Clifton <nickc@redhat.com> | 2019-03-14 14:45:32 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2019-03-14 14:45:32 +0000 |
commit | be22c732bf873e0c7e8a08564c97cafdfcf153bb (patch) | |
tree | 779aef5992f5920439e815d320be7f2038ace442 /bfd/elflink.c | |
parent | 3b336828de914a39741339b5341b88aa003d7225 (diff) | |
download | gdb-be22c732bf873e0c7e8a08564c97cafdfcf153bb.zip gdb-be22c732bf873e0c7e8a08564c97cafdfcf153bb.tar.gz gdb-be22c732bf873e0c7e8a08564c97cafdfcf153bb.tar.bz2 |
Fix illegal memory access parsing a corrupt ELF file.
PR 24332
* elflink.c (elf_link_add_object_symbols): Add new local variable
extversym_end. Initialise it to point to the end of the version
symbol table, if present. Check it when initialising and updating
the ever pointer.
Diffstat (limited to 'bfd/elflink.c')
-rw-r--r-- | bfd/elflink.c | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c index e50c0e4..3ac58da 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -3872,6 +3872,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) struct elf_link_hash_entry **sym_hash; bfd_boolean dynamic; Elf_External_Versym *extversym = NULL; + Elf_External_Versym *extversym_end = NULL; Elf_External_Versym *ever; struct elf_link_hash_entry *weaks; struct elf_link_hash_entry **nondeflt_vers = NULL; @@ -4297,13 +4298,14 @@ error_free_dyn: Elf_Internal_Shdr *versymhdr; versymhdr = &elf_tdata (abfd)->dynversym_hdr; - extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size); + amt = versymhdr->sh_size; + extversym = (Elf_External_Versym *) bfd_malloc (amt); if (extversym == NULL) goto error_free_sym; - amt = versymhdr->sh_size; if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0 || bfd_bread (extversym, amt, abfd) != amt) goto error_free_vers; + extversym_end = extversym + (amt / sizeof (* extversym)); } } @@ -4378,7 +4380,20 @@ error_free_dyn: } weaks = NULL; - ever = extversym != NULL ? extversym + extsymoff : NULL; + if (extversym == NULL) + ever = NULL; + else if (extversym + extsymoff < extversym_end) + ever = extversym + extsymoff; + else + { + /* xgettext:c-format */ + _bfd_error_handler (_("%pB: invalid version offset %lx (max %lx)"), + abfd, (long) extsymoff, + (long) (extversym_end - extversym) / sizeof (* extversym)); + bfd_set_error (bfd_error_bad_value); + goto error_free_vers; + } + for (isym = isymbuf, isymend = isymbuf + extsymcount; isym < isymend; isym++, sym_hash++, ever = (ever != NULL ? ever + 1 : NULL)) @@ -4562,6 +4577,14 @@ error_free_dyn: else iver.vs_vers = 0; } + else if (ever >= extversym_end) + { + /* xgettext:c-format */ + _bfd_error_handler (_("%pB: not enough version information"), + abfd); + bfd_set_error (bfd_error_bad_value); + goto error_free_vers; + } else _bfd_elf_swap_versym_in (abfd, ever, &iver); |