Skip to content

Commit 0921b99

Browse files
rui314amodra
authored andcommitted
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 <[email protected]>
1 parent 4187ba1 commit 0921b99

File tree

1 file changed

+12
-39
lines changed

1 file changed

+12
-39
lines changed

bfd/compress.c

Lines changed: 12 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -517,40 +517,23 @@ decompress_contents (bool is_zstd, bfd_byte *compressed_buffer,
517517
#endif
518518
}
519519

520-
z_stream strm;
521-
int rc;
522-
523520
/* It is possible the section consists of several compressed
524521
buffers concatenated together, so we uncompress in a loop. */
525-
/* PR 18313: The state field in the z_stream structure is supposed
526-
to be invisible to the user (ie us), but some compilers will
527-
still complain about it being used without initialisation. So
528-
we first zero the entire z_stream structure and then set the fields
529-
that we need. */
530-
memset (& strm, 0, sizeof strm);
531-
strm.avail_in = compressed_size;
532-
strm.next_in = (Bytef*) compressed_buffer;
533-
strm.avail_out = uncompressed_size;
534-
/* FIXME: strm.avail_in and strm.avail_out are typically unsigned
535-
int. Supporting sizes that don't fit in an unsigned int is
536-
possible but will require some rewriting of this function. */
537-
if (strm.avail_in != compressed_size || strm.avail_out != uncompressed_size)
538-
return false;
539-
540-
BFD_ASSERT (Z_OK == 0);
541-
rc = inflateInit (&strm);
542-
while (strm.avail_in > 0 && strm.avail_out > 0)
522+
do
543523
{
524+
uLongf dst_len = uncompressed_size;
525+
uLong src_len = compressed_size;
526+
int rc = uncompress2 ((Bytef *) uncompressed_buffer, &dst_len,
527+
(Bytef *) compressed_buffer, &src_len);
544528
if (rc != Z_OK)
545-
break;
546-
strm.next_out = ((Bytef*) uncompressed_buffer
547-
+ (uncompressed_size - strm.avail_out));
548-
rc = inflate (&strm, Z_FINISH);
549-
if (rc != Z_STREAM_END)
550-
break;
551-
rc = inflateReset (&strm);
529+
return false;
530+
uncompressed_buffer += dst_len;
531+
uncompressed_size -= dst_len;
532+
compressed_buffer += src_len;
533+
compressed_size -= src_len;
552534
}
553-
return inflateEnd (&strm) == Z_OK && rc == Z_OK && strm.avail_out == 0;
535+
while (compressed_size > 0 && uncompressed_size > 0);
536+
return compressed_size == 0 && uncompressed_size == 0;
554537
}
555538

556539
/* Compress section contents using zlib/zstd and store
@@ -987,7 +970,6 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec)
987970
bfd_size_type uncompressed_size;
988971
unsigned int uncompressed_alignment_power = 0;
989972
enum compression_type ch_type;
990-
z_stream strm;
991973

992974
compression_header_size = bfd_get_compression_header_size (abfd, sec);
993975
if (compression_header_size > MAX_COMPRESSION_HEADER_SIZE)
@@ -1025,15 +1007,6 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec)
10251007
return false;
10261008
}
10271009

1028-
/* PR28530, reject sizes unsupported by decompress_contents. */
1029-
strm.avail_in = sec->size;
1030-
strm.avail_out = uncompressed_size;
1031-
if (strm.avail_in != sec->size || strm.avail_out != uncompressed_size)
1032-
{
1033-
bfd_set_error (bfd_error_nonrepresentable_section);
1034-
return false;
1035-
}
1036-
10371010
sec->compressed_size = sec->size;
10381011
sec->size = uncompressed_size;
10391012
bfd_set_section_alignment (sec, uncompressed_alignment_power);

0 commit comments

Comments
 (0)