Automatic date update in version.in
[binutils-gdb.git] / bfd / compress.c
index a3adb8d82500c4e9676d58020413eb76d3e9793e..b2e39826e385b0884aa773274f603f234c05e236 100644 (file)
@@ -1,5 +1,5 @@
 /* Compressed section support (intended for debug sections).
-   Copyright (C) 2008-2021 Free Software Foundation, Inc.
+   Copyright (C) 2008-2022 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -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);
@@ -232,7 +237,6 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
   bfd_size_type save_rawsize;
   bfd_byte *compressed_buffer;
   unsigned int compression_header_size;
-  ufile_ptr filesize;
 
   if (abfd->direction != write_direction && sec->rawsize != 0)
     sz = sec->rawsize;
@@ -244,37 +248,34 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
       return true;
     }
 
-  filesize = bfd_get_file_size (abfd);
-  if (filesize > 0
-      && filesize < sz
-      /* PR 24753: Linker created sections can be larger than
-        the file size, eg if they are being used to hold stubs.  */
-      && (bfd_section_flags (sec) & SEC_LINKER_CREATED) == 0
-      /* PR 24753: Sections which have no content should also be
-        excluded as they contain no size on disk.  */
-      && (bfd_section_flags (sec) & SEC_HAS_CONTENTS) != 0
-      /* PR 28530: Check compressed sections with the corrupt size.  */
-      && (sec->compress_status != COMPRESS_SECTION_NONE
-      /* The MMO file format supports its own special compression
-        technique, but it uses COMPRESS_SECTION_NONE when loading
-        a section's contents.  */
-         || bfd_get_flavour (abfd) != bfd_target_mmo_flavour))
-    {
-      /* PR 24708: Avoid attempts to allocate a ridiculous amount
-        of memory.  */
-      bfd_set_error (bfd_error_file_truncated);
-      _bfd_error_handler
-       /* xgettext:c-format */
-       (_("error: %pB(%pA) section size (%#" PRIx64 " bytes) is larger than file size (%#" PRIx64 " bytes)"),
-        abfd, sec, (uint64_t) sz, (uint64_t) filesize);
-      return false;
-    }
-
   switch (sec->compress_status)
     {
     case COMPRESS_SECTION_NONE:
       if (p == NULL)
        {
+         ufile_ptr filesize = bfd_get_file_size (abfd);
+         if (filesize > 0
+             && filesize < sz
+             /* PR 24753: Linker created sections can be larger than
+                the file size, eg if they are being used to hold stubs.  */
+             && (bfd_section_flags (sec) & SEC_LINKER_CREATED) == 0
+             /* PR 24753: Sections which have no content should also be
+                excluded as they contain no size on disk.  */
+             && (bfd_section_flags (sec) & SEC_HAS_CONTENTS) != 0
+             /* The MMO file format supports its own special compression
+                technique, but it uses COMPRESS_SECTION_NONE when loading
+                a section's contents.  */
+             && bfd_get_flavour (abfd) != bfd_target_mmo_flavour)
+           {
+             /* PR 24708: Avoid attempts to allocate a ridiculous amount
+                of memory.  */
+             bfd_set_error (bfd_error_file_truncated);
+             _bfd_error_handler
+               /* xgettext:c-format */
+               (_("error: %pB(%pA) section size (%#" PRIx64 " bytes) is larger than file size (%#" PRIx64 " bytes)"),
+                abfd, sec, (uint64_t) sz, (uint64_t) filesize);
+             return false;
+           }
          p = (bfd_byte *) bfd_malloc (sz);
          if (p == NULL)
            {
@@ -520,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)
@@ -555,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);