diff options
author | Alan Modra <amodra@gmail.com> | 2022-11-10 11:48:01 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2022-11-10 20:29:03 +1030 |
commit | a3eb71adfea201f9e14980d8a96ea2e27ef52ad1 (patch) | |
tree | 2bba83828745cc3cf61d2f23ffd81fde8b7aedd0 /bfd/mach-o.c | |
parent | f735116b3fb6dc30912e969d6e8c1b15bbaef510 (diff) | |
download | gdb-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/mach-o.c')
-rw-r--r-- | bfd/mach-o.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/bfd/mach-o.c b/bfd/mach-o.c index 5279343..664ff44 100644 --- a/bfd/mach-o.c +++ b/bfd/mach-o.c @@ -1407,17 +1407,27 @@ bfd_mach_o_write_dyld_info (bfd *abfd, bfd_mach_o_load_command *command) } long -bfd_mach_o_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, - asection *asect) +bfd_mach_o_get_reloc_upper_bound (bfd *abfd, asection *asect) { -#if SIZEOF_LONG == SIZEOF_INT - if (asect->reloc_count >= LONG_MAX / sizeof (arelent *)) + size_t count, raw; + + count = asect->reloc_count; + if (count >= LONG_MAX / sizeof (arelent *) + || _bfd_mul_overflow (count, BFD_MACH_O_RELENT_SIZE, &raw)) { bfd_set_error (bfd_error_file_too_big); return -1; } -#endif - return (asect->reloc_count + 1L) * sizeof (arelent *); + if (!bfd_write_p (abfd)) + { + ufile_ptr filesize = bfd_get_file_size (abfd); + if (filesize != 0 && raw > filesize) + { + bfd_set_error (bfd_error_file_truncated); + return -1; + } + } + return (count + 1) * sizeof (arelent *); } /* In addition to the need to byte-swap the symbol number, the bit positions |