summaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2020-02-19 13:22:39 +1030
committerAlan Modra <amodra@gmail.com>2020-02-19 14:00:55 +1030
commit2c7c5554df19e410ea3a7d78b0c1435967a4bc62 (patch)
treeef0005f480637a4a474d1b23ff632caae8bf129c /bfd
parent2bb3687ba8720558082d1575823868286d7916b5 (diff)
downloadbinutils-gdb-2c7c5554df19e410ea3a7d78b0c1435967a4bc62.tar.gz
file size check in _bfd_alloc_and_read
* coffgen.c (_bfd_coff_get_external_symbols): Remove file size check. * elf.c (bfd_elf_get_str_section): Likewise. (_bfd_elf_slurp_version_tables): Likewise. * libbfd-in.h (_bfd_constant_p): Define. (_bfd_alloc_and_read, _bfd_malloc_and_read): Check read size against file size before allocating memory. * libbfd.h: Regenerate.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog10
-rw-r--r--bfd/coffgen.c8
-rw-r--r--bfd/elf.c14
-rw-r--r--bfd/libbfd-in.h30
-rw-r--r--bfd/libbfd.h30
5 files changed, 67 insertions, 25 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index f2ddd86a3c9..e68e5585052 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,15 @@
2020-02-19 Alan Modra <amodra@gmail.com>
+ * libbfd-in.h (_bfd_constant_p): Define.
+ (_bfd_alloc_and_read, _bfd_malloc_and_read): Check read size against
+ file size before allocating memory.
+ * coffgen.c (_bfd_coff_get_external_symbols): Remove file size check.
+ * elf.c (bfd_elf_get_str_section): Likewise.
+ (_bfd_elf_slurp_version_tables): Likewise.
+ * libbfd.h: Regenerate.
+
+2020-02-19 Alan Modra <amodra@gmail.com>
+
* libbfd-in.h (_bfd_alloc_and_read, _bfd_malloc_and_read): New.
* aoutx.h (aout_get_external_symbols): Replace calls to
bfd_[m]alloc and bfd_bread with call to _bfd_[m]alloc_and_read.
diff --git a/bfd/coffgen.c b/bfd/coffgen.c
index dda98394f11..daaaba95c58 100644
--- a/bfd/coffgen.c
+++ b/bfd/coffgen.c
@@ -1632,20 +1632,14 @@ _bfd_coff_get_external_symbols (bfd *abfd)
size_t symesz;
size_t size;
void * syms;
- ufile_ptr filesize;
if (obj_coff_external_syms (abfd) != NULL)
return TRUE;
- /* Check for integer overflow and for unreasonable symbol counts. */
- filesize = bfd_get_file_size (abfd);
symesz = bfd_coff_symesz (abfd);
- if (_bfd_mul_overflow (obj_raw_syment_count (abfd), symesz, &size)
- || (filesize != 0 && size > filesize))
+ if (_bfd_mul_overflow (obj_raw_syment_count (abfd), symesz, &size))
{
bfd_set_error (bfd_error_file_truncated);
- _bfd_error_handler (_("%pB: corrupt symbol count: %#" PRIx64 ""),
- abfd, (uint64_t) obj_raw_syment_count (abfd));
return FALSE;
}
diff --git a/bfd/elf.c b/bfd/elf.c
index 7eb717b7ffa..deb93b0a5a9 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -296,7 +296,6 @@ bfd_elf_get_str_section (bfd *abfd, unsigned int shindex)
/* Allocate and clear an extra byte at the end, to prevent crashes
in case the string table is not terminated. */
if (shstrtabsize + 1 <= 1
- || shstrtabsize > bfd_get_file_size (abfd)
|| bfd_seek (abfd, offset, SEEK_SET) != 0
|| (shstrtab = _bfd_alloc_and_read (abfd, shstrtabsize + 1,
shstrtabsize)) == NULL)
@@ -8586,19 +8585,6 @@ error_return_verref:
goto error_return;
}
- ufile_ptr filesize = bfd_get_file_size (abfd);
- if (filesize > 0 && filesize < hdr->sh_size)
- {
- /* PR 24708: Avoid attempts to allocate a ridiculous amount
- of memory. */
- bfd_set_error (bfd_error_no_memory);
- _bfd_error_handler
- /* xgettext:c-format */
- (_("error: %pB version reference section is too large (%#" PRIx64 " bytes)"),
- abfd, (uint64_t) hdr->sh_size);
- goto error_return_verref;
- }
-
if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0)
goto error_return_verref;
contents = _bfd_malloc_and_read (abfd, hdr->sh_size, hdr->sh_size);
diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h
index a8f9bcd47d3..6d796b7ef89 100644
--- a/bfd/libbfd-in.h
+++ b/bfd/libbfd-in.h
@@ -904,10 +904,26 @@ extern bfd_vma _bfd_safe_read_leb128
((*res) = (a), (*res) *= (b), (b) != 0 && (*res) / (b) != (a))
#endif
+#ifdef __GNUC__
+#define _bfd_constant_p(v) __builtin_constant_p (v)
+#else
+#define _bfd_constant_p(v) 0
+#endif
+
static inline bfd_byte *
_bfd_alloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize)
{
- bfd_byte *mem = bfd_alloc (abfd, asize);
+ bfd_byte *mem;
+ if (!_bfd_constant_p (rsize))
+ {
+ ufile_ptr filesize = bfd_get_file_size (abfd);
+ if (filesize != 0 && rsize > filesize)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return NULL;
+ }
+ }
+ mem = bfd_alloc (abfd, asize);
if (mem != NULL)
{
if (bfd_bread (mem, rsize, abfd) == rsize)
@@ -920,7 +936,17 @@ _bfd_alloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize)
static inline bfd_byte *
_bfd_malloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize)
{
- bfd_byte *mem = bfd_malloc (asize);
+ bfd_byte *mem;
+ if (!_bfd_constant_p (rsize))
+ {
+ ufile_ptr filesize = bfd_get_file_size (abfd);
+ if (filesize != 0 && rsize > filesize)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return NULL;
+ }
+ }
+ mem = bfd_malloc (asize);
if (mem != NULL)
{
if (bfd_bread (mem, rsize, abfd) == rsize)
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 77c66309a25..2391500c330 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -909,10 +909,26 @@ extern bfd_vma _bfd_safe_read_leb128
((*res) = (a), (*res) *= (b), (b) != 0 && (*res) / (b) != (a))
#endif
+#ifdef __GNUC__
+#define _bfd_constant_p(v) __builtin_constant_p (v)
+#else
+#define _bfd_constant_p(v) 0
+#endif
+
static inline bfd_byte *
_bfd_alloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize)
{
- bfd_byte *mem = bfd_alloc (abfd, asize);
+ bfd_byte *mem;
+ if (!_bfd_constant_p (rsize))
+ {
+ ufile_ptr filesize = bfd_get_file_size (abfd);
+ if (filesize != 0 && rsize > filesize)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return NULL;
+ }
+ }
+ mem = bfd_alloc (abfd, asize);
if (mem != NULL)
{
if (bfd_bread (mem, rsize, abfd) == rsize)
@@ -925,7 +941,17 @@ _bfd_alloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize)
static inline bfd_byte *
_bfd_malloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize)
{
- bfd_byte *mem = bfd_malloc (asize);
+ bfd_byte *mem;
+ if (!_bfd_constant_p (rsize))
+ {
+ ufile_ptr filesize = bfd_get_file_size (abfd);
+ if (filesize != 0 && rsize > filesize)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return NULL;
+ }
+ }
+ mem = bfd_malloc (asize);
if (mem != NULL)
{
if (bfd_bread (mem, rsize, abfd) == rsize)