bfd_get_file_size calls

Message ID 20200219032245.GH5570@bubble.grove.modra.org
State New
Headers show
Series
  • bfd_get_file_size calls
Related show

Commit Message

Alan Modra Feb. 19, 2020, 3:22 a.m.
bfd_get_file_size can return 0, meaning the file size is unknown.

	* coffgen.c (_bfd_coff_get_external_symbols): Don't call
	bfd_get_file_size twice.
	(_bfd_coff_read_string_table): Allow for bfd_get_file_size
	zero, ie. unknown, return.
	* elf-attrs.c (_bfd_elf_parse_attributes): Likewise.
	* elfcode.h (elf_swap_shdr_in): Likewise.
	(elf_object_p): Don't call bfd_get_file_size twice and correct
	file size check.


-- 
Alan Modra
Australia Development Lab, IBM

Patch

diff --git a/bfd/coffgen.c b/bfd/coffgen.c
index cf115d48c8..5287130490 100644
--- a/bfd/coffgen.c
+++ b/bfd/coffgen.c
@@ -1642,19 +1642,20 @@  _bfd_coff_get_external_symbols (bfd *abfd)
   bfd_size_type symesz;
   bfd_size_type size;
   void * syms;
+  ufile_ptr filesize;
 
   if (obj_coff_external_syms (abfd) != NULL)
     return TRUE;
 
   symesz = bfd_coff_symesz (abfd);
-
   size = obj_raw_syment_count (abfd) * symesz;
   if (size == 0)
     return TRUE;
+
   /* Check for integer overflow and for unreasonable symbol counts.  */
+  filesize = bfd_get_file_size (abfd);
   if (size < obj_raw_syment_count (abfd)
-      || (bfd_get_file_size (abfd) > 0
-	  && size > bfd_get_file_size (abfd)))
+      || (filesize != 0 && size > filesize))
 
     {
       _bfd_error_handler (_("%pB: corrupt symbol count: %#" PRIx64 ""),
@@ -1698,6 +1699,7 @@  _bfd_coff_read_string_table (bfd *abfd)
   bfd_size_type strsize;
   char *strings;
   file_ptr pos;
+  ufile_ptr filesize;
 
   if (obj_coff_strings (abfd) != NULL)
     return obj_coff_strings (abfd);
@@ -1731,7 +1733,9 @@  _bfd_coff_read_string_table (bfd *abfd)
 #endif
     }
 
-  if (strsize < STRING_SIZE_SIZE || strsize > bfd_get_file_size (abfd))
+  filesize = bfd_get_file_size (abfd);
+  if (strsize < STRING_SIZE_SIZE
+      || (filesize != 0 && strsize > filesize))
     {
       _bfd_error_handler
 	/* xgettext: c-format */
diff --git a/bfd/elf-attrs.c b/bfd/elf-attrs.c
index 169b697381..070104c273 100644
--- a/bfd/elf-attrs.c
+++ b/bfd/elf-attrs.c
@@ -436,11 +436,14 @@  _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
   bfd_byte *p_end;
   bfd_vma len;
   const char *std_sec;
+  ufile_ptr filesize;
 
   /* PR 17512: file: 2844a11d.  */
   if (hdr->sh_size == 0)
     return;
-  if (hdr->sh_size > bfd_get_file_size (abfd))
+
+  filesize = bfd_get_file_size (abfd);
+  if (filesize != 0 && hdr->sh_size > filesize)
     {
       /* xgettext:c-format */
       _bfd_error_handler (_("%pB: error: attribute section '%pA' too big: %#llx"),
diff --git a/bfd/elfcode.h b/bfd/elfcode.h
index e1e89cf78f..a6b0c613ba 100644
--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -317,11 +317,16 @@  elf_swap_shdr_in (bfd *abfd,
   /* PR 23657.  Check for invalid section size, in sections with contents.
      Note - we do not set an error value here because the contents
      of this particular section might not be needed by the consumer.  */
-  if (dst->sh_type != SHT_NOBITS
-      && dst->sh_size > bfd_get_file_size (abfd))
-    _bfd_error_handler
-      (_("warning: %pB has a corrupt section with a size (%" BFD_VMA_FMT "x) larger than the file size"),
-       abfd, dst->sh_size);
+  if (dst->sh_type != SHT_NOBITS)
+    {
+      ufile_ptr filesize = bfd_get_file_size (abfd);
+
+      if (filesize != 0 && dst->sh_size > filesize)
+	_bfd_error_handler
+	  (_("warning: %pB has a corrupt section with a size (%"
+	     BFD_VMA_FMT "x) larger than the file size"),
+	   abfd, dst->sh_size);
+    }
   dst->sh_link = H_GET_32 (abfd, src->sh_link);
   dst->sh_info = H_GET_32 (abfd, src->sh_info);
   dst->sh_addralign = H_GET_WORD (abfd, src->sh_addralign);
@@ -775,6 +780,7 @@  elf_object_p (bfd *abfd)
     {
       Elf_Internal_Phdr *i_phdr;
       unsigned int i;
+      ufile_ptr filesize;
 
 #ifndef BFD64
       if (i_ehdrp->e_phnum > ((bfd_size_type) -1) / sizeof (*i_phdr))
@@ -782,9 +788,10 @@  elf_object_p (bfd *abfd)
 #endif
       /* Check for a corrupt input file with an impossibly large number
 	 of program headers.  */
-      if (bfd_get_file_size (abfd) > 0
-	  && i_ehdrp->e_phnum > bfd_get_file_size (abfd))
-	goto got_no_match;
+      filesize = bfd_get_file_size (abfd);
+      if (filesize != 0
+	  && i_ehdrp->e_phnum > filesize / sizeof (Elf_External_Phdr))
+	goto got_wrong_format_error;
       elf_tdata (abfd)->phdr
 	= (Elf_Internal_Phdr *) bfd_alloc2 (abfd, i_ehdrp->e_phnum,
 					    sizeof (*i_phdr));