forked from Imagelibrary/binutils-gdb
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:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user