aboutsummaryrefslogtreecommitdiff
path: root/bfd/coffgen.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2022-11-10 11:48:01 +1030
committerAlan Modra <amodra@gmail.com>2022-11-10 20:29:03 +1030
commita3eb71adfea201f9e14980d8a96ea2e27ef52ad1 (patch)
tree2bba83828745cc3cf61d2f23ffd81fde8b7aedd0 /bfd/coffgen.c
parentf735116b3fb6dc30912e969d6e8c1b15bbaef510 (diff)
downloadgdb-a3eb71adfea201f9e14980d8a96ea2e27ef52ad1.zip
gdb-a3eb71adfea201f9e14980d8a96ea2e27ef52ad1.tar.gz
gdb-a3eb71adfea201f9e14980d8a96ea2e27ef52ad1.tar.bz2
Sanity check reloc count in get_reloc_upper_bound
The idea here is the stop tools from allocating up to 32G per section for the arelent pointer array, only to find a little later that the section reloc count was fuzzed. This usually doesn't hurt much (on systems that allow malloc overcommit) except when compiled with asan. We already do this for ELF targets, and while fixing the logic recently I decided other targets ought to do the same. * elf64-sparc.c (elf64_sparc_get_reloc_upper_bound): Sanity check section reloc count against file size. * mach-o.c (bfd_mach_o_get_reloc_upper_bound): Likewise. * aoutx.h (get_reloc_upper_bound): Likewise, and don't duplicate check done in bfd_get_reloc_upper_bound. * pdp11.c (get_reloc_upper_bound): Likewise. * coffgen.c (coff_get_reloc_upper_bound): Likewise.
Diffstat (limited to 'bfd/coffgen.c')
-rw-r--r--bfd/coffgen.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/bfd/coffgen.c b/bfd/coffgen.c
index 3e0fbc6..aab41c3 100644
--- a/bfd/coffgen.c
+++ b/bfd/coffgen.c
@@ -1976,19 +1976,25 @@ coff_get_normalized_symtab (bfd *abfd)
long
coff_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
{
- if (bfd_get_format (abfd) != bfd_object)
+ size_t count, raw;
+
+ count = asect->reloc_count;
+ if (count >= LONG_MAX / sizeof (arelent *)
+ || _bfd_mul_overflow (count, bfd_coff_relsz (abfd), &raw))
{
- bfd_set_error (bfd_error_invalid_operation);
+ bfd_set_error (bfd_error_file_too_big);
return -1;
}
-#if SIZEOF_LONG == SIZEOF_INT
- if (asect->reloc_count >= LONG_MAX / sizeof (arelent *))
+ if (!bfd_write_p (abfd))
{
- bfd_set_error (bfd_error_file_too_big);
- return -1;
+ ufile_ptr filesize = bfd_get_file_size (abfd);
+ if (filesize != 0 && raw > filesize)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return -1;
+ }
}
-#endif
- return (asect->reloc_count + 1L) * sizeof (arelent *);
+ return (count + 1) * sizeof (arelent *);
}
asymbol *