X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Fcompress.c;h=8f96d064bde1369a8956a3d3ed9d8599b86ead86;hb=e379e5f385f874adb0b414f917adb1fc50e20de9;hp=7b2c37c4187b2e6769bc283844c7b0acc652d75f;hpb=cfd14a500e0485374596234de4db10e88ebc7618;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/compress.c b/bfd/compress.c index 7b2c37c418..8f96d064bd 100644 --- a/bfd/compress.c +++ b/bfd/compress.c @@ -1,5 +1,5 @@ /* Compressed section support (intended for debug sections). - Copyright (C) 2008-2017 Free Software Foundation, Inc. + Copyright (C) 2008-2019 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -54,7 +54,7 @@ decompress_contents (bfd_byte *compressed_buffer, if (rc != Z_OK) break; strm.next_out = ((Bytef*) uncompressed_buffer - + (uncompressed_size - strm.avail_out)); + + (uncompressed_size - strm.avail_out)); rc = inflate (&strm, Z_FINISH); if (rc != Z_STREAM_END) break; @@ -84,11 +84,13 @@ bfd_compress_section_contents (bfd *abfd, sec_ptr sec, int zlib_size = 0; int orig_compression_header_size; bfd_size_type orig_uncompressed_size; + unsigned int orig_uncompressed_alignment_pow; int header_size = bfd_get_compression_header_size (abfd, NULL); bfd_boolean compressed = bfd_is_section_compressed_with_header (abfd, sec, &orig_compression_header_size, - &orig_uncompressed_size); + &orig_uncompressed_size, + &orig_uncompressed_alignment_pow); /* Either ELF compression header or the 12-byte, "ZLIB" + 8-byte size, overhead in .zdebug* section. */ @@ -106,7 +108,7 @@ bfd_compress_section_contents (bfd *abfd, sec_ptr sec, if (orig_compression_header_size == 0) { /* Convert it from .zdebug* section. Get the uncompressed - size first. We need to substract the 12-byte overhead in + size first. We need to subtract the 12-byte overhead in .zdebug* section. Set orig_compression_header_size to the 12-bye overhead. */ orig_compression_header_size = 12; @@ -153,6 +155,8 @@ bfd_compress_section_contents (bfd *abfd, sec_ptr sec, return 0; } free (uncompressed_buffer); + bfd_set_section_alignment (sec, orig_uncompressed_alignment_pow); + sec->contents = buffer; sec->compress_status = COMPRESS_SECTION_DONE; return orig_uncompressed_size; @@ -239,18 +243,32 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr) *ptr = NULL; return TRUE; } - else if (bfd_get_file_size (abfd) > 0 - && sz > (bfd_size_type) bfd_get_file_size (abfd)) - { - *ptr = NULL; - 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 + /* 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_no_memory); + _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) { @@ -258,9 +276,9 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr) if (bfd_get_error () == bfd_error_no_memory) _bfd_error_handler /* xgettext:c-format */ - (_("error: %B(%A) is too large (%#lx bytes)"), - abfd, sec, (long) sz); - return FALSE; + (_("error: %pB(%pA) is too large (%#" PRIx64 " bytes)"), + abfd, sec, (uint64_t) sz); + return FALSE; } } @@ -370,20 +388,24 @@ SYNOPSIS bfd_boolean bfd_is_section_compressed_with_header (bfd *abfd, asection *section, int *compression_header_size_p, - bfd_size_type *uncompressed_size_p); + bfd_size_type *uncompressed_size_p, + unsigned int *uncompressed_alignment_power_p); DESCRIPTION Return @code{TRUE} if @var{section} is compressed. Compression - header size is returned in @var{compression_header_size_p} and - uncompressed size is returned in @var{uncompressed_size_p}. If - compression is unsupported, compression header size is returned - with -1 and uncompressed size is returned with 0. + header size is returned in @var{compression_header_size_p}, + uncompressed size is returned in @var{uncompressed_size_p} + and the uncompressed data alignement power is returned in + @var{uncompressed_align_pow_p}. If compression is + unsupported, compression header size is returned with -1 + and uncompressed size is returned with 0. */ bfd_boolean bfd_is_section_compressed_with_header (bfd *abfd, sec_ptr sec, int *compression_header_size_p, - bfd_size_type *uncompressed_size_p) + bfd_size_type *uncompressed_size_p, + unsigned int *uncompressed_align_pow_p) { bfd_byte header[MAX_COMPRESSION_HEADER_SIZE]; int compression_header_size; @@ -391,6 +413,8 @@ bfd_is_section_compressed_with_header (bfd *abfd, sec_ptr sec, unsigned int saved = sec->compress_status; bfd_boolean compressed; + *uncompressed_align_pow_p = 0; + compression_header_size = bfd_get_compression_header_size (abfd, sec); if (compression_header_size > MAX_COMPRESSION_HEADER_SIZE) abort (); @@ -403,7 +427,7 @@ bfd_is_section_compressed_with_header (bfd *abfd, sec_ptr sec, if (bfd_get_section_contents (abfd, sec, header, 0, header_size)) { if (compression_header_size == 0) - /* In this case, it should be "ZLIB" followed by the uncompressed + /* In this case, it should be "ZLIB" followed by the uncompressed section size, 8 bytes in big-endian order. */ compressed = CONST_STRNEQ ((char*) header , "ZLIB"); else @@ -418,7 +442,8 @@ bfd_is_section_compressed_with_header (bfd *abfd, sec_ptr sec, if (compression_header_size != 0) { if (!bfd_check_compression_header (abfd, header, sec, - uncompressed_size_p)) + uncompressed_size_p, + uncompressed_align_pow_p)) compression_header_size = -1; } /* Check for the pathalogical case of a debug string section that @@ -455,9 +480,11 @@ bfd_is_section_compressed (bfd *abfd, sec_ptr sec) { int compression_header_size; bfd_size_type uncompressed_size; + unsigned int uncompressed_align_power; return (bfd_is_section_compressed_with_header (abfd, sec, &compression_header_size, - &uncompressed_size) + &uncompressed_size, + &uncompressed_align_power) && compression_header_size >= 0 && uncompressed_size > 0); } @@ -486,6 +513,7 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec) int compression_header_size; int header_size; bfd_size_type uncompressed_size; + unsigned int uncompressed_alignment_power = 0; compression_header_size = bfd_get_compression_header_size (abfd, sec); if (compression_header_size > MAX_COMPRESSION_HEADER_SIZE) @@ -514,7 +542,8 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec) uncompressed_size = bfd_getb64 (header + 4); } else if (!bfd_check_compression_header (abfd, header, sec, - &uncompressed_size)) + &uncompressed_size, + &uncompressed_alignment_power)) { bfd_set_error (bfd_error_wrong_format); return FALSE; @@ -522,6 +551,7 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec) sec->compressed_size = sec->size; sec->size = uncompressed_size; + bfd_set_section_alignment (sec, uncompressed_alignment_power); sec->compress_status = DECOMPRESS_SECTION_SIZED; return TRUE;