summaryrefslogtreecommitdiff
path: root/binutils
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2023-04-11 15:30:02 +0100
committerNick Clifton <nickc@redhat.com>2023-04-11 15:30:02 +0100
commit45f5fe468b23c92b571756ec72b6a9c7be034074 (patch)
tree983be532e9c66368c69e590d570fcc9c8a6e2163 /binutils
parent37522c873e86dd4941b9cdf38116f31d447d2234 (diff)
downloadbinutils-gdb-45f5fe468b23c92b571756ec72b6a9c7be034074.tar.gz
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')
-rw-r--r--binutils/ChangeLog6
-rw-r--r--binutils/readelf.c27
2 files changed, 27 insertions, 6 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 0794bed00d3..f81f2308651 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,9 @@
+2023-04-11 Nick Clifton <nickc@redhat.com>
+
+ PR 30311
+ * readelf.c (uncompress_section_contents): Check for a
+ suspiciously large uncompressed size.
+
2023-03-30 Nick Clifton <nickc@redhat.com>
PR 30284
diff --git a/binutils/readelf.c b/binutils/readelf.c
index a47cb0eda0a..b872876a8b6 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. */