asan: alpha-vms: memory leaks

Alan Modra amodra@gmail.com
Sun Dec 29 11:40:00 GMT 2019


	* vms-misc.c (_bfd_vms_save_sized_string): Add abfd param, make
	size a size_t.  Use bfd_alloc rather than bfd_malloc.
	(_bfd_vms_save_counted_string): Similarly.
	* vms.h (_bfd_vms_save_sized_string): Update prototype.
	(_bfd_vms_save_counted_string): Likewise.
	* vms-alpha.c (_bfd_vms_slurp_ehdr): Adjust
	_bfd_vms_save_counted_string and bfd_vms_save_sized_string calls.
	(_bfd_vms_slurp_egsd, parse_module): Likewise.
	(_bfd_vms_slurp_eisd): Likewise.  Check return status.
	(alpha_vms_bfd_link_hash_table_free): New function.
	(alpha_vms_bfd_link_hash_table_create): Arrange to call it.
	(vms_close_and_cleanup): Free more memory.  Don't release tdata.

diff --git a/bfd/vms-alpha.c b/bfd/vms-alpha.c
index 0b1b4ca8d8..5d2ff527aa 100644
--- a/bfd/vms-alpha.c
+++ b/bfd/vms-alpha.c
@@ -595,10 +595,13 @@ _bfd_vms_slurp_eisd (bfd *abfd, unsigned int offset)
 	  if (rec_size < offsetof (struct vms_eisd, gblnam))
 	    return FALSE;
 	  else if (rec_size < sizeof (struct vms_eisd))
-	    name = _bfd_vms_save_counted_string (eisd->gblnam,
+	    name = _bfd_vms_save_counted_string (abfd, eisd->gblnam,
 						 rec_size - offsetof (struct vms_eisd, gblnam));
 	  else
-	    name = _bfd_vms_save_counted_string (eisd->gblnam, EISD__K_GBLNAMLEN);
+	    name = _bfd_vms_save_counted_string (abfd, eisd->gblnam,
+						 EISD__K_GBLNAMLEN);
+	  if (name == NULL)
+	    return FALSE;
 	  bfd_flags |= SEC_COFF_SHARED_LIBRARY;
 	  bfd_flags &= ~(SEC_ALLOC | SEC_LOAD);
 	}
@@ -610,7 +613,9 @@ _bfd_vms_slurp_eisd (bfd *abfd, unsigned int offset)
 	{
 	  const char *pfx;
 
-	  name = (char*) bfd_alloc (abfd, 32);
+	  name = (char *) bfd_alloc (abfd, 32);
+	  if (name == NULL)
+	    return FALSE;
 	  if (flags & EISD__M_DZRO)
 	    pfx = "BSS";
 	  else if (flags & EISD__M_EXE)
@@ -924,36 +929,39 @@ _bfd_vms_slurp_ehdr (bfd *abfd)
       PRIV (hdr_data).hdr_l_recsiz = bfd_getl32 (vms_rec + 16);
       if ((vms_rec + 20 + vms_rec[20] + 1) >= end)
 	goto fail;
-      PRIV (hdr_data).hdr_t_name   = _bfd_vms_save_counted_string (vms_rec + 20, vms_rec[20]);
+      PRIV (hdr_data).hdr_t_name
+	= _bfd_vms_save_counted_string (abfd, vms_rec + 20, vms_rec[20]);
       ptr = vms_rec + 20 + vms_rec[20] + 1;
       if ((ptr + *ptr + 1) >= end)
 	goto fail;
-      PRIV (hdr_data).hdr_t_version =_bfd_vms_save_counted_string (ptr, *ptr);
+      PRIV (hdr_data).hdr_t_version
+	= _bfd_vms_save_counted_string (abfd, ptr, *ptr);
       ptr += *ptr + 1;
       if (ptr + 17 >= end)
 	goto fail;
-      PRIV (hdr_data).hdr_t_date = _bfd_vms_save_sized_string (ptr, 17);
+      PRIV (hdr_data).hdr_t_date
+	= _bfd_vms_save_sized_string (abfd, ptr, 17);
       break;
 
     case EMH__C_LNM:
       if (vms_rec + PRIV (recrd.rec_size - 6) > end)
 	goto fail;
-      PRIV (hdr_data).hdr_c_lnm =
-	_bfd_vms_save_sized_string (vms_rec, PRIV (recrd.rec_size - 6));
+      PRIV (hdr_data).hdr_c_lnm
+	= _bfd_vms_save_sized_string (abfd, vms_rec, PRIV (recrd.rec_size - 6));
       break;
 
     case EMH__C_SRC:
       if (vms_rec + PRIV (recrd.rec_size - 6) > end)
 	goto fail;
-      PRIV (hdr_data).hdr_c_src =
-	_bfd_vms_save_sized_string (vms_rec, PRIV (recrd.rec_size - 6));
+      PRIV (hdr_data).hdr_c_src
+	= _bfd_vms_save_sized_string (abfd, vms_rec, PRIV (recrd.rec_size - 6));
       break;
 
     case EMH__C_TTL:
       if (vms_rec + PRIV (recrd.rec_size - 6) > end)
 	goto fail;
-      PRIV (hdr_data).hdr_c_ttl =
-	_bfd_vms_save_sized_string (vms_rec, PRIV (recrd.rec_size - 6));
+      PRIV (hdr_data).hdr_c_ttl
+	= _bfd_vms_save_sized_string (abfd, vms_rec, PRIV (recrd.rec_size - 6));
       break;
 
     case EMH__C_CPR:
@@ -1238,7 +1246,8 @@ _bfd_vms_slurp_egsd (bfd *abfd)
 		char *name;
 		unsigned long align_addr;
 
-		name = _bfd_vms_save_counted_string (&egps->namlng, gsd_size - 4);
+		name = _bfd_vms_save_counted_string (abfd, &egps->namlng,
+						     gsd_size - 4);
 
 		section = bfd_make_section (abfd, name);
 		if (!section)
@@ -1251,7 +1260,8 @@ _bfd_vms_slurp_egsd (bfd *abfd)
 		vms_section_data (section)->flags = vms_flags;
 		vms_section_data (section)->no_flags = 0;
 
-		new_flags = vms_secflag_by_name (evax_section_flags, name,
+		new_flags = vms_secflag_by_name (evax_section_flags,
+						 section->name,
 						 section->size > 0);
 		if (section->size > 0)
 		  new_flags |= SEC_LOAD;
@@ -4228,7 +4238,7 @@ parse_module (bfd *abfd, struct module *module, unsigned char *ptr,
 	{
 	case DST__K_MODBEG:
 	  module->name
-	    = _bfd_vms_save_counted_string (ptr + DST_S_B_MODBEG_NAME,
+	    = _bfd_vms_save_counted_string (abfd, ptr + DST_S_B_MODBEG_NAME,
 					    maxptr - (ptr + DST_S_B_MODBEG_NAME));
 
 	  curr_pc = 0;
@@ -4246,7 +4256,7 @@ parse_module (bfd *abfd, struct module *module, unsigned char *ptr,
 	  funcinfo = (struct funcinfo *)
 	    bfd_zalloc (abfd, sizeof (struct funcinfo));
 	  funcinfo->name
-	    = _bfd_vms_save_counted_string (ptr + DST_S_B_RTNBEG_NAME,
+	    = _bfd_vms_save_counted_string (abfd, ptr + DST_S_B_RTNBEG_NAME,
 					    maxptr - (ptr + DST_S_B_RTNBEG_NAME));
 	  funcinfo->low = bfd_getl32 (ptr + DST_S_L_RTNBEG_ADDRESS);
 	  funcinfo->next = module->func_table;
@@ -4297,11 +4307,10 @@ parse_module (bfd *abfd, struct module *module, unsigned char *ptr,
 		  {
 		    unsigned int fileid
 		      = bfd_getl16 (src_ptr + DST_S_W_SRC_DF_FILEID);
-		    char *filename
-		      = _bfd_vms_save_counted_string (src_ptr + DST_S_B_SRC_DF_FILENAME,
-						      (ptr + rec_length) -
-						      (src_ptr + DST_S_B_SRC_DF_FILENAME)
-						      );
+		    char *filename = _bfd_vms_save_counted_string
+		      (abfd,
+		       src_ptr + DST_S_B_SRC_DF_FILENAME,
+		       ptr + rec_length - (src_ptr + DST_S_B_SRC_DF_FILENAME));
 
 		    while (fileid >= module->file_table_count)
 		      {
@@ -8360,6 +8369,27 @@ alpha_vms_link_hash_newfunc (struct bfd_hash_entry *entry,
   return (struct bfd_hash_entry *) ret;
 }
 
+static void
+alpha_vms_bfd_link_hash_table_free (bfd *abfd)
+{
+  struct alpha_vms_link_hash_table *t;
+  unsigned i;
+
+  t = (struct alpha_vms_link_hash_table *) abfd->link.hash;
+  for (i = 0; i < VEC_COUNT (t->shrlibs); i++)
+    {
+      struct alpha_vms_shlib_el *shlib;
+
+      shlib = &VEC_EL (t->shrlibs, struct alpha_vms_shlib_el, i);
+      free (&VEC_EL (shlib->ca, bfd_vma, 0));
+      free (&VEC_EL (shlib->lp, bfd_vma, 0));
+      free (&VEC_EL (shlib->qr, struct alpha_vms_vma_ref, 0));
+    }
+  free (&VEC_EL (t->shrlibs, struct alpha_vms_shlib_el, 0));
+
+  _bfd_generic_link_hash_table_free (abfd);
+}
+
 /* Create an Alpha/VMS link hash table.  */
 
 static struct bfd_link_hash_table *
@@ -8381,6 +8411,7 @@ alpha_vms_bfd_link_hash_table_create (bfd *abfd)
 
   VEC_INIT (ret->shrlibs);
   ret->fixup = NULL;
+  ret->root.hash_table_free = alpha_vms_bfd_link_hash_table_free;
 
   return &ret->root;
 }
@@ -9307,35 +9338,32 @@ vms_close_and_cleanup (bfd * abfd)
   if (abfd == NULL || abfd->tdata.any == NULL)
     return TRUE;
 
-  if (abfd->format == bfd_archive)
+  if (abfd->format == bfd_object)
     {
-      bfd_release (abfd, abfd->tdata.any);
-      abfd->tdata.any = NULL;
-      return TRUE;
-    }
-
-  if (PRIV (recrd.buf) != NULL)
-    free (PRIV (recrd.buf));
+      struct module *module;
 
-  if (PRIV (sections) != NULL)
-    free (PRIV (sections));
+      free (PRIV (recrd.buf));
+      free (PRIV (sections));
+      free (PRIV (syms));
+      free (PRIV (dst_ptr_offsets));
 
-  bfd_release (abfd, abfd->tdata.any);
-  abfd->tdata.any = NULL;
+      for (module = PRIV (modules); module; module = module->next)
+	free (module->file_table);
 
 #ifdef VMS
-  if (abfd->direction == write_direction)
-    {
-      /* Last step on VMS is to convert the file to variable record length
-	 format.  */
-      if (!bfd_cache_close (abfd))
-	return FALSE;
-      if (!_bfd_vms_convert_to_var_unix_filename (abfd->filename))
-	return FALSE;
-    }
+      if (abfd->direction == write_direction)
+	{
+	  /* Last step on VMS is to convert the file to variable record length
+	     format.  */
+	  if (!bfd_cache_close (abfd))
+	    return FALSE;
+	  if (!_bfd_vms_convert_to_var_unix_filename (abfd->filename))
+	    return FALSE;
+	}
 #endif
+    }
 
-  return TRUE;
+  return _bfd_generic_close_and_cleanup (abfd);
 }
 
 /* Called when a new section is created.  */
diff --git a/bfd/vms-misc.c b/bfd/vms-misc.c
index bc422895bd..c94f1c3ecf 100644
--- a/bfd/vms-misc.c
+++ b/bfd/vms-misc.c
@@ -139,13 +139,19 @@ _bfd_hexdump (int level, unsigned char *ptr, int size, int offset)
    Size is string size (size of record).  */
 
 char *
-_bfd_vms_save_sized_string (unsigned char *str, unsigned int size)
+_bfd_vms_save_sized_string (bfd *abfd, unsigned char *str, size_t size)
 {
-  char *newstr = bfd_malloc ((bfd_size_type) size + 1);
+  char *newstr;
 
+  if (size == (size_t) -1)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return NULL;
+    }
+  newstr = bfd_alloc (abfd, size + 1);
   if (newstr == NULL)
     return NULL;
-  memcpy (newstr, (char *) str, (size_t) size);
+  memcpy (newstr, str, size);
   newstr[size] = 0;
 
   return newstr;
@@ -155,13 +161,13 @@ _bfd_vms_save_sized_string (unsigned char *str, unsigned int size)
    PTR points to size byte on entry.  */
 
 char *
-_bfd_vms_save_counted_string (unsigned char *ptr, unsigned int maxlen)
+_bfd_vms_save_counted_string (bfd *abfd, unsigned char *ptr, size_t maxlen)
 {
   unsigned int len = *ptr++;
 
   if (len > maxlen)
     return NULL;
-  return _bfd_vms_save_sized_string (ptr, len);
+  return _bfd_vms_save_sized_string (abfd, ptr, len);
 }
 
 /* Object output routines.   */
diff --git a/bfd/vms.h b/bfd/vms.h
index 6c96b58d05..8df75b74cb 100644
--- a/bfd/vms.h
+++ b/bfd/vms.h
@@ -118,8 +118,8 @@ extern void vms_time_t_to_vms_time (time_t ut, unsigned int *hi, unsigned int *l
 extern void vms_get_time (unsigned int *hi, unsigned int *lo);
 extern void vms_raw_get_time (unsigned char *buf);
 
-extern char * _bfd_vms_save_sized_string (unsigned char *, unsigned);
-extern char * _bfd_vms_save_counted_string (unsigned char *, unsigned);
+extern char * _bfd_vms_save_sized_string (bfd *, unsigned char *, size_t);
+extern char * _bfd_vms_save_counted_string (bfd *, unsigned char *, size_t);
 extern void   _bfd_vms_output_begin (struct vms_rec_wr *, int);
 extern void   _bfd_vms_output_alignment (struct vms_rec_wr *, int);
 extern void   _bfd_vms_output_begin_subrec (struct vms_rec_wr *, int);

-- 
Alan Modra
Australia Development Lab, IBM



More information about the Binutils mailing list