X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Farchive.c;h=9d63849a483d5cd5c5ad40eb6b811bae2c9ae813;hb=dcb5d41befce097d48875e744f57fe3209c61aab;hp=d2a9a65ea9bb6fee1674cf4321dd3d91ca52ae86;hpb=2bb3687ba8720558082d1575823868286d7916b5;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/archive.c b/bfd/archive.c index d2a9a65ea9..9d63849a48 100644 --- a/bfd/archive.c +++ b/bfd/archive.c @@ -403,7 +403,7 @@ find_nested_archive (const char *filename, bfd *arch_bfd) bfd *abfd; /* PR 15140: Don't allow a nested archive pointing to itself. */ - if (filename_cmp (filename, arch_bfd->filename) == 0) + if (filename_cmp (filename, bfd_get_filename (arch_bfd)) == 0) { bfd_set_error (bfd_error_malformed_archive); return NULL; @@ -413,7 +413,7 @@ find_nested_archive (const char *filename, bfd *arch_bfd) abfd != NULL; abfd = abfd->archive_next) { - if (filename_cmp (filename, abfd->filename) == 0) + if (filename_cmp (filename, bfd_get_filename (abfd)) == 0) return abfd; } abfd = open_nested_file (filename, arch_bfd); @@ -488,6 +488,7 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag) bfd_size_type parsed_size; struct areltdata *ared; char *filename = NULL; + ufile_ptr filesize; bfd_size_type namelen = 0; bfd_size_type allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr); char *allocptr = 0; @@ -538,11 +539,19 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag) { /* BSD-4.4 extended name */ namelen = atoi (&hdr.ar_name[3]); + filesize = bfd_get_file_size (abfd); + if (namelen > parsed_size + || namelen > -allocsize - 2 + || (filesize != 0 && namelen > filesize)) + { + bfd_set_error (bfd_error_malformed_archive); + return NULL; + } allocsize += namelen + 1; parsed_size -= namelen; extra_size = namelen; - allocptr = (char *) bfd_zmalloc (allocsize); + allocptr = (char *) bfd_malloc (allocsize); if (allocptr == NULL) return NULL; filename = (allocptr @@ -586,13 +595,13 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag) if (!allocptr) { - allocptr = (char *) bfd_zmalloc (allocsize); + allocptr = (char *) bfd_malloc (allocsize); if (allocptr == NULL) return NULL; } + memset (allocptr, 0, sizeof (struct areltdata)); ared = (struct areltdata *) allocptr; - ared->arch_header = allocptr + sizeof (struct areltdata); memcpy (ared->arch_header, &hdr, sizeof (struct ar_hdr)); ared->parsed_size = parsed_size; @@ -619,7 +628,7 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag) char * _bfd_append_relative_path (bfd *arch, char *elt_name) { - const char *arch_name = arch->filename; + const char *arch_name = bfd_get_filename (arch); const char *base_name = lbasename (arch_name); size_t prefix_len; char *filename; @@ -728,8 +737,7 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos) else { n_bfd->origin = n_bfd->proxy_origin; - n_bfd->filename = bfd_strdup (filename); - if (n_bfd->filename == NULL) + if (!bfd_set_filename (n_bfd, filename)) goto out; } @@ -842,7 +850,7 @@ _bfd_noarchive_openr_next_archived_file (bfd *archive, return (bfd *) _bfd_ptr_bfd_null_error (archive); } -const bfd_target * +bfd_cleanup bfd_generic_archive_p (bfd *abfd) { struct artdata *tdata_hold; @@ -924,7 +932,7 @@ bfd_generic_archive_p (bfd *abfd) } } - return abfd->xvec; + return _bfd_no_cleanup; } /* Some constants for a 32 bit BSD archive structure. We do not @@ -951,11 +959,12 @@ static bfd_boolean do_slurp_bsd_armap (bfd *abfd) { struct areltdata *mapdata; - unsigned int counter; + size_t counter; bfd_byte *raw_armap, *rbase; struct artdata *ardata = bfd_ardata (abfd); char *stringbase; - bfd_size_type parsed_size, amt; + bfd_size_type parsed_size; + size_t amt, string_size; carsym *set; mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd); @@ -965,44 +974,51 @@ do_slurp_bsd_armap (bfd *abfd) free (mapdata); /* PR 17512: file: 883ff754. */ /* PR 17512: file: 0458885f. */ - if (parsed_size < 4) - return FALSE; - - raw_armap = (bfd_byte *) _bfd_alloc_and_read (abfd, parsed_size, parsed_size); - if (raw_armap == NULL) + if (parsed_size < BSD_SYMDEF_COUNT_SIZE + BSD_STRING_COUNT_SIZE) { - if (bfd_get_error () != bfd_error_system_call) - bfd_set_error (bfd_error_malformed_archive); + bfd_set_error (bfd_error_malformed_archive); return FALSE; } - ardata->symdef_count = H_GET_32 (abfd, raw_armap) / BSD_SYMDEF_SIZE; - if (ardata->symdef_count * BSD_SYMDEF_SIZE > - parsed_size - BSD_SYMDEF_COUNT_SIZE) + raw_armap = (bfd_byte *) _bfd_alloc_and_read (abfd, parsed_size, parsed_size); + if (raw_armap == NULL) + return FALSE; + + parsed_size -= BSD_SYMDEF_COUNT_SIZE + BSD_STRING_COUNT_SIZE; + amt = H_GET_32 (abfd, raw_armap); + if (amt > parsed_size + || amt % BSD_SYMDEF_SIZE != 0) { /* Probably we're using the wrong byte ordering. */ bfd_set_error (bfd_error_wrong_format); - bfd_release (abfd, raw_armap); - return FALSE; + goto release_armap; } rbase = raw_armap + BSD_SYMDEF_COUNT_SIZE; - stringbase = ((char *) rbase - + ardata->symdef_count * BSD_SYMDEF_SIZE - + BSD_STRING_COUNT_SIZE); - amt = ardata->symdef_count * sizeof (carsym); - ardata->symdefs = (struct carsym *) bfd_alloc (abfd, amt); - if (!ardata->symdefs) + stringbase = (char *) rbase + amt + BSD_STRING_COUNT_SIZE; + string_size = parsed_size - amt; + + ardata->symdef_count = amt / BSD_SYMDEF_SIZE; + if (_bfd_mul_overflow (ardata->symdef_count, sizeof (carsym), &amt)) { - bfd_release (abfd, raw_armap); - return FALSE; + bfd_set_error (bfd_error_no_memory); + goto release_armap; } + ardata->symdefs = (struct carsym *) bfd_alloc (abfd, amt); + if (!ardata->symdefs) + goto release_armap; for (counter = 0, set = ardata->symdefs; counter < ardata->symdef_count; counter++, set++, rbase += BSD_SYMDEF_SIZE) { - set->name = H_GET_32 (abfd, rbase) + stringbase; + unsigned nameoff = H_GET_32 (abfd, rbase); + if (nameoff >= string_size) + { + bfd_set_error (bfd_error_malformed_archive); + goto release_armap; + } + set->name = stringbase + nameoff; set->file_offset = H_GET_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE); } @@ -1014,6 +1030,12 @@ do_slurp_bsd_armap (bfd *abfd) to be allocated on an objalloc anyway... */ abfd->has_armap = TRUE; return TRUE; + + release_armap: + ardata->symdef_count = 0; + ardata->symdefs = NULL; + bfd_release (abfd, raw_armap); + return FALSE; } /* Read a COFF archive symbol table. Returns FALSE on error, TRUE @@ -1029,12 +1051,12 @@ do_slurp_coff_armap (bfd *abfd) char *stringend; bfd_size_type stringsize; bfd_size_type parsed_size; + ufile_ptr filesize; + size_t nsymz, carsym_size, ptrsize, i; carsym *carsyms; - bfd_size_type nsymz; /* Number of symbols in armap. */ bfd_vma (*swap) (const void *); - char int_buf[sizeof (long)]; - bfd_size_type carsym_size, ptrsize; - unsigned int i; + char int_buf[4]; + struct areltdata *tmp; mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd); if (mapdata == NULL) @@ -1043,28 +1065,33 @@ do_slurp_coff_armap (bfd *abfd) free (mapdata); if (bfd_bread (int_buf, 4, abfd) != 4) - { - if (bfd_get_error () != bfd_error_system_call) - bfd_set_error (bfd_error_malformed_archive); - return FALSE; - } + return FALSE; + /* It seems that all numeric information in a coff archive is always - in big endian format, nomatter the host or target. */ + in big endian format, no matter the host or target. */ swap = bfd_getb32; nsymz = bfd_getb32 (int_buf); - stringsize = parsed_size - (4 * nsymz) - 4; /* The coff armap must be read sequentially. So we construct a bsd-style one in core all at once, for simplicity. */ - if (nsymz > ~ (bfd_size_type) 0 / sizeof (carsym)) + if (_bfd_mul_overflow (nsymz, sizeof (carsym), &carsym_size)) { bfd_set_error (bfd_error_no_memory); return FALSE; } - carsym_size = (nsymz * sizeof (carsym)); - ptrsize = (4 * nsymz); + filesize = bfd_get_file_size (abfd); + ptrsize = 4 * nsymz; + if ((filesize != 0 && parsed_size > filesize) + || parsed_size < 4 + || parsed_size - 4 < ptrsize) + { + bfd_set_error (bfd_error_malformed_archive); + return FALSE; + } + + stringsize = parsed_size - ptrsize - 4; if (carsym_size + stringsize + 1 <= carsym_size) { @@ -1072,22 +1099,20 @@ do_slurp_coff_armap (bfd *abfd) return FALSE; } + /* Allocate and read in the raw offsets. */ + raw_armap = (int *) _bfd_malloc_and_read (abfd, ptrsize, ptrsize); + if (raw_armap == NULL) + return FALSE; + ardata->symdefs = (struct carsym *) bfd_alloc (abfd, carsym_size + stringsize + 1); if (ardata->symdefs == NULL) - return FALSE; + goto free_armap; carsyms = ardata->symdefs; stringbase = ((char *) ardata->symdefs) + carsym_size; - /* Allocate and read in the raw offsets. */ - raw_armap = (int *) _bfd_alloc_and_read (abfd, ptrsize, ptrsize); - if (raw_armap == NULL - || (bfd_bread (stringbase, stringsize, abfd) != stringsize)) - { - if (bfd_get_error () != bfd_error_system_call) - bfd_set_error (bfd_error_malformed_archive); - goto release_symdefs; - } + if (bfd_bread (stringbase, stringsize, abfd) != stringsize) + goto release_symdefs; /* OK, build the carsyms. */ stringend = stringbase + stringsize; @@ -1107,32 +1132,29 @@ do_slurp_coff_armap (bfd *abfd) ardata->first_file_filepos = bfd_tell (abfd); /* Pad to an even boundary if you have to. */ ardata->first_file_filepos += (ardata->first_file_filepos) % 2; + if (bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET) != 0) + goto release_symdefs; abfd->has_armap = TRUE; - bfd_release (abfd, raw_armap); + free (raw_armap); /* Check for a second archive header (as used by PE). */ - { - struct areltdata *tmp; - - bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET); - tmp = (struct areltdata *) _bfd_read_ar_hdr (abfd); - if (tmp != NULL) - { - if (tmp->arch_header[0] == '/' - && tmp->arch_header[1] == ' ') - { - ardata->first_file_filepos += - (tmp->parsed_size + sizeof (struct ar_hdr) + 1) & ~(unsigned) 1; - } - free (tmp); - } - } + tmp = (struct areltdata *) _bfd_read_ar_hdr (abfd); + if (tmp != NULL) + { + if (tmp->arch_header[0] == '/' + && tmp->arch_header[1] == ' ') + ardata->first_file_filepos + += (tmp->parsed_size + sizeof (struct ar_hdr) + 1) & ~(unsigned) 1; + free (tmp); + } return TRUE; -release_symdefs: + release_symdefs: bfd_release (abfd, (ardata)->symdefs); + free_armap: + free (raw_armap); return FALSE; } @@ -1209,8 +1231,6 @@ bfd_boolean _bfd_slurp_extended_name_table (bfd *abfd) { char nextname[17]; - struct areltdata *namedata; - bfd_size_type amt; /* FIXME: Formatting sucks here, and in case of failure of BFD_READ, we probably don't want to return TRUE. */ @@ -1219,6 +1239,10 @@ _bfd_slurp_extended_name_table (bfd *abfd) if (bfd_bread (nextname, 16, abfd) == 16) { + struct areltdata *namedata; + bfd_size_type amt; + ufile_ptr filesize; + if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0) return FALSE; @@ -1234,9 +1258,13 @@ _bfd_slurp_extended_name_table (bfd *abfd) if (namedata == NULL) return FALSE; + filesize = bfd_get_file_size (abfd); amt = namedata->parsed_size; - if (amt + 1 == 0) - goto byebye; + if (amt + 1 == 0 || (filesize != 0 && amt > filesize)) + { + bfd_set_error (bfd_error_malformed_archive); + goto byebye; + } bfd_ardata (abfd)->extended_names_size = amt; bfd_ardata (abfd)->extended_names = (char *) bfd_alloc (abfd, amt + 1); @@ -1440,8 +1468,7 @@ adjust_relative_path (const char * path, const char * ref_path) if (len > pathbuf_len) { - if (pathbuf != NULL) - free (pathbuf); + free (pathbuf); pathbuf_len = 0; pathbuf = (char *) bfd_malloc (len); if (pathbuf == NULL) @@ -1535,13 +1562,13 @@ _bfd_construct_extended_name_table (bfd *abfd, if (bfd_is_thin_archive (abfd)) { - const char *filename = current->filename; + const char *filename = bfd_get_filename (current); /* If the element being added is a member of another archive (i.e., we are flattening), use the containing archive's name. */ if (current->my_archive && ! bfd_is_thin_archive (current->my_archive)) - filename = current->my_archive->filename; + filename = bfd_get_filename (current->my_archive); /* If the path is the same as the previous path seen, reuse it. This can happen when flattening a thin @@ -1554,8 +1581,8 @@ _bfd_construct_extended_name_table (bfd *abfd, /* If the path is relative, adjust it relative to the containing archive. */ if (! IS_ABSOLUTE_PATH (filename) - && ! IS_ABSOLUTE_PATH (abfd->filename)) - normal = adjust_relative_path (filename, abfd->filename); + && ! IS_ABSOLUTE_PATH (bfd_get_filename (abfd))) + normal = adjust_relative_path (filename, bfd_get_filename (abfd)); else normal = filename; @@ -1569,7 +1596,7 @@ _bfd_construct_extended_name_table (bfd *abfd, continue; } - normal = normalize (abfd, current->filename); + normal = normalize (abfd, bfd_get_filename (current)); if (normal == NULL) return FALSE; @@ -1626,7 +1653,7 @@ _bfd_construct_extended_name_table (bfd *abfd, const char *normal; unsigned int thislen; long stroff; - const char *filename = current->filename; + const char *filename = bfd_get_filename (current); if (bfd_is_thin_archive (abfd)) { @@ -1634,7 +1661,7 @@ _bfd_construct_extended_name_table (bfd *abfd, (i.e., we are flattening), use the containing archive's name. */ if (current->my_archive && ! bfd_is_thin_archive (current->my_archive)) - filename = current->my_archive->filename; + filename = bfd_get_filename (current->my_archive); /* If the path is the same as the previous path seen, reuse it. This can happen when flattening a thin archive that contains other archives. @@ -1643,8 +1670,8 @@ _bfd_construct_extended_name_table (bfd *abfd, if (last_filename && filename_cmp (last_filename, filename) == 0) normal = last_filename; else if (! IS_ABSOLUTE_PATH (filename) - && ! IS_ABSOLUTE_PATH (abfd->filename)) - normal = adjust_relative_path (filename, abfd->filename); + && ! IS_ABSOLUTE_PATH (bfd_get_filename (abfd))) + normal = adjust_relative_path (filename, bfd_get_filename (abfd)); else normal = filename; } @@ -1712,7 +1739,7 @@ _bfd_archive_bsd44_construct_extended_name_table (bfd *abfd, current != NULL; current = current->archive_next) { - const char *normal = normalize (abfd, current->filename); + const char *normal = normalize (abfd, bfd_get_filename (current)); int has_space = 0; unsigned int len; @@ -1758,7 +1785,7 @@ _bfd_bsd44_write_ar_hdr (bfd *archive, bfd *abfd) if (is_bsd44_extended_name (hdr->ar_name)) { /* This is a BSD 4.4 extended name. */ - const char *fullname = normalize (abfd, abfd->filename); + const char *fullname = normalize (abfd, bfd_get_filename (abfd)); unsigned int len = strlen (fullname); unsigned int padded_len = (len + 3) & ~3; @@ -2110,13 +2137,15 @@ _bfd_write_archive_contents (bfd *arch) if (!current->arelt_data) { current->arelt_data = - bfd_ar_hdr_from_filesystem (arch, current->filename, current); + bfd_ar_hdr_from_filesystem (arch, bfd_get_filename (current), + current); if (!current->arelt_data) goto input_err; /* Put in the file name. */ BFD_SEND (arch, _bfd_truncate_arname, - (arch, current->filename, (char *) arch_hdr (current))); + (arch, bfd_get_filename (current), + (char *) arch_hdr (current))); } if (makemap && ! hasobjects) @@ -2265,7 +2294,7 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int elength) /* Drop all the files called __.SYMDEF, we're going to make our own. */ while (arch->archive_head - && strcmp (arch->archive_head->filename, "__.SYMDEF") == 0) + && strcmp (bfd_get_filename (arch->archive_head), "__.SYMDEF") == 0) arch->archive_head = arch->archive_head->archive_next; /* Map over each element. */ @@ -2296,8 +2325,7 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int elength) { if (storage > syms_max) { - if (syms_max > 0) - free (syms); + free (syms); syms_max = storage; syms = (asymbol **) bfd_malloc (syms_max); if (syms == NULL) @@ -2378,20 +2406,16 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int elength) ret = BFD_SEND (arch, write_armap, (arch, elength, map, orl_count, stridx)); - if (syms_max > 0) - free (syms); - if (map != NULL) - free (map); + free (syms); + free (map); if (first_name != NULL) bfd_release (arch, first_name); return ret; error_return: - if (syms_max > 0) - free (syms); - if (map != NULL) - free (map); + free (syms); + free (map); if (first_name != NULL) bfd_release (arch, first_name); @@ -2466,7 +2490,7 @@ _bfd_bsd_write_armap (bfd *arch, { struct stat statbuf; - if (stat (arch->filename, &statbuf) == 0) + if (stat (bfd_get_filename (arch), &statbuf) == 0) bfd_ardata (arch)->armap_timestamp = (statbuf.st_mtime + ARMAP_TIME_OFFSET); uid = getuid();