asan: alpha-vms: memory leaks
[deliverable/binutils-gdb.git] / bfd / vms-alpha.c
index 4dde056e1ee67e638a3af4beda2a08897f0e557b..5d2ff527aa3a27e70a95905072fc6d1bff8c7cbe 100644 (file)
@@ -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:
@@ -1137,12 +1145,20 @@ add_symbol_entry (bfd *abfd, struct vms_symbol_entry *sym)
    Return NULL in case of error.  */
 
 static struct vms_symbol_entry *
-add_symbol (bfd *abfd, const unsigned char *ascic)
+add_symbol (bfd *abfd, const unsigned char *ascic, unsigned int max)
 {
   struct vms_symbol_entry *entry;
-  int len;
+  unsigned int len;
 
   len = *ascic++;
+  max -= 1;
+  if (len > max)
+    {
+      _bfd_error_handler (_("record is too small for symbol name length"));
+      bfd_set_error (bfd_error_bad_value);
+      return NULL;
+    }
+
   entry = (struct vms_symbol_entry *)bfd_zalloc (abfd, sizeof (*entry) + len);
   if (entry == NULL)
     return NULL;
@@ -1230,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)
@@ -1243,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;
@@ -1292,7 +1310,7 @@ _bfd_vms_slurp_egsd (bfd *abfd)
 
        case EGSD__C_SYM:
          {
-           int nameoff;
+           unsigned int nameoff;
            struct vms_symbol_entry *entry;
            struct vms_egsy *egsy = (struct vms_egsy *) vms_rec;
            flagword old_flags;
@@ -1303,7 +1321,13 @@ _bfd_vms_slurp_egsd (bfd *abfd)
            else
              nameoff = ESRF__B_NAMLNG;
 
-           entry = add_symbol (abfd, vms_rec + nameoff);
+           if (nameoff >= gsd_size)
+             {
+               _bfd_error_handler (_("ECSD__C_SYM record is too small"));
+               bfd_set_error (bfd_error_bad_value);
+               return FALSE;
+             }
+           entry = add_symbol (abfd, vms_rec + nameoff, gsd_size - nameoff);
            if (entry == NULL)
              return FALSE;
 
@@ -1363,11 +1387,17 @@ _bfd_vms_slurp_egsd (bfd *abfd)
            struct vms_symbol_entry *entry;
            struct vms_egst *egst = (struct vms_egst *)vms_rec;
            flagword old_flags;
+           unsigned int nameoff = offsetof (struct vms_egst, namlng);
 
            old_flags = bfd_getl16 (egst->header.flags);
 
-           entry = add_symbol (abfd, &egst->namlng);
-
+           if (nameoff >= gsd_size)
+             {
+               _bfd_error_handler (_("ECSD__C_SYMG record is too small"));
+               bfd_set_error (bfd_error_bad_value);
+               return FALSE;
+             }
+           entry = add_symbol (abfd, &egst->namlng, gsd_size - nameoff);
            if (entry == NULL)
              return FALSE;
 
@@ -1854,19 +1884,23 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
 
   while (ptr < maxptr)
     {
-      int cmd = bfd_getl16 (ptr);
-      int cmd_length = bfd_getl16 (ptr + 2);
+      int cmd, cmd_length;
 
-      ptr += 4;
+      if (ptr + 4 > maxptr)
+       goto corrupt_etir;
+
+      cmd = bfd_getl16 (ptr);
+      cmd_length = bfd_getl16 (ptr + 2);
 
       /* PR 21589 and 21579: Check for a corrupt ETIR record.  */
-      if (cmd_length < 4 || (ptr + cmd_length > maxptr + 4))
+      if (cmd_length < 4 || ptr + cmd_length > maxptr)
        {
        corrupt_etir:
          _bfd_error_handler (_("corrupt ETIR record encountered"));
          bfd_set_error (bfd_error_bad_value);
          return FALSE;
        }
+      ptr += 4;
 
 #if VMS_DEBUG
       _bfd_vms_debug (4, "etir: %s(%d)\n",
@@ -1890,7 +1924,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
 
             stack 32 bit value, sign extend to 64 bit.  */
        case ETIR__C_STA_LW:
-         if (ptr + 4 >= maxptr)
+         if (ptr + 4 > maxptr)
            goto corrupt_etir;
          _bfd_vms_push (abfd, bfd_getl32 (ptr), RELC_NONE);
          break;
@@ -1900,7 +1934,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
 
             stack 64 bit value of symbol.  */
        case ETIR__C_STA_QW:
-         if (ptr + 8 >= maxptr)
+         if (ptr + 8 > maxptr)
            goto corrupt_etir;
          _bfd_vms_push (abfd, bfd_getl64 (ptr), RELC_NONE);
          break;
@@ -1915,7 +1949,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
          {
            int psect;
 
-           if (ptr + 12 >= maxptr)
+           if (ptr + 12 > maxptr)
              goto corrupt_etir;
            psect = bfd_getl32 (ptr);
            if ((unsigned int) psect >= PRIV (section_count))
@@ -2006,7 +2040,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
          {
            int size;
 
-           if (ptr + 4 >= maxptr)
+           if (ptr + 4 > maxptr)
              goto corrupt_etir;
            size = bfd_getl32 (ptr);
            _bfd_vms_pop (abfd, &op1, &rel1);
@@ -2089,7 +2123,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
          {
            unsigned int size;
 
-           if (ptr + 4 >= maxptr)
+           if (ptr + 4 > maxptr)
              goto corrupt_etir;
            size = bfd_getl32 (ptr);
            image_write (abfd, ptr + 4, size);
@@ -2252,7 +2286,7 @@ _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
          /* Augment relocation base: increment image location counter by offset
             arg: lw    offset value.  */
        case ETIR__C_CTL_AUGRB:
-         if (ptr + 4 >= maxptr)
+         if (ptr + 4 > maxptr)
            goto corrupt_etir;
          op1 = bfd_getl32 (ptr);
          image_inc_ptr (abfd, op1);
@@ -4204,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;
@@ -4222,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;
@@ -4273,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)
                      {
@@ -8336,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 *
@@ -8357,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;
 }
@@ -9283,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.  */
This page took 0.033154 seconds and 4 git commands to generate.