diff options
author | Nick Clifton <nickc@redhat.com> | 2023-04-11 15:30:02 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2023-04-11 15:30:02 +0100 |
commit | 45f5fe468b23c92b571756ec72b6a9c7be034074 (patch) | |
tree | 983be532e9c66368c69e590d570fcc9c8a6e2163 /binutils/readelf.c | |
parent | 37522c873e86dd4941b9cdf38116f31d447d2234 (diff) | |
download | gdb-45f5fe468b23c92b571756ec72b6a9c7be034074.zip gdb-45f5fe468b23c92b571756ec72b6a9c7be034074.tar.gz gdb-45f5fe468b23c92b571756ec72b6a9c7be034074.tar.bz2 |
Fix an attempt to allocate an overlarge amount of memory when decoding a corrupt ELF format file.
PR 30311
* readelf.c (uncompress_section_contents): Check for a suspiciously large uncompressed size.
Diffstat (limited to 'binutils/readelf.c')
-rw-r--r-- | binutils/readelf.c | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/binutils/readelf.c b/binutils/readelf.c index a47cb0e..b872876 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -15268,15 +15268,30 @@ get_section_contents (Elf_Internal_Shdr * section, Filedata * filedata) /* Uncompresses a section that was compressed using zlib/zstd, in place. */ static bool -uncompress_section_contents (bool is_zstd, unsigned char **buffer, - uint64_t uncompressed_size, uint64_t *size) +uncompress_section_contents (bool is_zstd, + unsigned char ** buffer, + uint64_t uncompressed_size, + uint64_t * size, + uint64_t file_size) { uint64_t compressed_size = *size; unsigned char *compressed_buffer = *buffer; - unsigned char *uncompressed_buffer = xmalloc (uncompressed_size); + unsigned char *uncompressed_buffer = NULL; z_stream strm; int rc; + /* Similar to _bfd_section_size_insane() in the BFD library we expect an + upper limit of ~10x compression. Any compression larger than that is + thought to be due to fuzzing of the compression header. */ + if (uncompressed_size > file_size * 10) + { + error (_("Uncompressed section size is suspiciously large: 0x%" PRIu64 "\n"), + uncompressed_size); + goto fail; + } + + uncompressed_buffer = xmalloc (uncompressed_size); + if (is_zstd) { #ifdef HAVE_ZSTD @@ -15406,7 +15421,7 @@ dump_section_as_strings (Elf_Internal_Shdr * section, Filedata * filedata) if (uncompressed_size) { if (uncompress_section_contents (is_zstd, &start, uncompressed_size, - &new_size)) + &new_size, filedata->file_size)) num_bytes = new_size; else { @@ -15629,7 +15644,7 @@ dump_section_as_bytes (Elf_Internal_Shdr *section, if (uncompressed_size) { if (uncompress_section_contents (is_zstd, &start, uncompressed_size, - &new_size)) + &new_size, filedata->file_size)) { section_size = new_size; } @@ -16061,7 +16076,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, if (uncompressed_size) { if (uncompress_section_contents (is_zstd, &start, uncompressed_size, - &size)) + &size, filedata->file_size)) { /* Free the compressed buffer, update the section buffer and the section size if uncompress is successful. */ |