171 lines
4.9 KiB
Diff
171 lines
4.9 KiB
Diff
From 3a551c7a1b80fca579461774860574eabfd7f18f Mon Sep 17 00:00:00 2001
|
||
From: Alan Modra <amodra@gmail.com>
|
||
Date: Sun, 16 Dec 2018 23:02:50 +1030
|
||
Subject: [PATCH] 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.
|
||
url:https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=3a551c7a1b80fca579461774860574eabfd7f18f
|
||
diff --git a/bfd/aoutx.h b/bfd/aoutx.h
|
||
index 023843b0be..78eaa9c503 100644
|
||
--- a/bfd/aoutx.h
|
||
+++ b/bfd/aoutx.h
|
||
@@ -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);
|
||
-
|
||
- 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;
|
||
+ 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;
|
||
+ }
|
||
|
||
- 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
|
||
diff --git a/bfd/elf.c b/bfd/elf.c
|
||
index 688429b73e..b10dcd83c5 100644
|
||
--- a/bfd/elf.c
|
||
+++ b/bfd/elf.c
|
||
@@ -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
|
||
--
|
||
2.19.1
|
||
|