From 37d2e9c7b10e298403640fdd38a50fedae8525b2 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Sun, 29 Dec 2019 12:55:34 +1030 Subject: [PATCH] asan: alpha-vms: memory leaks * 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. --- bfd/ChangeLog | 15 +++++++ bfd/vms-alpha.c | 114 ++++++++++++++++++++++++++++++------------------ bfd/vms-misc.c | 16 ++++--- bfd/vms.h | 4 +- 4 files changed, 99 insertions(+), 50 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index de79b5eb23..807dc07ca0 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,18 @@ +2019-12-29 Alan Modra + + * 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. + 2019-12-29 Alan Modra * coffcode.h (coff_close_and_cleanup): Redefine to.. 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); -- 2.34.1