PR28834, PR26946 sanity checking section size

This patch provides a new function to sanity check section sizes.
It's mostly extracted from what we had in bfd_get_full_section_contents
but also handles compressed debug sections.
Improvements are:
- section file offset is taken into account,
- added checks that a compressed section can be read from file.

The function is then used when handling multiple .debug_* sections
that need to be read into a single buffer, to sanity check sizes
before allocating the buffer.

	PR 26946, PR 28834
	* Makefile.am (LIBBFD_H_FILES): Add section.c.
	* compress.c (bfd_get_full_section_contents): Move section size
	sanity checks..
	* section.c (_bfd_section_size_insane): ..to here.  New function.
	* dwarf2.c (read_section): Use _bfd_section_size_insane.
	(_bfd_dwarf2_slurp_debug_info): Likewise.
	* Makefile.in: Regenerate.
	* libbfd.h: Regenerate.
This commit is contained in:
Alan Modra
2022-11-11 13:43:42 +10:30
parent d0e5049d8f
commit f7502dfe3f
6 changed files with 94 additions and 45 deletions

View File

@@ -1703,3 +1703,69 @@ _bfd_nowrite_set_section_contents (bfd *abfd,
{
return _bfd_bool_bfd_false_error (abfd);
}
/*
INTERNAL_FUNCTION
_bfd_section_size_insane
SYNOPSIS
bool _bfd_section_size_insane (bfd *abfd, asection *sec);
DESCRIPTION
Returns true if the given section has a size that indicates
it cannot be read from file. Return false if the size is OK
*or* this function can't say one way or the other.
*/
bool
_bfd_section_size_insane (bfd *abfd, asection *sec)
{
bfd_size_type size = bfd_get_section_limit_octets (abfd, sec);
if (size == 0)
return false;
if ((bfd_section_flags (sec) & SEC_IN_MEMORY) != 0
/* 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)
return false;
ufile_ptr filesize = bfd_get_file_size (abfd);
if (filesize == 0)
return false;
if (sec->compress_status == DECOMPRESS_SECTION_ZSTD
|| sec->compress_status == DECOMPRESS_SECTION_ZLIB)
{
/* PR26946, PR28834: Sanity check compress header uncompressed
size against the original file size, and check that the
compressed section can be read from file. We choose an
arbitrary uncompressed size of 10x the file size, rather than
a compress ratio. The reason being that compiling
"int aaa..a;" with "a" repeated enough times can result in
compression ratios without limit for .debug_str, whereas such
a file will usually also have the enormous symbol
uncompressed in .symtab. */
if (size / 10 > filesize)
{
bfd_set_error (bfd_error_bad_value);
return true;
}
size = sec->compressed_size;
}
if ((ufile_ptr) sec->filepos > filesize || size > filesize - sec->filepos)
{
bfd_set_error (bfd_error_file_truncated);
return true;
}
return false;
}