diff options
author | Alan Modra <amodra@gmail.com> | 2021-11-05 14:07:56 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2021-11-05 14:15:18 +1030 |
commit | c5967f38de59c7375970c09b2c8b8702a01eb9d2 (patch) | |
tree | 21419b8ba4297ff9b92edb3a47dbedc953b278ea /bfd/compress.c | |
parent | a3c0896d80d21545bd8036deb5e1ad4027db5677 (diff) | |
download | gdb-c5967f38de59c7375970c09b2c8b8702a01eb9d2.zip gdb-c5967f38de59c7375970c09b2c8b8702a01eb9d2.tar.gz gdb-c5967f38de59c7375970c09b2c8b8702a01eb9d2.tar.bz2 |
PR28530, Hang in objdump on machine with 196GB RAM
Investigating the PR28530 testcase, which has a fuzzed compression
header with an enormous size, I noticed that decompress_contents is
broken when the size doesn't fit in strm.avail_out. It wouldn't be
too hard to support larger sizes (patches welcome!) but for now just
stop decompress_contents from returning rubbish.
PR 28530
* compress.c (decompress_contents): Fail when uncompressed_size
is too big.
(bfd_init_section_decompress_status): Likewise.
Diffstat (limited to 'bfd/compress.c')
-rw-r--r-- | bfd/compress.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/bfd/compress.c b/bfd/compress.c index 4a2ada3..70daf4e 100644 --- a/bfd/compress.c +++ b/bfd/compress.c @@ -46,6 +46,11 @@ decompress_contents (bfd_byte *compressed_buffer, strm.avail_in = compressed_size; strm.next_in = (Bytef*) compressed_buffer; strm.avail_out = uncompressed_size; + /* FIXME: strm.avail_in and strm.avail_out are typically unsigned + int. Supporting sizes that don't fit in an unsigned int is + possible but will require some rewriting of this function. */ + if (strm.avail_in != compressed_size || strm.avail_out != uncompressed_size) + return false; BFD_ASSERT (Z_OK == 0); rc = inflateInit (&strm); @@ -516,6 +521,7 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec) int header_size; bfd_size_type uncompressed_size; unsigned int uncompressed_alignment_power = 0; + z_stream strm; compression_header_size = bfd_get_compression_header_size (abfd, sec); if (compression_header_size > MAX_COMPRESSION_HEADER_SIZE) @@ -551,6 +557,15 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec) return false; } + /* PR28530, reject sizes unsupported by decompress_contents. */ + strm.avail_in = sec->size; + strm.avail_out = uncompressed_size; + if (strm.avail_in != sec->size || strm.avail_out != uncompressed_size) + { + bfd_set_error (bfd_error_nonrepresentable_section); + return false; + } + sec->compressed_size = sec->size; sec->size = uncompressed_size; bfd_set_section_alignment (sec, uncompressed_alignment_power); |