From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 50014 invoked by alias); 19 Feb 2020 03:26:38 -0000 Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org Received: (qmail 49825 invoked by uid 89); 19 Feb 2020 03:26:25 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.1 spammy= X-HELO: mail-pf1-f179.google.com Received: from mail-pf1-f179.google.com (HELO mail-pf1-f179.google.com) (209.85.210.179) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 19 Feb 2020 03:26:19 +0000 Received: by mail-pf1-f179.google.com with SMTP id 2so11741941pfg.12 for ; Tue, 18 Feb 2020 19:26:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:subject:message-id:mime-version:content-disposition :user-agent; bh=gwMhTIqd5KLSGWASH5uyI3mf1KWoBlTY6dVUzlnCeBg=; b=HmYU30eXg/yQRxvmQuxWeFPk9e+gcU2kVR+j621jbcW26jNd867vCwMnz/wwzHBcdk I+mequXYg+uKLmUiHvY/T3b+mmp7bIdP6dF3Hsg7h6XdT5scE0cY2fIrTm9ZBmS6+mMQ a+SYmsOhLBvYpx6EaC67AmGG9ok5JKFOHl6kiBrq8yC+1fKZpVJy1b9Izetota5BNYu3 33nOLZwHwLbeRKhZkVcO9dIiJ2XNgbUW/aLTvN/HUb7RqhX/Nqd+VD8tsvxepMkW+Ykx jGIqzUzF85SR86djYuVFg9hDYGITBtyGnOeDPtLWRSBR+Fb047PbKBlj54vi+F32DWzd Tn0g== Return-Path: Received: from bubble.grove.modra.org ([2406:3400:51d:8cc0:70ef:550d:1ef3:328a]) by smtp.gmail.com with ESMTPSA id v9sm343469pja.26.2020.02.18.19.26.14 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Feb 2020 19:26:14 -0800 (PST) Received: by bubble.grove.modra.org (Postfix, from userid 1000) id 484018ADF5; Wed, 19 Feb 2020 13:56:10 +1030 (ACDT) Date: Wed, 19 Feb 2020 03:26:00 -0000 From: Alan Modra To: binutils@sourceware.org Subject: _bfd_mul_overflow Message-ID: <20200219032610.GK5570@bubble.grove.modra.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.9.4 (2018-02-28) X-IsSubscribed: yes X-SW-Source: 2020-02/txt/msg00439.txt.bz2 This patch removes the bfd_alloc2 series of memory allocation functions, replacing them with __builtin_mul_overflow followed by bfd_alloc. Why do that? Well, a followup patch will implement _bfd_alloc_and_read and I don't want to implement alloc2 variants as well. * coffcode.h (buy_and_read, coff_slurp_line_table), (coff_slurp_symbol_table, coff_slurp_reloc_table): Replace bfd_[z][m]alloc2 calls with _bfd_mul_overflow followed by the corresponding bfd_alloc call. Adjust variables to suit. * coffgen.c (_bfd_coff_get_external_symbols): Likewise. * ecoff.c (_bfd_ecoff_slurp_symbolic_info), (_bfd_ecoff_slurp_symbol_table, READ): Likewise. * elf.c (bfd_elf_get_elf_syms, setup_group, bfd_section_from_shdr), (swap_out_syms, _bfd_elf_slurp_version_tables): Likewise. * elf32-m32c.c (m32c_elf_relax_section): Likewise. * elf32-rl78.c (rl78_elf_relax_section): Likewise. * elf32-rx.c (elf32_rx_relax_section): Likewise. * elf64-alpha.c (READ): Likewise. * elfcode.h (elf_object_p, elf_write_relocs, elf_write_shdrs_and_ehdr), (elf_slurp_symbol_table, elf_slurp_reloc_table), (bfd_from_remote_memory): Likewise. * elfcore.h (core_find_build_id): Likewise. * elfxx-mips.c (READ): Likewise. * mach-o.c (bfd_mach_o_mangle_sections), (bfd_mach_o_read_symtab_symbols, bfd_mach_o_read_thread), (bfd_mach_o_read_dysymtab, bfd_mach_o_flatten_sections), (bfd_mach_o_scan, bfd_mach_o_fat_archive_p): Likewise. * som.c (setup_sections, som_prep_for_fixups) (som_build_and_write_symbol_table, som_slurp_symbol_table), (som_slurp_reloc_table, som_bfd_count_ar_symbols), (som_bfd_fill_in_ar_symbols, som_slurp_armap), (som_bfd_ar_write_symbol_stuff): Likewise. * vms-alpha.c (vector_grow1): Likewise. * vms-lib.c (vms_add_index): Likewise. * wasm-module.c (wasm_scan_name_function_section): Likewise. * libbfd.c (bfd_malloc2, bfd_realloc2, bfd_zmalloc2): Delete. * opncls.c (bfd_alloc2, bfd_zalloc2): Delete. * libbfd-in.h (bfd_malloc2, bfd_realloc2, bfd_zmalloc2), (bfd_alloc2, bfd_zalloc2): Delete. (_bfd_mul_overflow): Define. * libbfd.h: Regenerate. diff --git a/bfd/coffcode.h b/bfd/coffcode.h index 3311b9f813..551105dfb3 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -4200,13 +4200,19 @@ static void * buy_and_read (bfd *abfd, file_ptr where, bfd_size_type nmemb, bfd_size_type size) { - void *area = bfd_alloc2 (abfd, nmemb, size); + void *area; + size_t amt; + if (_bfd_mul_overflow (nmemb, size, &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return NULL; + } + area = bfd_alloc (abfd, amt); if (!area) return NULL; - size *= nmemb; if (bfd_seek (abfd, where, SEEK_SET) != 0 - || bfd_bread (area, size, abfd) != size) + || bfd_bread (area, amt, abfd) != amt) return NULL; return area; } @@ -4265,6 +4271,7 @@ coff_slurp_line_table (bfd *abfd, asection *asect) LINENO *src; bfd_boolean have_func; bfd_boolean ret = TRUE; + size_t amt; if (asect->lineno_count == 0) return TRUE; @@ -4279,9 +4286,12 @@ coff_slurp_line_table (bfd *abfd, asection *asect) return FALSE; } - lineno_cache = (alent *) bfd_alloc2 (abfd, - (bfd_size_type) asect->lineno_count + 1, - sizeof (alent)); + if (_bfd_mul_overflow (asect->lineno_count + 1, sizeof (alent), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } + lineno_cache = (alent *) bfd_alloc (abfd, amt); if (lineno_cache == NULL) return FALSE; @@ -4395,8 +4405,12 @@ coff_slurp_line_table (bfd *abfd, asection *asect) alent *n_lineno_cache; /* Create a table of functions. */ - func_table = (alent **) bfd_alloc2 (abfd, nbr_func, sizeof (alent *)); - if (func_table != NULL) + if (_bfd_mul_overflow (nbr_func, sizeof (alent *), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + ret = FALSE; + } + else if ((func_table = (alent **) bfd_alloc (abfd, amt)) != NULL) { alent **p = func_table; unsigned int i; @@ -4411,9 +4425,12 @@ coff_slurp_line_table (bfd *abfd, asection *asect) qsort (func_table, nbr_func, sizeof (alent *), coff_sort_func_alent); /* Create the new sorted table. */ - n_lineno_cache = (alent *) bfd_alloc2 (abfd, asect->lineno_count, - sizeof (alent)); - if (n_lineno_cache != NULL) + if (_bfd_mul_overflow (asect->lineno_count, sizeof (alent), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + ret = FALSE; + } + else if ((n_lineno_cache = (alent *) bfd_alloc (abfd, amt)) != NULL) { alent *n_cache_ptr = n_lineno_cache; @@ -4459,6 +4476,7 @@ coff_slurp_symbol_table (bfd * abfd) unsigned int *table_ptr; unsigned int number_of_symbols = 0; bfd_boolean ret = TRUE; + size_t amt; if (obj_symbols (abfd)) return TRUE; @@ -4468,15 +4486,23 @@ coff_slurp_symbol_table (bfd * abfd) return FALSE; /* Allocate enough room for all the symbols in cached form. */ - cached_area = (coff_symbol_type *) bfd_alloc2 (abfd, - obj_raw_syment_count (abfd), - sizeof (coff_symbol_type)); + if (_bfd_mul_overflow (obj_raw_syment_count (abfd), + sizeof (*cached_area), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } + cached_area = (coff_symbol_type *) bfd_alloc (abfd, amt); if (cached_area == NULL) return FALSE; - table_ptr = (unsigned int *) bfd_zalloc2 (abfd, obj_raw_syment_count (abfd), - sizeof (unsigned int)); - + if (_bfd_mul_overflow (obj_raw_syment_count (abfd), + sizeof (*table_ptr), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } + table_ptr = (unsigned int *) bfd_zalloc (abfd, amt); if (table_ptr == NULL) return FALSE; else @@ -4963,6 +4989,7 @@ coff_slurp_reloc_table (bfd * abfd, sec_ptr asect, asymbol ** symbols) arelent *reloc_cache; arelent *cache_ptr; unsigned int idx; + size_t amt; if (asect->relocation) return TRUE; @@ -4976,9 +5003,12 @@ coff_slurp_reloc_table (bfd * abfd, sec_ptr asect, asymbol ** symbols) native_relocs = (RELOC *) buy_and_read (abfd, asect->rel_filepos, asect->reloc_count, bfd_coff_relsz (abfd)); - reloc_cache = (arelent *) bfd_alloc2 (abfd, asect->reloc_count, - sizeof (arelent)); - + if (_bfd_mul_overflow (asect->reloc_count, sizeof (arelent), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } + reloc_cache = (arelent *) bfd_alloc (abfd, amt); if (reloc_cache == NULL || native_relocs == NULL) return FALSE; diff --git a/bfd/coffgen.c b/bfd/coffgen.c index 5287130490..20cee0a74c 100644 --- a/bfd/coffgen.c +++ b/bfd/coffgen.c @@ -1639,30 +1639,29 @@ copy_name (bfd *abfd, char *name, size_t maxlen) bfd_boolean _bfd_coff_get_external_symbols (bfd *abfd) { - bfd_size_type symesz; - bfd_size_type size; + size_t symesz; + size_t size; void * syms; ufile_ptr filesize; if (obj_coff_external_syms (abfd) != NULL) return TRUE; - symesz = bfd_coff_symesz (abfd); - size = obj_raw_syment_count (abfd) * symesz; - if (size == 0) - return TRUE; - /* Check for integer overflow and for unreasonable symbol counts. */ filesize = bfd_get_file_size (abfd); - if (size < obj_raw_syment_count (abfd) + symesz = bfd_coff_symesz (abfd); + if (_bfd_mul_overflow (obj_raw_syment_count (abfd), symesz, &size) || (filesize != 0 && size > filesize)) - { + bfd_set_error (bfd_error_file_truncated); _bfd_error_handler (_("%pB: corrupt symbol count: %#" PRIx64 ""), abfd, (uint64_t) obj_raw_syment_count (abfd)); return FALSE; } + if (size == 0) + return TRUE; + syms = bfd_malloc (size); if (syms == NULL) { diff --git a/bfd/ecoff.c b/bfd/ecoff.c index e8ccbd45df..15c18aca76 100644 --- a/bfd/ecoff.c +++ b/bfd/ecoff.c @@ -514,6 +514,7 @@ _bfd_ecoff_slurp_symbolic_info (bfd *abfd, bfd_size_type raw_end; bfd_size_type cb_end; file_ptr pos; + size_t amt; BFD_ASSERT (debug == &ecoff_data (abfd)->debug_info); @@ -615,8 +616,13 @@ _bfd_ecoff_slurp_symbolic_info (bfd *abfd, We need to look at the fdr to deal with a lot of information in the symbols, so we swap them here. */ - debug->fdr = (FDR *) bfd_alloc2 (abfd, internal_symhdr->ifdMax, - sizeof (struct fdr)); + if (_bfd_mul_overflow ((unsigned long) internal_symhdr->ifdMax, + sizeof (struct fdr), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } + debug->fdr = (FDR *) bfd_alloc (abfd, amt); if (debug->fdr == NULL) return FALSE; external_fdr_size = backend->debug_swap.external_fdr_size; @@ -872,6 +878,7 @@ _bfd_ecoff_slurp_symbol_table (bfd *abfd) char *eraw_end; FDR *fdr_ptr; FDR *fdr_end; + size_t amt; /* If we've already read in the symbol table, do nothing. */ if (ecoff_data (abfd)->canonical_symbols != NULL) @@ -884,8 +891,13 @@ _bfd_ecoff_slurp_symbol_table (bfd *abfd) if (bfd_get_symcount (abfd) == 0) return TRUE; - internal = (ecoff_symbol_type *) bfd_alloc2 (abfd, bfd_get_symcount (abfd), - sizeof (ecoff_symbol_type)); + if (_bfd_mul_overflow (bfd_get_symcount (abfd), + sizeof (ecoff_symbol_type), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } + internal = (ecoff_symbol_type *) bfd_alloc (abfd, amt); if (internal == NULL) return FALSE; @@ -3745,25 +3757,32 @@ ecoff_final_link_debug_accumulate (bfd *output_bfd, HDRR *symhdr = &debug->symbolic_header; bfd_boolean ret; -#define READ(ptr, offset, count, size, type) \ - if (symhdr->count == 0) \ - debug->ptr = NULL; \ - else \ - { \ - bfd_size_type amt = (bfd_size_type) size * symhdr->count; \ - debug->ptr = (type) bfd_malloc (amt); \ - if (debug->ptr == NULL) \ - { \ - ret = FALSE; \ - goto return_something; \ - } \ - if (bfd_seek (input_bfd, (file_ptr) symhdr->offset, SEEK_SET) != 0 \ - || bfd_bread (debug->ptr, amt, input_bfd) != amt) \ - { \ - ret = FALSE; \ - goto return_something; \ - } \ - } +#define READ(ptr, offset, count, size, type) \ + do \ + { \ + size_t amt; \ + debug->ptr = NULL; \ + if (symhdr->count == 0) \ + break; \ + if (_bfd_mul_overflow (size, symhdr->count, &amt)) \ + { \ + bfd_set_error (bfd_error_file_too_big); \ + ret = FALSE; \ + goto return_something; \ + } \ + debug->ptr = (type) bfd_malloc (amt); \ + if (debug->ptr == NULL) \ + { \ + ret = FALSE; \ + goto return_something; \ + } \ + if (bfd_seek (input_bfd, symhdr->offset, SEEK_SET) != 0 \ + || bfd_bread (debug->ptr, amt, input_bfd) != amt) \ + { \ + ret = FALSE; \ + goto return_something; \ + } \ + } while (0) /* If raw_syments is not NULL, then the data was already by read by _bfd_ecoff_slurp_symbolic_info. */ diff --git a/bfd/elf.c b/bfd/elf.c index 8f18daf687..a3af7ef2af 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -402,7 +402,7 @@ bfd_elf_get_elf_syms (bfd *ibfd, Elf_Internal_Sym *isymend; const struct elf_backend_data *bed; size_t extsym_size; - bfd_size_type amt; + size_t amt; file_ptr pos; if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) @@ -448,11 +448,16 @@ bfd_elf_get_elf_syms (bfd *ibfd, alloc_intsym = NULL; bed = get_elf_backend_data (ibfd); extsym_size = bed->s->sizeof_sym; - amt = (bfd_size_type) symcount * extsym_size; + if (_bfd_mul_overflow (symcount, extsym_size, &amt)) + { + bfd_set_error (bfd_error_file_too_big); + intsym_buf = NULL; + goto out; + } pos = symtab_hdr->sh_offset + symoffset * extsym_size; if (extsym_buf == NULL) { - alloc_ext = bfd_malloc2 (symcount, extsym_size); + alloc_ext = bfd_malloc (amt); extsym_buf = alloc_ext; } if (extsym_buf == NULL @@ -467,12 +472,16 @@ bfd_elf_get_elf_syms (bfd *ibfd, extshndx_buf = NULL; else { - amt = (bfd_size_type) symcount * sizeof (Elf_External_Sym_Shndx); + if (_bfd_mul_overflow (symcount, sizeof (Elf_External_Sym_Shndx), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + intsym_buf = NULL; + goto out; + } pos = shndx_hdr->sh_offset + symoffset * sizeof (Elf_External_Sym_Shndx); if (extshndx_buf == NULL) { - alloc_extshndx = (Elf_External_Sym_Shndx *) - bfd_malloc2 (symcount, sizeof (Elf_External_Sym_Shndx)); + alloc_extshndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt); extshndx_buf = alloc_extshndx; } if (extshndx_buf == NULL @@ -486,8 +495,12 @@ bfd_elf_get_elf_syms (bfd *ibfd, if (intsym_buf == NULL) { - alloc_intsym = (Elf_Internal_Sym *) - bfd_malloc2 (symcount, sizeof (Elf_Internal_Sym)); + if (_bfd_mul_overflow (symcount, sizeof (Elf_Internal_Sym), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + goto out; + } + alloc_intsym = (Elf_Internal_Sym *) bfd_malloc (amt); intsym_buf = alloc_intsym; if (intsym_buf == NULL) goto out; @@ -629,15 +642,14 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect) { /* We keep a list of elf section headers for group sections, so we can find them quickly. */ - bfd_size_type amt; + size_t amt; elf_tdata (abfd)->num_group = num_group; - elf_tdata (abfd)->group_sect_ptr = (Elf_Internal_Shdr **) - bfd_alloc2 (abfd, num_group, sizeof (Elf_Internal_Shdr *)); + amt = num_group * sizeof (Elf_Internal_Shdr *); + elf_tdata (abfd)->group_sect_ptr + = (Elf_Internal_Shdr **) bfd_zalloc (abfd, amt); if (elf_tdata (abfd)->group_sect_ptr == NULL) return FALSE; - memset (elf_tdata (abfd)->group_sect_ptr, 0, - num_group * sizeof (Elf_Internal_Shdr *)); num_group = 0; for (i = 0; i < shnum; i++) @@ -659,24 +671,12 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect) num_group += 1; /* Read the raw contents. */ - BFD_ASSERT (sizeof (*dest) >= 4); - amt = shdr->sh_size * sizeof (*dest) / 4; - shdr->contents = (unsigned char *) - bfd_alloc2 (abfd, shdr->sh_size, sizeof (*dest) / 4); - /* PR binutils/4110: Handle corrupt group headers. */ - if (shdr->contents == NULL) - { - _bfd_error_handler - /* xgettext:c-format */ - (_("%pB: corrupt size field in group section" - " header: %#" PRIx64), - abfd, (uint64_t) shdr->sh_size); - bfd_set_error (bfd_error_bad_value); - -- num_group; - continue; - } - - if (bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0 + BFD_ASSERT (sizeof (*dest) >= 4 && sizeof (*dest) % 4 == 0); + shdr->contents = NULL; + if (_bfd_mul_overflow (shdr->sh_size, + sizeof (*dest) / 4, &amt) + || (shdr->contents = bfd_alloc (abfd, amt)) == NULL + || bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0 || (bfd_bread (shdr->contents, shdr->sh_size, abfd) != shdr->sh_size)) { @@ -690,8 +690,11 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect) /* PR 17510: If the group contents are even partially corrupt, do not allow any of the contents to be used. */ - bfd_release (abfd, shdr->contents); - shdr->contents = NULL; + if (shdr->contents != NULL) + { + bfd_release (abfd, shdr->contents); + shdr->contents = NULL; + } continue; } @@ -8015,7 +8018,7 @@ swap_out_syms (bfd *abfd, int relocatable_p) { const struct elf_backend_data *bed; - int symcount; + unsigned int symcount; asymbol **syms; struct elf_strtab_hash *stt; Elf_Internal_Shdr *symtab_hdr; @@ -8026,9 +8029,9 @@ swap_out_syms (bfd *abfd, bfd_byte *outbound_shndx; unsigned long outbound_syms_index; unsigned long outbound_shndx_index; - int idx; + unsigned int idx; unsigned int num_locals; - bfd_size_type amt; + size_t amt; bfd_boolean name_local_sections; if (!elf_map_symbols (abfd, &num_locals)) @@ -8052,21 +8055,22 @@ swap_out_syms (bfd *abfd, symstrtab_hdr->sh_type = SHT_STRTAB; /* Allocate buffer to swap out the .strtab section. */ - symstrtab = (struct elf_sym_strtab *) bfd_malloc2 (symcount + 1, - sizeof (*symstrtab)); - if (symstrtab == NULL) + if (_bfd_mul_overflow (symcount + 1, sizeof (*symstrtab), &amt) + || (symstrtab = (struct elf_sym_strtab *) bfd_malloc (amt)) == NULL) { + bfd_set_error (bfd_error_no_memory); _bfd_elf_strtab_free (stt); return FALSE; } - outbound_syms = (bfd_byte *) bfd_alloc2 (abfd, 1 + symcount, - bed->s->sizeof_sym); - if (outbound_syms == NULL) + if (_bfd_mul_overflow (symcount + 1, bed->s->sizeof_sym, &amt) + || (outbound_syms = (bfd_byte *) bfd_alloc (abfd, amt)) == NULL) { -error_return: - _bfd_elf_strtab_free (stt); + error_no_mem: + bfd_set_error (bfd_error_no_memory); + error_return: free (symstrtab); + _bfd_elf_strtab_free (stt); return FALSE; } symtab_hdr->contents = outbound_syms; @@ -8080,9 +8084,10 @@ error_return: symtab_shndx_hdr = & elf_symtab_shndx_list (abfd)->hdr; if (symtab_shndx_hdr->sh_name != 0) { - amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx); - outbound_shndx = (bfd_byte *) - bfd_zalloc2 (abfd, 1 + symcount, sizeof (Elf_External_Sym_Shndx)); + if (_bfd_mul_overflow (symcount + 1, + sizeof (Elf_External_Sym_Shndx), &amt)) + goto error_no_mem; + outbound_shndx = (bfd_byte *) bfd_zalloc (abfd, amt); if (outbound_shndx == NULL) goto error_return; @@ -8570,6 +8575,7 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver) { bfd_byte *contents = NULL; unsigned int freeidx = 0; + size_t amt; if (elf_dynverref (abfd) != 0) { @@ -8614,9 +8620,12 @@ error_return_verref: || bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size) goto error_return_verref; - elf_tdata (abfd)->verref = (Elf_Internal_Verneed *) - bfd_alloc2 (abfd, hdr->sh_info, sizeof (Elf_Internal_Verneed)); - + if (_bfd_mul_overflow (hdr->sh_info, sizeof (Elf_Internal_Verneed), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + goto error_return_verref; + } + elf_tdata (abfd)->verref = (Elf_Internal_Verneed *) bfd_alloc (abfd, amt); if (elf_tdata (abfd)->verref == NULL) goto error_return_verref; @@ -8645,9 +8654,14 @@ error_return_verref: iverneed->vn_auxptr = NULL; else { + if (_bfd_mul_overflow (iverneed->vn_cnt, + sizeof (Elf_Internal_Vernaux), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + goto error_return_verref; + } iverneed->vn_auxptr = (struct elf_internal_vernaux *) - bfd_alloc2 (abfd, iverneed->vn_cnt, - sizeof (Elf_Internal_Vernaux)); + bfd_alloc (abfd, amt); if (iverneed->vn_auxptr == NULL) goto error_return_verref; } @@ -8779,9 +8793,12 @@ error_return_verref: else freeidx = ++maxidx; } - - elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *) - bfd_zalloc2 (abfd, maxidx, sizeof (Elf_Internal_Verdef)); + if (_bfd_mul_overflow (maxidx, sizeof (Elf_Internal_Verdef), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + goto error_return_verdef; + } + elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *) bfd_zalloc (abfd, amt); if (elf_tdata (abfd)->verdef == NULL) goto error_return_verdef; @@ -8809,9 +8826,14 @@ error_return_verref: iverdef->vd_auxptr = NULL; else { + if (_bfd_mul_overflow (iverdef->vd_cnt, + sizeof (Elf_Internal_Verdaux), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + goto error_return_verdef; + } iverdef->vd_auxptr = (struct elf_internal_verdaux *) - bfd_alloc2 (abfd, iverdef->vd_cnt, - sizeof (Elf_Internal_Verdaux)); + bfd_alloc (abfd, amt); if (iverdef->vd_auxptr == NULL) goto error_return_verdef; } @@ -8874,8 +8896,12 @@ error_return_verref: else freeidx++; - elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *) - bfd_zalloc2 (abfd, freeidx, sizeof (Elf_Internal_Verdef)); + if (_bfd_mul_overflow (freeidx, sizeof (Elf_Internal_Verdef), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + goto error_return; + } + elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *) bfd_zalloc (abfd, amt); if (elf_tdata (abfd)->verdef == NULL) goto error_return; diff --git a/bfd/elf32-m32c.c b/bfd/elf32-m32c.c index 70ccd6203a..89bdccacd0 100644 --- a/bfd/elf32-m32c.c +++ b/bfd/elf32-m32c.c @@ -1491,10 +1491,14 @@ m32c_elf_relax_section if (shndx_hdr && shndx_hdr->sh_size != 0) { - bfd_size_type amt; + size_t amt; - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_External_Sym_Shndx); + if (_bfd_mul_overflow (symtab_hdr->sh_info, + sizeof (Elf_External_Sym_Shndx), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + goto error_return; + } shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); if (shndx_buf == NULL) goto error_return; diff --git a/bfd/elf32-rl78.c b/bfd/elf32-rl78.c index b7e3464c6f..f4abf0425e 100644 --- a/bfd/elf32-rl78.c +++ b/bfd/elf32-rl78.c @@ -2121,10 +2121,14 @@ rl78_elf_relax_section if (shndx_hdr && shndx_hdr->sh_size != 0) { - bfd_size_type amt; + size_t amt; - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_External_Sym_Shndx); + if (_bfd_mul_overflow (symtab_hdr->sh_info, + sizeof (Elf_External_Sym_Shndx), &amt)) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); if (shndx_buf == NULL) goto error_return; diff --git a/bfd/elf32-rx.c b/bfd/elf32-rx.c index 744bbf24d5..a94aee729c 100644 --- a/bfd/elf32-rx.c +++ b/bfd/elf32-rx.c @@ -2058,10 +2058,14 @@ elf32_rx_relax_section (bfd * abfd, if (shndx_hdr && shndx_hdr->sh_size != 0) { - bfd_size_type amt; + size_t amt; - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_External_Sym_Shndx); + if (_bfd_mul_overflow (symtab_hdr->sh_info, + sizeof (Elf_External_Sym_Shndx), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + goto error_return; + } shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); if (shndx_buf == NULL) goto error_return; diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c index 96ce158b55..ae4be9f074 100644 --- a/bfd/elf64-alpha.c +++ b/bfd/elf64-alpha.c @@ -1387,18 +1387,24 @@ elf64_alpha_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) \ - if (symhdr->count == 0) \ - debug->ptr = NULL; \ - else \ + do \ { \ - bfd_size_type amt = (bfd_size_type) size * symhdr->count; \ + size_t amt; \ + debug->ptr = NULL; \ + if (symhdr->count == 0) \ + break; \ + if (_bfd_mul_overflow (size, symhdr->count, &amt)) \ + { \ + bfd_set_error (bfd_error_file_too_big); \ + goto error_return; \ + } \ debug->ptr = (type) bfd_malloc (amt); \ if (debug->ptr == NULL) \ goto error_return; \ if (bfd_seek (abfd, (file_ptr) symhdr->offset, SEEK_SET) != 0 \ || bfd_bread (debug->ptr, amt, abfd) != amt) \ goto error_return; \ - } + } while (0) READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *); READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, void *); diff --git a/bfd/elfcode.h b/bfd/elfcode.h index a6b0c613ba..e7dfdee95e 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -687,19 +687,18 @@ elf_object_p (bfd *abfd) { Elf_Internal_Shdr *shdrp; unsigned int num_sec; + size_t amt; -#ifndef BFD64 - if (i_ehdrp->e_shnum > ((bfd_size_type) -1) / sizeof (*i_shdrp)) + if (_bfd_mul_overflow (i_ehdrp->e_shnum, sizeof (*i_shdrp), &amt)) goto got_wrong_format_error; -#endif - i_shdrp = (Elf_Internal_Shdr *) bfd_alloc2 (abfd, i_ehdrp->e_shnum, - sizeof (*i_shdrp)); + i_shdrp = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt); if (!i_shdrp) goto got_no_match; num_sec = i_ehdrp->e_shnum; elf_numsections (abfd) = num_sec; - elf_elfsections (abfd) - = (Elf_Internal_Shdr **) bfd_alloc2 (abfd, num_sec, sizeof (i_shdrp)); + if (_bfd_mul_overflow (num_sec, sizeof (i_shdrp), &amt)) + goto got_wrong_format_error; + elf_elfsections (abfd) = (Elf_Internal_Shdr **) bfd_alloc (abfd, amt); if (!elf_elfsections (abfd)) goto got_no_match; @@ -781,20 +780,18 @@ elf_object_p (bfd *abfd) Elf_Internal_Phdr *i_phdr; unsigned int i; ufile_ptr filesize; + size_t amt; -#ifndef BFD64 - if (i_ehdrp->e_phnum > ((bfd_size_type) -1) / sizeof (*i_phdr)) - goto got_wrong_format_error; -#endif /* Check for a corrupt input file with an impossibly large number of program headers. */ filesize = bfd_get_file_size (abfd); if (filesize != 0 && i_ehdrp->e_phnum > filesize / sizeof (Elf_External_Phdr)) goto got_wrong_format_error; + if (_bfd_mul_overflow (i_ehdrp->e_phnum, sizeof (*i_phdr), &amt)) + goto got_wrong_format_error; elf_tdata (abfd)->phdr - = (Elf_Internal_Phdr *) bfd_alloc2 (abfd, i_ehdrp->e_phnum, - sizeof (*i_phdr)); + = (Elf_Internal_Phdr *) bfd_alloc (abfd, amt); if (elf_tdata (abfd)->phdr == NULL) goto got_no_match; if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_phoff, SEEK_SET) != 0) @@ -881,6 +878,7 @@ elf_write_relocs (bfd *abfd, asection *sec, void *data) unsigned int idx; asymbol *last_sym; int last_sym_idx; + size_t amt; /* If we have already failed, don't do anything. */ if (*failedp) @@ -907,10 +905,10 @@ elf_write_relocs (bfd *abfd, asection *sec, void *data) rela_hdr = elf_section_data (sec)->rel.hdr; rela_hdr->sh_size = rela_hdr->sh_entsize * sec->reloc_count; - rela_hdr->contents = (unsigned char *) bfd_alloc2 (abfd, sec->reloc_count, - rela_hdr->sh_entsize); - if (rela_hdr->contents == NULL) + if (_bfd_mul_overflow (sec->reloc_count, rela_hdr->sh_entsize, &amt) + || (rela_hdr->contents = bfd_alloc (abfd, amt)) == NULL) { + bfd_set_error (bfd_error_no_memory); *failedp = TRUE; return; } @@ -1019,7 +1017,7 @@ elf_write_shdrs_and_ehdr (bfd *abfd) Elf_External_Shdr *x_shdrp; /* Section header table, external form */ Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */ unsigned int count; - bfd_size_type amt; + size_t amt; i_ehdrp = elf_elfheader (abfd); i_shdrp = elf_elfsections (abfd); @@ -1045,8 +1043,12 @@ elf_write_shdrs_and_ehdr (bfd *abfd) i_shdrp[0]->sh_link = i_ehdrp->e_shstrndx; /* at this point we've concocted all the ELF sections... */ - x_shdrp = (Elf_External_Shdr *) bfd_alloc2 (abfd, i_ehdrp->e_shnum, - sizeof (*x_shdrp)); + if (_bfd_mul_overflow (i_ehdrp->e_shnum, sizeof (*x_shdrp), &amt)) + { + bfd_set_error (bfd_error_no_memory); + return FALSE; + } + x_shdrp = (Elf_External_Shdr *) bfd_alloc (abfd, amt); if (!x_shdrp) return FALSE; @@ -1157,6 +1159,7 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic) Elf_External_Versym *xver; Elf_External_Versym *xverbuf = NULL; const struct elf_backend_data *ebd; + size_t amt; /* Read each raw ELF symbol, converting from external ELF form to internal ELF form, and then using the information to create a @@ -1201,8 +1204,12 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic) if (isymbuf == NULL) return -1; - symbase = (elf_symbol_type *) bfd_zalloc2 (abfd, symcount, - sizeof (elf_symbol_type)); + if (_bfd_mul_overflow (symcount, sizeof (elf_symbol_type), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + goto error_return; + } + symbase = (elf_symbol_type *) bfd_zalloc (abfd, amt); if (symbase == (elf_symbol_type *) NULL) goto error_return; @@ -1522,6 +1529,7 @@ elf_slurp_reloc_table (bfd *abfd, bfd_size_type reloc_count; bfd_size_type reloc_count2; arelent *relents; + size_t amt; if (asect->relocation != NULL) return TRUE; @@ -1559,8 +1567,12 @@ elf_slurp_reloc_table (bfd *abfd, reloc_count2 = 0; } - relents = (arelent *) bfd_alloc2 (abfd, reloc_count + reloc_count2, - sizeof (arelent)); + if (_bfd_mul_overflow (reloc_count + reloc_count2, sizeof (arelent), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } + relents = (arelent *) bfd_alloc (abfd, amt); if (relents == NULL) return FALSE; @@ -1660,6 +1672,7 @@ NAME(_bfd_elf,bfd_from_remote_memory) bfd_vma shdr_end; bfd_vma loadbase; char *filename; + size_t amt; /* Read in the ELF header in external format. */ err = target_read_memory (ehdr_vma, (bfd_byte *) &x_ehdr, sizeof x_ehdr); @@ -1716,9 +1729,13 @@ NAME(_bfd_elf,bfd_from_remote_memory) return NULL; } - x_phdrs - = (Elf_External_Phdr *) bfd_malloc2 (i_ehdr.e_phnum, - sizeof (*x_phdrs) + sizeof (*i_phdrs)); + if (_bfd_mul_overflow (i_ehdr.e_phnum, + sizeof (*x_phdrs) + sizeof (*i_phdrs), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return NULL; + } + x_phdrs = (Elf_External_Phdr *) bfd_malloc (amt); if (x_phdrs == NULL) return NULL; err = target_read_memory (ehdr_vma + i_ehdr.e_phoff, (bfd_byte *) x_phdrs, diff --git a/bfd/elfcore.h b/bfd/elfcore.h index 60339bc65f..eaf40f24cc 100644 --- a/bfd/elfcore.h +++ b/bfd/elfcore.h @@ -335,6 +335,7 @@ NAME(_bfd_elf, core_find_build_id) Elf_Internal_Ehdr i_ehdr; /* Elf file header, internal form. */ Elf_Internal_Phdr *i_phdr; unsigned int i; + size_t amt; /* Seek to the position of the segment at OFFSET. */ if (bfd_seek (abfd, offset, SEEK_SET) != 0) @@ -384,8 +385,12 @@ NAME(_bfd_elf, core_find_build_id) goto fail; /* Read in program headers. */ - i_phdr = (Elf_Internal_Phdr *) bfd_alloc2 (abfd, i_ehdr.e_phnum, - sizeof (*i_phdr)); + if (_bfd_mul_overflow (i_ehdr.e_phnum, sizeof (*i_phdr), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + goto fail; + } + i_phdr = (Elf_Internal_Phdr *) bfd_alloc (abfd, amt); if (i_phdr == NULL) goto fail; diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index a05c67154c..81ed9b390a 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -1413,18 +1413,24 @@ _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) \ - if (symhdr->count == 0) \ - debug->ptr = NULL; \ - else \ + do \ { \ - bfd_size_type amt = (bfd_size_type) size * symhdr->count; \ + size_t amt; \ + debug->ptr = NULL; \ + if (symhdr->count == 0) \ + break; \ + if (_bfd_mul_overflow (size, symhdr->count, &amt)) \ + { \ + bfd_set_error (bfd_error_file_too_big); \ + goto error_return; \ + } \ debug->ptr = bfd_malloc (amt); \ if (debug->ptr == NULL) \ goto error_return; \ if (bfd_seek (abfd, symhdr->offset, SEEK_SET) != 0 \ || bfd_bread (debug->ptr, amt, abfd) != amt) \ goto error_return; \ - } + } while (0) READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *); READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, void *); diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h index 20bf85cc0c..00650c3c86 100644 --- a/bfd/libbfd-in.h +++ b/bfd/libbfd-in.h @@ -116,12 +116,6 @@ extern void *bfd_realloc_or_free (void *, bfd_size_type) ATTRIBUTE_HIDDEN; extern void *bfd_zmalloc (bfd_size_type) ATTRIBUTE_HIDDEN; -extern void *bfd_malloc2 - (bfd_size_type, bfd_size_type) ATTRIBUTE_HIDDEN; -extern void *bfd_realloc2 - (void *, bfd_size_type, bfd_size_type) ATTRIBUTE_HIDDEN; -extern void *bfd_zmalloc2 - (bfd_size_type, bfd_size_type) ATTRIBUTE_HIDDEN; static inline char * bfd_strdup (const char *str) @@ -134,10 +128,6 @@ bfd_strdup (const char *str) } /* These routines allocate and free things on the BFD's objalloc. */ -extern void *bfd_alloc2 - (bfd *, bfd_size_type, bfd_size_type) ATTRIBUTE_HIDDEN; -extern void *bfd_zalloc2 - (bfd *, bfd_size_type, bfd_size_type) ATTRIBUTE_HIDDEN; extern void bfd_release (bfd *, void *) ATTRIBUTE_HIDDEN; @@ -905,3 +895,11 @@ extern bfd_signed_vma _bfd_read_signed_leb128 extern bfd_vma _bfd_safe_read_leb128 (bfd *, bfd_byte *, unsigned int *, bfd_boolean, const bfd_byte * const) ATTRIBUTE_HIDDEN; + +#if GCC_VERSION >= 7000 +#define _bfd_mul_overflow(a, b, res) __builtin_mul_overflow (a, b, res) +#else +/* Assumes unsigned values. Careful! Args evaluated multiple times. */ +#define _bfd_mul_overflow(a, b, res) \ + ((*res) = (a), (*res) *= (b), (b) != 0 && (*res) / (b) != (a)) +#endif diff --git a/bfd/libbfd.c b/bfd/libbfd.c index 84fadb234b..cb7c3b5aba 100644 --- a/bfd/libbfd.c +++ b/bfd/libbfd.c @@ -279,24 +279,6 @@ bfd_malloc (bfd_size_type size) return ptr; } -/* Allocate memory using malloc, nmemb * size with overflow checking. */ - -void * -bfd_malloc2 (bfd_size_type nmemb, bfd_size_type size) -{ - if ((nmemb | size) >= HALF_BFD_SIZE_TYPE - && size != 0 - && nmemb > ~(bfd_size_type) 0 / size) - { - bfd_set_error (bfd_error_no_memory); - return NULL; - } - - return bfd_malloc (size * nmemb); -} - -/* Reallocate memory using realloc. */ - void * bfd_realloc (void *ptr, bfd_size_type size) { @@ -322,22 +304,6 @@ bfd_realloc (void *ptr, bfd_size_type size) return ret; } -/* Reallocate memory using realloc, nmemb * size with overflow checking. */ - -void * -bfd_realloc2 (void *ptr, bfd_size_type nmemb, bfd_size_type size) -{ - if ((nmemb | size) >= HALF_BFD_SIZE_TYPE - && size != 0 - && nmemb > ~(bfd_size_type) 0 / size) - { - bfd_set_error (bfd_error_no_memory); - return NULL; - } - - return bfd_realloc (ptr, size * nmemb); -} - /* Reallocate memory using realloc. If this fails the pointer is freed before returning. */ @@ -365,25 +331,6 @@ bfd_zmalloc (bfd_size_type size) return ptr; } -/* Allocate memory using malloc (nmemb * size) with overflow checking - and clear it. */ - -void * -bfd_zmalloc2 (bfd_size_type nmemb, bfd_size_type size) -{ - void *ptr = bfd_malloc2 (nmemb, size); - - if (ptr != NULL) - { - size_t sz = nmemb * size; - - if (sz > 0) - memset (ptr, 0, sz); - } - - return ptr; -} - /* INTERNAL_FUNCTION bfd_write_bigendian_4byte_int diff --git a/bfd/mach-o.c b/bfd/mach-o.c index a18c68c6d8..1cc9d43250 100644 --- a/bfd/mach-o.c +++ b/bfd/mach-o.c @@ -2554,6 +2554,7 @@ bfd_mach_o_mangle_sections (bfd *abfd, bfd_mach_o_data_struct *mdata) asection *sec; unsigned target_index; unsigned nsect; + size_t amt; nsect = bfd_count_sections (abfd); @@ -2572,8 +2573,12 @@ bfd_mach_o_mangle_sections (bfd *abfd, bfd_mach_o_data_struct *mdata) } mdata->nsects = nsect; - mdata->sections = bfd_alloc2 (abfd, - mdata->nsects, sizeof (bfd_mach_o_section *)); + if (_bfd_mul_overflow (mdata->nsects, sizeof (bfd_mach_o_section *), &amt)) + { + bfd_set_error (bfd_error_no_memory); + return FALSE; + } + mdata->sections = bfd_alloc (abfd, amt); if (mdata->sections == NULL) return FALSE; @@ -3923,14 +3928,16 @@ bfd_mach_o_read_symtab_symbols (bfd *abfd) bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd); bfd_mach_o_symtab_command *sym = mdata->symtab; unsigned long i; + size_t amt; if (sym == NULL || sym->symbols) /* Return now if there are no symbols or if already loaded. */ return TRUE; - sym->symbols = bfd_alloc2 (abfd, sym->nsyms, sizeof (bfd_mach_o_asymbol)); - if (sym->symbols == NULL) + if (_bfd_mul_overflow (sym->nsyms, sizeof (bfd_mach_o_asymbol), &amt) + || (sym->symbols = bfd_alloc (abfd, amt)) == NULL) { + bfd_set_error (bfd_error_no_memory); _bfd_error_handler (_("bfd_mach_o_read_symtab_symbols: " "unable to allocate memory for symbols")); sym->nsyms = 0; @@ -4174,6 +4181,7 @@ bfd_mach_o_read_thread (bfd *abfd, bfd_mach_o_load_command *command) unsigned int nflavours; unsigned int i; struct mach_o_thread_command_external raw; + size_t amt; BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD) || (command->type == BFD_MACH_O_LC_UNIXTHREAD)); @@ -4200,8 +4208,12 @@ bfd_mach_o_read_thread (bfd *abfd, bfd_mach_o_load_command *command) return FALSE; /* Allocate threads. */ - cmd->flavours = bfd_alloc2 (abfd, nflavours, - sizeof (bfd_mach_o_thread_flavour)); + if (_bfd_mul_overflow (nflavours, sizeof (bfd_mach_o_thread_flavour), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } + cmd->flavours = bfd_alloc (abfd, amt); if (cmd->flavours == NULL) return FALSE; cmd->nflavours = nflavours; @@ -4315,9 +4327,15 @@ bfd_mach_o_read_dysymtab (bfd *abfd, bfd_mach_o_load_command *command) unsigned int i; int wide = bfd_mach_o_wide_p (abfd); unsigned int module_len = wide ? 56 : 52; + size_t amt; - cmd->dylib_module = - bfd_alloc2 (abfd, cmd->nmodtab, sizeof (bfd_mach_o_dylib_module)); + if (_bfd_mul_overflow (cmd->nmodtab, + sizeof (bfd_mach_o_dylib_module), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } + cmd->dylib_module = bfd_alloc (abfd, amt); if (cmd->dylib_module == NULL) return FALSE; @@ -4364,9 +4382,15 @@ bfd_mach_o_read_dysymtab (bfd *abfd, bfd_mach_o_load_command *command) if (cmd->ntoc != 0) { unsigned long i; + size_t amt; - cmd->dylib_toc = bfd_alloc2 - (abfd, cmd->ntoc, sizeof (bfd_mach_o_dylib_table_of_content)); + if (_bfd_mul_overflow (cmd->ntoc, + sizeof (bfd_mach_o_dylib_table_of_content), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } + cmd->dylib_toc = bfd_alloc (abfd, amt); if (cmd->dylib_toc == NULL) return FALSE; @@ -4389,9 +4413,14 @@ bfd_mach_o_read_dysymtab (bfd *abfd, bfd_mach_o_load_command *command) if (cmd->nindirectsyms != 0) { unsigned int i; + size_t amt; - cmd->indirect_syms = bfd_alloc2 - (abfd, cmd->nindirectsyms, sizeof (unsigned int)); + if (_bfd_mul_overflow (cmd->nindirectsyms, sizeof (unsigned int), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } + cmd->indirect_syms = bfd_alloc (abfd, amt); if (cmd->indirect_syms == NULL) return FALSE; @@ -4414,9 +4443,15 @@ bfd_mach_o_read_dysymtab (bfd *abfd, bfd_mach_o_load_command *command) { unsigned long v; unsigned int i; + size_t amt; - cmd->ext_refs = bfd_alloc2 - (abfd, cmd->nextrefsyms, sizeof (bfd_mach_o_dylib_reference)); + if (_bfd_mul_overflow (cmd->nextrefsyms, + sizeof (bfd_mach_o_dylib_reference), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } + cmd->ext_refs = bfd_alloc (abfd, amt); if (cmd->ext_refs == NULL) return FALSE; @@ -5005,6 +5040,7 @@ bfd_mach_o_flatten_sections (bfd *abfd) bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd); bfd_mach_o_load_command *cmd; long csect = 0; + size_t amt; /* Count total number of sections. */ mdata->nsects = 0; @@ -5021,8 +5057,12 @@ bfd_mach_o_flatten_sections (bfd *abfd) } /* Allocate sections array. */ - mdata->sections = bfd_alloc2 (abfd, - mdata->nsects, sizeof (bfd_mach_o_section *)); + if (_bfd_mul_overflow (mdata->nsects, sizeof (bfd_mach_o_section *), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } + mdata->sections = bfd_alloc (abfd, amt); if (mdata->sections == NULL && mdata->nsects != 0) return FALSE; @@ -5195,11 +5235,18 @@ bfd_mach_o_scan (bfd *abfd, if (header->ncmds != 0) { bfd_mach_o_load_command *cmd; + size_t amt; mdata->first_command = NULL; mdata->last_command = NULL; - cmd = bfd_alloc2 (abfd, header->ncmds, sizeof (bfd_mach_o_load_command)); + if (_bfd_mul_overflow (header->ncmds, + sizeof (bfd_mach_o_load_command), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } + cmd = bfd_alloc (abfd, amt); if (cmd == NULL) return FALSE; @@ -5418,6 +5465,7 @@ bfd_mach_o_fat_archive_p (bfd *abfd) mach_o_fat_data_struct *adata = NULL; struct mach_o_fat_header_external hdr; unsigned long i; + size_t amt; if (bfd_seek (abfd, 0, SEEK_SET) != 0 || bfd_bread (&hdr, sizeof (hdr), abfd) != sizeof (hdr)) @@ -5437,8 +5485,13 @@ bfd_mach_o_fat_archive_p (bfd *abfd) if (adata->nfat_arch > 30) goto error; - adata->archentries = - bfd_alloc2 (abfd, adata->nfat_arch, sizeof (mach_o_fat_archentry)); + if (_bfd_mul_overflow (adata->nfat_arch, + sizeof (mach_o_fat_archentry), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + goto error; + } + adata->archentries = bfd_alloc (abfd, amt); if (adata->archentries == NULL) goto error; diff --git a/bfd/opncls.c b/bfd/opncls.c index 796202d31a..99097a9e39 100644 --- a/bfd/opncls.c +++ b/bfd/opncls.c @@ -981,32 +981,6 @@ bfd_alloc (bfd *abfd, bfd_size_type size) return ret; } -/* -INTERNAL_FUNCTION - bfd_alloc2 - -SYNOPSIS - void *bfd_alloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size); - -DESCRIPTION - Allocate a block of @var{nmemb} elements of @var{size} bytes each - of memory attached to <> and return a pointer to it. -*/ - -void * -bfd_alloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size) -{ - if ((nmemb | size) >= HALF_BFD_SIZE_TYPE - && size != 0 - && nmemb > ~(bfd_size_type) 0 / size) - { - bfd_set_error (bfd_error_no_memory); - return NULL; - } - - return bfd_alloc (abfd, size * nmemb); -} - /* FUNCTION bfd_zalloc @@ -1030,39 +1004,6 @@ bfd_zalloc (bfd *abfd, bfd_size_type size) return res; } -/* -INTERNAL_FUNCTION - bfd_zalloc2 - -SYNOPSIS - void *bfd_zalloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size); - -DESCRIPTION - Allocate a block of @var{nmemb} elements of @var{size} bytes each - of zeroed memory attached to <> and return a pointer to it. -*/ - -void * -bfd_zalloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size) -{ - void *res; - - if ((nmemb | size) >= HALF_BFD_SIZE_TYPE - && size != 0 - && nmemb > ~(bfd_size_type) 0 / size) - { - bfd_set_error (bfd_error_no_memory); - return NULL; - } - - size *= nmemb; - - res = bfd_alloc (abfd, size); - if (res) - memset (res, 0, (size_t) size); - return res; -} - /* Free a block allocated for a BFD. Note: Also frees all more recently allocated blocks! */ diff --git a/bfd/som.c b/bfd/som.c index 9c29230ece..d7d4d8f845 100644 --- a/bfd/som.c +++ b/bfd/som.c @@ -2079,17 +2079,17 @@ setup_sections (bfd *abfd, unsigned int total_subspaces = 0; asection **subspace_sections = NULL; asection *section; - bfd_size_type amt; + size_t amt; /* First, read in space names. */ amt = file_hdr->space_strings_size; - if (amt == (bfd_size_type) -1) + if (amt == (size_t) -1) { bfd_set_error (bfd_error_no_memory); goto error_return; } space_strings = bfd_malloc (amt + 1); - if (space_strings == NULL && amt != 0) + if (space_strings == NULL) goto error_return; if (bfd_seek (abfd, current_offset + file_hdr->space_strings_location, @@ -2344,7 +2344,12 @@ setup_sections (bfd *abfd, } /* Now that we've read in all the subspace records, we need to assign a target index to each subspace. */ - subspace_sections = bfd_malloc2 (total_subspaces, sizeof (asection *)); + if (_bfd_mul_overflow (total_subspaces, sizeof (asection *), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + goto error_return; + } + subspace_sections = bfd_malloc (amt); if (subspace_sections == NULL) goto error_return; @@ -2804,6 +2809,7 @@ som_prep_for_fixups (bfd *abfd, asymbol **syms, unsigned long num_syms) unsigned long i; asection *section; asymbol **sorted_syms; + size_t amt; /* Most SOM relocations involving a symbol have a length which is dependent on the index of the symbol. So symbols which are @@ -2875,7 +2881,12 @@ som_prep_for_fixups (bfd *abfd, asymbol **syms, unsigned long num_syms) /* Sort a copy of the symbol table, rather than the canonical output symbol table. */ - sorted_syms = bfd_zalloc2 (abfd, num_syms, sizeof (asymbol *)); + if (_bfd_mul_overflow (num_syms, sizeof (asymbol *), &amt)) + { + bfd_set_error (bfd_error_no_memory); + return FALSE; + } + sorted_syms = bfd_zalloc (abfd, amt); if (sorted_syms == NULL) return FALSE; memcpy (sorted_syms, syms, num_syms * sizeof (asymbol *)); @@ -4460,12 +4471,18 @@ som_build_and_write_symbol_table (bfd *abfd) struct som_external_symbol_dictionary_record *som_symtab = NULL; unsigned int i; bfd_size_type symtab_size; + size_t amt; /* Compute total symbol table size and allocate a chunk of memory to hold the symbol table as we build it. */ - som_symtab - = bfd_zmalloc2 (num_syms, - sizeof (struct som_external_symbol_dictionary_record)); + if (_bfd_mul_overflow (num_syms, + sizeof (struct som_external_symbol_dictionary_record), + &amt)) + { + bfd_set_error (bfd_error_no_memory); + return FALSE; + } + som_symtab = bfd_zmalloc (amt); if (som_symtab == NULL && num_syms != 0) goto error_return; @@ -4638,12 +4655,12 @@ bfd_section_from_som_symbol static unsigned int som_slurp_symbol_table (bfd *abfd) { - int symbol_count = bfd_get_symcount (abfd); - int symsize = sizeof (struct som_external_symbol_dictionary_record); + unsigned int symbol_count = bfd_get_symcount (abfd); + size_t symsize = sizeof (struct som_external_symbol_dictionary_record); char *stringtab; struct som_external_symbol_dictionary_record *buf = NULL, *bufp, *endbufp; som_symbol_type *sym, *symbase; - bfd_size_type amt; + size_t amt; /* Return saved value if it exists. */ if (obj_som_symtab (abfd) != NULL) @@ -4658,18 +4675,26 @@ som_slurp_symbol_table (bfd *abfd) stringtab = obj_som_stringtab (abfd); - symbase = bfd_zmalloc2 (symbol_count, sizeof (som_symbol_type)); + if (_bfd_mul_overflow (symbol_count, sizeof (som_symbol_type), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + goto error_return; + } + symbase = bfd_zmalloc (amt); if (symbase == NULL) goto error_return; /* Read in the external SOM representation. */ - buf = bfd_malloc2 (symbol_count, symsize); + if (_bfd_mul_overflow (symbol_count, symsize, &amt)) + { + bfd_set_error (bfd_error_file_too_big); + goto error_return; + } + buf = bfd_malloc (amt); if (buf == NULL) goto error_return; if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) != 0) goto error_return; - amt = symbol_count; - amt *= symsize; if (bfd_bread (buf, amt, abfd) != amt) goto error_return; @@ -5259,7 +5284,7 @@ som_slurp_reloc_table (bfd *abfd, unsigned int fixup_stream_size; arelent *internal_relocs; unsigned int num_relocs; - bfd_size_type amt; + size_t amt; fixup_stream_size = som_section_data (section)->reloc_size; /* If there were no relocations, then there is nothing to do. */ @@ -5303,7 +5328,12 @@ som_slurp_reloc_table (bfd *abfd, if (section->relocation != NULL) return TRUE; - internal_relocs = bfd_zalloc2 (abfd, num_relocs, sizeof (arelent)); + if (_bfd_mul_overflow (num_relocs, sizeof (arelent), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } + internal_relocs = bfd_zalloc (abfd, amt); if (internal_relocs == NULL) return FALSE; @@ -5884,12 +5914,17 @@ som_bfd_count_ar_symbols (bfd *abfd, { unsigned int i; unsigned char *hash_table; - bfd_size_type amt; + size_t amt; file_ptr lst_filepos; lst_filepos = bfd_tell (abfd) - sizeof (struct som_external_lst_header); - hash_table = bfd_malloc2 (lst_header->hash_size, 4); + if (_bfd_mul_overflow (lst_header->hash_size, 4, &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } + hash_table = bfd_malloc (amt); if (hash_table == NULL && lst_header->hash_size != 0) goto error_return; @@ -5898,7 +5933,6 @@ som_bfd_count_ar_symbols (bfd *abfd, /* Read in the hash table. The hash table is an array of 32-bit file offsets which point to the hash chains. */ - amt = (bfd_size_type) lst_header->hash_size * 4; if (bfd_bread ((void *) hash_table, amt, abfd) != amt) goto error_return; @@ -5975,18 +6009,22 @@ som_bfd_fill_in_ar_symbols (bfd *abfd, carsym *set = syms[0]; unsigned char *hash_table; struct som_external_som_entry *som_dict = NULL; - bfd_size_type amt; + size_t amt; file_ptr lst_filepos; unsigned int string_loc; lst_filepos = bfd_tell (abfd) - sizeof (struct som_external_lst_header); - hash_table = bfd_malloc2 (lst_header->hash_size, 4); + if (_bfd_mul_overflow (lst_header->hash_size, 4, &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } + hash_table = bfd_malloc (amt); if (hash_table == NULL && lst_header->hash_size != 0) goto error_return; /* Read in the hash table. The has table is an array of 32bit file offsets which point to the hash chains. */ - amt = (bfd_size_type) lst_header->hash_size * 4; if (bfd_bread ((void *) hash_table, amt, abfd) != amt) goto error_return; @@ -5995,13 +6033,16 @@ som_bfd_fill_in_ar_symbols (bfd *abfd, if (bfd_seek (abfd, lst_filepos + lst_header->dir_loc, SEEK_SET) != 0) goto error_return; - som_dict = bfd_malloc2 (lst_header->module_count, - sizeof (struct som_external_som_entry)); + if (_bfd_mul_overflow (lst_header->module_count, + sizeof (struct som_external_som_entry), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + goto error_return; + } + som_dict = bfd_malloc (amt); if (som_dict == NULL && lst_header->module_count != 0) goto error_return; - amt = lst_header->module_count; - amt *= sizeof (struct som_external_som_entry); if (bfd_bread ((void *) som_dict, amt, abfd) != amt) goto error_return; @@ -6156,7 +6197,7 @@ som_slurp_armap (bfd *abfd) unsigned int parsed_size; struct artdata *ardata = bfd_ardata (abfd); char nextname[17]; - bfd_size_type amt = 16; + size_t amt = 16; int i = bfd_bread ((void *) nextname, amt, abfd); /* Special cases. */ @@ -6225,7 +6266,12 @@ som_slurp_armap (bfd *abfd) /* Initialize the cache and allocate space for the library symbols. */ ardata->cache = 0; - ardata->symdefs = bfd_alloc2 (abfd, ardata->symdef_count, sizeof (carsym)); + if (_bfd_mul_overflow (ardata->symdef_count, sizeof (carsym), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } + ardata->symdefs = bfd_alloc (abfd, amt); if (!ardata->symdefs) return FALSE; @@ -6352,22 +6398,39 @@ som_bfd_ar_write_symbol_stuff (bfd *abfd, struct som_external_som_entry *som_dict = NULL; struct som_external_lst_symbol_record **last_hash_entry = NULL; unsigned int curr_som_offset, som_index = 0; - bfd_size_type amt; + size_t amt; unsigned int module_count; unsigned int hash_size; hash_size = bfd_getb32 (lst.hash_size); - hash_table = bfd_zmalloc2 (hash_size, 4); + if (_bfd_mul_overflow (hash_size, 4, &amt)) + { + bfd_set_error (bfd_error_no_memory); + return FALSE; + } + hash_table = bfd_zmalloc (amt); if (hash_table == NULL && hash_size != 0) goto error_return; module_count = bfd_getb32 (lst.module_count); - som_dict = bfd_zmalloc2 (module_count, sizeof (struct som_external_som_entry)); + if (_bfd_mul_overflow (module_count, + sizeof (struct som_external_som_entry), &amt)) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + som_dict = bfd_zmalloc (amt); if (som_dict == NULL && module_count != 0) goto error_return; - last_hash_entry - = bfd_zmalloc2 (hash_size, sizeof (struct som_external_lst_symbol_record *)); + if (_bfd_mul_overflow (hash_size, + sizeof (struct som_external_lst_symbol_record *), + &amt)) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + last_hash_entry = bfd_zmalloc (amt); if (last_hash_entry == NULL && hash_size != 0) goto error_return; @@ -6395,10 +6458,16 @@ som_bfd_ar_write_symbol_stuff (bfd *abfd, curr_som_offset = (curr_som_offset + 0x1) & ~0x1; /* FIXME should be done with buffers just like everything else... */ - lst_syms = bfd_malloc2 (nsyms, sizeof (struct som_external_lst_symbol_record)); + if (_bfd_mul_overflow (nsyms, + sizeof (struct som_external_lst_symbol_record), &amt)) + { + bfd_set_error (bfd_error_no_memory); + goto error_return; + } + lst_syms = bfd_malloc (amt); if (lst_syms == NULL && nsyms != 0) goto error_return; - strings = bfd_malloc ((bfd_size_type) string_size); + strings = bfd_malloc (string_size); if (strings == NULL && string_size != 0) goto error_return; @@ -6543,17 +6612,17 @@ som_bfd_ar_write_symbol_stuff (bfd *abfd, } /* Now scribble out the hash table. */ - amt = (bfd_size_type) hash_size * 4; + amt = (size_t) hash_size * 4; if (bfd_bwrite ((void *) hash_table, amt, abfd) != amt) goto error_return; /* Then the SOM dictionary. */ - amt = (bfd_size_type) module_count * sizeof (struct som_external_som_entry); + amt = (size_t) module_count * sizeof (struct som_external_som_entry); if (bfd_bwrite ((void *) som_dict, amt, abfd) != amt) goto error_return; /* The library symbols. */ - amt = (bfd_size_type) nsyms * sizeof (struct som_external_lst_symbol_record); + amt = (size_t) nsyms * sizeof (struct som_external_lst_symbol_record); if (bfd_bwrite ((void *) lst_syms, amt, abfd) != amt) goto error_return; diff --git a/bfd/vms-alpha.c b/bfd/vms-alpha.c index ac01c4dac8..24842780b6 100644 --- a/bfd/vms-alpha.c +++ b/bfd/vms-alpha.c @@ -2963,17 +2963,23 @@ vector_grow1 (struct vector_type *vec, size_t elsz) if (vec->max_el == 0) { vec->max_el = 16; - vec->els = bfd_malloc2 (vec->max_el, elsz); + vec->els = bfd_malloc (vec->max_el * elsz); } else { + size_t amt; if (vec->max_el > -1u / 2) { bfd_set_error (bfd_error_file_too_big); return NULL; } vec->max_el *= 2; - vec->els = bfd_realloc2 (vec->els, vec->max_el, elsz); + if (_bfd_mul_overflow (vec->max_el, elsz, &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return NULL; + } + vec->els = bfd_realloc (vec->els, amt); } } if (vec->els == NULL) diff --git a/bfd/vms-lib.c b/bfd/vms-lib.c index 3d14a46185..dc07e79710 100644 --- a/bfd/vms-lib.c +++ b/bfd/vms-lib.c @@ -134,12 +134,23 @@ vms_add_index (struct carsym_mem *cs, char *name, if (cs->nbr == cs->max) { struct carsym *n; + size_t amt; + if (cs->max > -33u / 2) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } cs->max = 2 * cs->max + 32; + if (_bfd_mul_overflow (cs->max, sizeof (struct carsym), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } if (!cs->realloced) { - n = bfd_malloc2 (cs->max, sizeof (struct carsym)); + n = bfd_malloc (amt); if (n == NULL) return FALSE; memcpy (n, cs->idx, cs->nbr * sizeof (struct carsym)); @@ -147,7 +158,7 @@ vms_add_index (struct carsym_mem *cs, char *name, } else { - n = bfd_realloc_or_free (cs->idx, cs->nbr * sizeof (struct carsym)); + n = bfd_realloc_or_free (cs->idx, amt); if (n == NULL) return FALSE; } diff --git a/bfd/wasm-module.c b/bfd/wasm-module.c index dfd3d873b2..315d3effb8 100644 --- a/bfd/wasm-module.c +++ b/bfd/wasm-module.c @@ -245,6 +245,7 @@ wasm_scan_name_function_section (bfd *abfd, sec_ptr asect) tdata_type *tdata = abfd->tdata.any; asymbol *symbols = NULL; sec_ptr space_function_index; + size_t amt; p = asect->contents; end = asect->contents + asect->size; @@ -301,7 +302,12 @@ wasm_scan_name_function_section (bfd *abfd, sec_ptr asect) if (!space_function_index) return FALSE; - symbols = bfd_alloc2 (abfd, tdata->symcount, sizeof (asymbol)); + if (_bfd_mul_overflow (tdata->symcount, sizeof (asymbol), &amt)) + { + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } + symbols = bfd_alloc (abfd, amt); if (!symbols) return FALSE; -- Alan Modra Australia Development Lab, IBM