PR23994, libbfd integer overflow

PR 23994
	* aoutx.h: Include limits.h.
	(get_reloc_upper_bound): Detect long overflow and return a file
	too big error if it occurs.
	* elf.c: Include limits.h.
	(_bfd_elf_get_symtab_upper_bound): Detect long overflow and return
	a file too big error if it occurs.
	(_bfd_elf_get_dynamic_symtab_upper_bound): Likewise.
	(_bfd_elf_get_dynamic_reloc_upper_bound): Likewise.
This commit is contained in:
Alan Modra 2018-12-16 23:02:50 +10:30
parent 40b9228581
commit 3a551c7a1b
3 changed files with 57 additions and 27 deletions

View File

@ -1,3 +1,15 @@
2018-12-17 Alan Modra <amodra@gmail.com>
PR 23994
* aoutx.h: Include limits.h.
(get_reloc_upper_bound): Detect long overflow and return a file
too big error if it occurs.
* elf.c: Include limits.h.
(_bfd_elf_get_symtab_upper_bound): Detect long overflow and return
a file too big error if it occurs.
(_bfd_elf_get_dynamic_symtab_upper_bound): Likewise.
(_bfd_elf_get_dynamic_reloc_upper_bound): Likewise.
2018-12-14 H.J. Lu <hongjiu.lu@intel.com>
PR ld/23900

View File

@ -117,6 +117,7 @@ DESCRIPTION
#define KEEPIT udata.i
#include "sysdep.h"
#include <limits.h>
#include "bfd.h"
#include "safe-ctype.h"
#include "bfdlink.h"
@ -2491,6 +2492,8 @@ NAME (aout, canonicalize_reloc) (bfd *abfd,
long
NAME (aout, get_reloc_upper_bound) (bfd *abfd, sec_ptr asect)
{
bfd_size_type count;
if (bfd_get_format (abfd) != bfd_object)
{
bfd_set_error (bfd_error_invalid_operation);
@ -2498,26 +2501,25 @@ NAME (aout, get_reloc_upper_bound) (bfd *abfd, sec_ptr asect)
}
if (asect->flags & SEC_CONSTRUCTOR)
return sizeof (arelent *) * (asect->reloc_count + 1);
count = asect->reloc_count;
else if (asect == obj_datasec (abfd))
count = exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd);
else if (asect == obj_textsec (abfd))
count = exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd);
else if (asect == obj_bsssec (abfd))
count = 0;
else
{
bfd_set_error (bfd_error_invalid_operation);
return -1;
}
if (asect == obj_datasec (abfd))
return sizeof (arelent *)
* ((exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd))
+ 1);
if (asect == obj_textsec (abfd))
return sizeof (arelent *)
* ((exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd))
+ 1);
if (asect == obj_bsssec (abfd))
return sizeof (arelent *);
if (asect == obj_bsssec (abfd))
return 0;
bfd_set_error (bfd_error_invalid_operation);
return -1;
if (count >= LONG_MAX / sizeof (arelent *))
{
bfd_set_error (bfd_error_file_too_big);
return -1;
}
return (count + 1) * sizeof (arelent *);
}
long

View File

@ -35,6 +35,7 @@ SECTION
/* For sparc64-cross-sparc32. */
#define _SYSCALL32
#include "sysdep.h"
#include <limits.h>
#include "bfd.h"
#include "bfdlink.h"
#include "libbfd.h"
@ -8215,11 +8216,16 @@ error_return:
long
_bfd_elf_get_symtab_upper_bound (bfd *abfd)
{
long symcount;
bfd_size_type symcount;
long symtab_size;
Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->symtab_hdr;
symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym;
if (symcount >= LONG_MAX / sizeof (asymbol *))
{
bfd_set_error (bfd_error_file_too_big);
return -1;
}
symtab_size = (symcount + 1) * (sizeof (asymbol *));
if (symcount > 0)
symtab_size -= sizeof (asymbol *);
@ -8230,7 +8236,7 @@ _bfd_elf_get_symtab_upper_bound (bfd *abfd)
long
_bfd_elf_get_dynamic_symtab_upper_bound (bfd *abfd)
{
long symcount;
bfd_size_type symcount;
long symtab_size;
Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->dynsymtab_hdr;
@ -8241,6 +8247,11 @@ _bfd_elf_get_dynamic_symtab_upper_bound (bfd *abfd)
}
symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym;
if (symcount >= LONG_MAX / sizeof (asymbol *))
{
bfd_set_error (bfd_error_file_too_big);
return -1;
}
symtab_size = (symcount + 1) * (sizeof (asymbol *));
if (symcount > 0)
symtab_size -= sizeof (asymbol *);
@ -8310,7 +8321,7 @@ _bfd_elf_canonicalize_dynamic_symtab (bfd *abfd,
long
_bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd)
{
long ret;
bfd_size_type count;
asection *s;
if (elf_dynsymtab (abfd) == 0)
@ -8319,15 +8330,20 @@ _bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd)
return -1;
}
ret = sizeof (arelent *);
count = 1;
for (s = abfd->sections; s != NULL; s = s->next)
if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
&& (elf_section_data (s)->this_hdr.sh_type == SHT_REL
|| elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
ret += ((s->size / elf_section_data (s)->this_hdr.sh_entsize)
* sizeof (arelent *));
return ret;
{
count += s->size / elf_section_data (s)->this_hdr.sh_entsize;
if (count > LONG_MAX / sizeof (arelent *))
{
bfd_set_error (bfd_error_file_too_big);
return -1;
}
}
return count * sizeof (arelent *);
}
/* Canonicalize the dynamic relocation entries. Note that we return the