asan: heap buffer overflow printing ecoff debug info file name

Message ID ZCoAizHXDaTVgiFm@squeak.grove.modra.org
State Accepted
Headers
Series asan: heap buffer overflow printing ecoff debug info file name |

Checks

Context Check Description
snail/binutils-gdb-check success Github commit url

Commit Message

Alan Modra April 2, 2023, 10:24 p.m. UTC
  A case of a string section ending with an unterminated string.  Fix it
by allocating one more byte and making it zero.  Also make functions
reading the data return void* so that casts are not needed.

	* ecoff.c (READ): Delete type param.  Allocate one extra byte
	to terminate string sections with a NUL.  Adjust invocation.
	* elfxx-mips.c (READ): Likewise.
	* libbfd-in.h (_bfd_alloc_and_read): Return a void*.
	(_bfd_malloc_and_read): Likewise.
	* libbfd.h: Regenerate.
  

Patch

diff --git a/bfd/ecoff.c b/bfd/ecoff.c
index 1bea7005fee..fb6fcade913 100644
--- a/bfd/ecoff.c
+++ b/bfd/ecoff.c
@@ -3749,7 +3749,7 @@  ecoff_final_link_debug_accumulate (bfd *output_bfd,
   HDRR *symhdr = &debug->symbolic_header;
   bool ret;
 
-#define READ(ptr, offset, count, size, type)				\
+#define READ(ptr, offset, count, size)					\
   do									\
     {									\
       size_t amt;							\
@@ -3767,29 +3767,28 @@  ecoff_final_link_debug_accumulate (bfd *output_bfd,
 	  ret = false;							\
 	  goto return_something;					\
 	}								\
-      debug->ptr = (type) _bfd_malloc_and_read (input_bfd, amt, amt);	\
+      debug->ptr = _bfd_malloc_and_read (input_bfd, amt + 1, amt);	\
       if (debug->ptr == NULL)						\
 	{								\
 	  ret = false;							\
 	  goto return_something;					\
 	}								\
+      ((char *) debug->ptr)[amt] = 0;					\
     } while (0)
 
   /* If raw_syments is not NULL, then the data was already by read by
      _bfd_ecoff_slurp_symbolic_info.  */
   if (ecoff_data (input_bfd)->raw_syments == NULL)
     {
-      READ (line, cbLineOffset, cbLine, sizeof (unsigned char),
-	    unsigned char *);
-      READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, void *);
-      READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, void *);
-      READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, void *);
-      READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, void *);
-      READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext),
-	    union aux_ext *);
-      READ (ss, cbSsOffset, issMax, sizeof (char), char *);
-      READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, void *);
-      READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, void *);
+      READ (line, cbLineOffset, cbLine, sizeof (unsigned char));
+      READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size);
+      READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size);
+      READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size);
+      READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size);
+      READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext));
+      READ (ss, cbSsOffset, issMax, sizeof (char));
+      READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size);
+      READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size);
     }
 #undef READ
 
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 35bbd86044b..d34a755807b 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -1486,7 +1486,7 @@  _bfd_mips_elf_read_ecoff_info (bfd *abfd, asection *section,
 
   /* The symbolic header contains absolute file offsets and sizes to
      read.  */
-#define READ(ptr, offset, count, size, type)				\
+#define READ(ptr, offset, count, size)					\
   do									\
     {									\
       size_t amt;							\
@@ -1500,23 +1500,23 @@  _bfd_mips_elf_read_ecoff_info (bfd *abfd, asection *section,
 	}								\
       if (bfd_seek (abfd, symhdr->offset, SEEK_SET) != 0)		\
 	goto error_return;						\
-      debug->ptr = (type) _bfd_malloc_and_read (abfd, amt, amt);	\
+      debug->ptr = _bfd_malloc_and_read (abfd, amt + 1, amt);		\
       if (debug->ptr == NULL)						\
 	goto error_return;						\
+      ((char *) debug->ptr)[amt] = 0;					\
     } while (0)
 
-  READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *);
-  READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, void *);
-  READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, void *);
-  READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, void *);
-  READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, void *);
-  READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext),
-	union aux_ext *);
-  READ (ss, cbSsOffset, issMax, sizeof (char), char *);
-  READ (ssext, cbSsExtOffset, issExtMax, sizeof (char), char *);
-  READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, void *);
-  READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, void *);
-  READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, void *);
+  READ (line, cbLineOffset, cbLine, sizeof (unsigned char));
+  READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size);
+  READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size);
+  READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size);
+  READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size);
+  READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext));
+  READ (ss, cbSsOffset, issMax, sizeof (char));
+  READ (ssext, cbSsExtOffset, issExtMax, sizeof (char));
+  READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size);
+  READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size);
+  READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size);
 #undef READ
 
   return true;
diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h
index 1c9f34bb6d7..561cef1a12e 100644
--- a/bfd/libbfd-in.h
+++ b/bfd/libbfd-in.h
@@ -929,10 +929,10 @@  extern bool _bfd_link_keep_memory (struct bfd_link_info *)
 #define _bfd_constant_p(v) 0
 #endif
 
-static inline bfd_byte *
+static inline void *
 _bfd_alloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize)
 {
-  bfd_byte *mem;
+  void *mem;
   if (!_bfd_constant_p (rsize))
     {
       ufile_ptr filesize = bfd_get_file_size (abfd);
@@ -952,10 +952,10 @@  _bfd_alloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize)
   return NULL;
 }
 
-static inline bfd_byte *
+static inline void *
 _bfd_malloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize)
 {
-  bfd_byte *mem;
+  void *mem;
   if (!_bfd_constant_p (rsize))
     {
       ufile_ptr filesize = bfd_get_file_size (abfd);
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index d1dc7b912a0..ae17717efa3 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -935,10 +935,10 @@  extern bool _bfd_link_keep_memory (struct bfd_link_info *)
 #define _bfd_constant_p(v) 0
 #endif
 
-static inline bfd_byte *
+static inline void *
 _bfd_alloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize)
 {
-  bfd_byte *mem;
+  void *mem;
   if (!_bfd_constant_p (rsize))
     {
       ufile_ptr filesize = bfd_get_file_size (abfd);
@@ -958,10 +958,10 @@  _bfd_alloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize)
   return NULL;
 }
 
-static inline bfd_byte *
+static inline void *
 _bfd_malloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize)
 {
-  bfd_byte *mem;
+  void *mem;
   if (!_bfd_constant_p (rsize))
     {
       ufile_ptr filesize = bfd_get_file_size (abfd);