mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-12-19 01:19:41 +08:00
PR 33033, Support compressed debug sections larger than 4 GiB
z_stream's avail_in and avail_out are defined as "unsigned int", so it cannot decode an entire compressed stream in one pass if the stream is larger than 4 GiB. The simplest solution to this problem is to use zlib's convenient uncompress2() function, which handles the details for us. Signed-off-by: Rui Ueyama <rui314@gmail.com>
This commit is contained in:
@@ -517,40 +517,23 @@ decompress_contents (bool is_zstd, bfd_byte *compressed_buffer,
|
||||
#endif
|
||||
}
|
||||
|
||||
z_stream strm;
|
||||
int rc;
|
||||
|
||||
/* It is possible the section consists of several compressed
|
||||
buffers concatenated together, so we uncompress in a loop. */
|
||||
/* PR 18313: The state field in the z_stream structure is supposed
|
||||
to be invisible to the user (ie us), but some compilers will
|
||||
still complain about it being used without initialisation. So
|
||||
we first zero the entire z_stream structure and then set the fields
|
||||
that we need. */
|
||||
memset (& strm, 0, sizeof strm);
|
||||
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);
|
||||
while (strm.avail_in > 0 && strm.avail_out > 0)
|
||||
do
|
||||
{
|
||||
uLongf dst_len = uncompressed_size;
|
||||
uLong src_len = compressed_size;
|
||||
int rc = uncompress2 ((Bytef *) uncompressed_buffer, &dst_len,
|
||||
(Bytef *) compressed_buffer, &src_len);
|
||||
if (rc != Z_OK)
|
||||
break;
|
||||
strm.next_out = ((Bytef*) uncompressed_buffer
|
||||
+ (uncompressed_size - strm.avail_out));
|
||||
rc = inflate (&strm, Z_FINISH);
|
||||
if (rc != Z_STREAM_END)
|
||||
break;
|
||||
rc = inflateReset (&strm);
|
||||
return false;
|
||||
uncompressed_buffer += dst_len;
|
||||
uncompressed_size -= dst_len;
|
||||
compressed_buffer += src_len;
|
||||
compressed_size -= src_len;
|
||||
}
|
||||
return inflateEnd (&strm) == Z_OK && rc == Z_OK && strm.avail_out == 0;
|
||||
while (compressed_size > 0 && uncompressed_size > 0);
|
||||
return compressed_size == 0 && uncompressed_size == 0;
|
||||
}
|
||||
|
||||
/* Compress section contents using zlib/zstd and store
|
||||
@@ -987,7 +970,6 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec)
|
||||
bfd_size_type uncompressed_size;
|
||||
unsigned int uncompressed_alignment_power = 0;
|
||||
enum compression_type ch_type;
|
||||
z_stream strm;
|
||||
|
||||
compression_header_size = bfd_get_compression_header_size (abfd, sec);
|
||||
if (compression_header_size > MAX_COMPRESSION_HEADER_SIZE)
|
||||
@@ -1025,15 +1007,6 @@ 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);
|
||||
|
||||
Reference in New Issue
Block a user