From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 52959 invoked by alias); 19 Feb 2020 03:29:04 -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 52941 invoked by uid 89); 19 Feb 2020 03:29:03 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-23.2 required=5.0 tests=AWL,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-pj1-f49.google.com Received: from mail-pj1-f49.google.com (HELO mail-pj1-f49.google.com) (209.85.216.49) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 19 Feb 2020 03:29:01 +0000 Received: by mail-pj1-f49.google.com with SMTP id f2so1249934pjq.1 for ; Tue, 18 Feb 2020 19:29:01 -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=W/RRPkT84WvF887UgYB+LNYQlDU/ydGcMsGrivXlbaE=; b=Ie8YvklWg+c880Gyxe+32/qrMsgfVb38Ee1oSlS0a77EJOUTwVH1LugD/KznUkkyi+ 2a1ZS4mwG0ulroo0ebPvWSuTYE+jlT2x3rCwaAh9PJ5IZM07rJkfkysWcBTadaHdvsr7 g5/Ws8fZipsnwMeaKgRNXY8aq1nPAknd7//6jLK6DJwnYcJA6maHlWzTDh98x0ggkPqz ssta2CWvGTQa63qOfJuTPuwr04UdgkeIYAQ5EQDdLwZUiONYkC6EaIkQ4DcVk0arue9D I3oN3MZyo2AEYRluOK9FUFRffbU1r36zaW2NFnEu+Z42/3widjPbPpjtlEVt+dt9JGYe 751A== Return-Path: Received: from bubble.grove.modra.org (158.106.96.58.static.exetel.com.au. [58.96.106.158]) by smtp.gmail.com with ESMTPSA id q17sm368414pgn.94.2020.02.18.19.28.57 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Feb 2020 19:28:58 -0800 (PST) Received: by bubble.grove.modra.org (Postfix, from userid 1000) id C80598ADF5; Wed, 19 Feb 2020 13:58:54 +1030 (ACDT) Date: Wed, 19 Feb 2020 03:29:00 -0000 From: Alan Modra To: binutils@sourceware.org Subject: Miscellaneous memory alloc related fixes Message-ID: <20200219032854.GL5570@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/msg00440.txt.bz2 Some minor tidies. Allocating memory for internal relocs and symbols after reading external relocs is slightly better with fuzzed files. You can at least do something about silly sizes that way. * aoutx.h (slurp_reloc_table): Allocate reloc_cache after reading external relocs. * ecoff.c (ecoff_slurp_reloc_table): Likewise. * archive.c (_bfd_write_archive_contents): Don't twiddle bfd_error after bfd_bread. * archive64.c (_bfd_archive_64_bit_slurp_armap): Remove unnecessary bfd_release. * elf32-m32c.c (m32c_offset_for_reloc): Make shndx_buf a bfd_byte*. (m32c_elf_relax_section): Likewise. * elf32-rl78.c (rl78_offset_for_reloc): Likewise. (rl78_elf_relax_section): Likewise. * elf32-rx.c (rx_offset_for_reloc): Likewise. (elf32_rx_relax_section): Likewise. * mach-o.c (bfd_mach_o_alloc_and_read): Move earlier with better parameter types and use.. (bfd_mach_o_read_dylinker, bfd_mach_o_read_dylib), (bfd_mach_o_read_fvmlib, bfd_mach_o_read_str): ..in these functions. * peicode.h (pe_bfd_object_p): Don't zero the part of opthdr being read from file, just the extra. * som.c (som_slurp_symbol_table): Allocate internal symbol buffer after reading external syms. Free on failure. diff --git a/bfd/aoutx.h b/bfd/aoutx.h index df04ab2644..7cc72b4b67 100644 --- a/bfd/aoutx.h +++ b/bfd/aoutx.h @@ -2316,34 +2316,29 @@ NAME (aout, slurp_reloc_table) (bfd *abfd, sec_ptr asect, asymbol **symbols) return FALSE; } - if (reloc_size == 0) - return TRUE; /* Nothing to be done. */ - - if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0) - return FALSE; - each_size = obj_reloc_entry_size (abfd); - count = reloc_size / each_size; if (count == 0) return TRUE; /* Nothing to be done. */ - amt = count * sizeof (arelent); - reloc_cache = (arelent *) bfd_zmalloc (amt); - if (reloc_cache == NULL) + if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0) return FALSE; relocs = bfd_malloc (reloc_size); if (relocs == NULL) + return FALSE; + + if (bfd_bread (relocs, reloc_size, abfd) != reloc_size) { - free (reloc_cache); + free (relocs); return FALSE; } - if (bfd_bread (relocs, reloc_size, abfd) != reloc_size) + amt = count * sizeof (arelent); + reloc_cache = (arelent *) bfd_zmalloc (amt); + if (reloc_cache == NULL) { free (relocs); - free (reloc_cache); return FALSE; } diff --git a/bfd/archive.c b/bfd/archive.c index 67d1c9e153..91127d7e6b 100644 --- a/bfd/archive.c +++ b/bfd/archive.c @@ -2193,11 +2193,7 @@ _bfd_write_archive_contents (bfd *arch) amt = remaining; errno = 0; if (bfd_bread (buffer, amt, current) != amt) - { - if (bfd_get_error () != bfd_error_system_call) - bfd_set_error (bfd_error_file_truncated); - goto input_err; - } + goto input_err; if (bfd_bwrite (buffer, amt, arch) != amt) return FALSE; remaining -= amt; diff --git a/bfd/archive64.c b/bfd/archive64.c index 59e42c699e..c693ff9d0b 100644 --- a/bfd/archive64.c +++ b/bfd/archive64.c @@ -117,7 +117,7 @@ _bfd_archive_64_bit_slurp_armap (bfd *abfd) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_malformed_archive); - goto release_raw_armap; + goto release_symdefs; } stringend = stringbase + stringsize; @@ -142,8 +142,6 @@ _bfd_archive_64_bit_slurp_armap (bfd *abfd) return TRUE; -release_raw_armap: - bfd_release (abfd, raw_armap); release_symdefs: bfd_release (abfd, ardata->symdefs); return FALSE; diff --git a/bfd/ecoff.c b/bfd/ecoff.c index 15c18aca76..1d9e385b2b 100644 --- a/bfd/ecoff.c +++ b/bfd/ecoff.c @@ -1623,20 +1623,25 @@ ecoff_slurp_reloc_table (bfd *abfd, if (! _bfd_ecoff_slurp_symbol_table (abfd)) return FALSE; - amt = section->reloc_count; - amt *= sizeof (arelent); - internal_relocs = (arelent *) bfd_alloc (abfd, amt); - external_reloc_size = backend->external_reloc_size; amt = external_reloc_size * section->reloc_count; external_relocs = (char *) bfd_alloc (abfd, amt); - if (internal_relocs == NULL || external_relocs == NULL) + if (external_relocs == NULL) return FALSE; if (bfd_seek (abfd, section->rel_filepos, SEEK_SET) != 0) return FALSE; if (bfd_bread (external_relocs, amt, abfd) != amt) return FALSE; + amt = section->reloc_count; + amt *= sizeof (arelent); + internal_relocs = (arelent *) bfd_alloc (abfd, amt); + if (internal_relocs == NULL) + { + bfd_release (abfd, external_relocs); + return FALSE; + } + for (i = 0, rptr = internal_relocs; i < section->reloc_count; i++, rptr++) { struct internal_reloc intern; diff --git a/bfd/elf32-m32c.c b/bfd/elf32-m32c.c index 89bdccacd0..a4dfd8d3d4 100644 --- a/bfd/elf32-m32c.c +++ b/bfd/elf32-m32c.c @@ -1284,7 +1284,7 @@ static bfd_vma m32c_offset_for_reloc (bfd *abfd, Elf_Internal_Rela *rel, Elf_Internal_Shdr *symtab_hdr, - Elf_External_Sym_Shndx *shndx_buf ATTRIBUTE_UNUSED, + bfd_byte *shndx_buf ATTRIBUTE_UNUSED, Elf_Internal_Sym *intsyms) { bfd_vma symval; @@ -1442,7 +1442,7 @@ m32c_elf_relax_section bfd_byte * free_contents = NULL; Elf_Internal_Sym *intsyms = NULL; Elf_Internal_Sym *free_intsyms = NULL; - Elf_External_Sym_Shndx *shndx_buf = NULL; + bfd_byte *shndx_buf = NULL; int machine; if (abfd == elf_hash_table (link_info)->dynobj @@ -1499,13 +1499,13 @@ m32c_elf_relax_section bfd_set_error (bfd_error_file_too_big); goto error_return; } - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); + shndx_buf = bfd_malloc (amt); if (shndx_buf == NULL) goto error_return; if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 || bfd_bread (shndx_buf, amt, abfd) != amt) goto error_return; - shndx_hdr->contents = (bfd_byte *) shndx_buf; + shndx_hdr->contents = shndx_buf; } /* Get a copy of the native relocations. */ diff --git a/bfd/elf32-rl78.c b/bfd/elf32-rl78.c index f4abf0425e..40f8c5881b 100644 --- a/bfd/elf32-rl78.c +++ b/bfd/elf32-rl78.c @@ -1822,7 +1822,7 @@ static bfd_vma rl78_offset_for_reloc (bfd * abfd, Elf_Internal_Rela * rel, Elf_Internal_Shdr * symtab_hdr, - Elf_External_Sym_Shndx * shndx_buf ATTRIBUTE_UNUSED, + bfd_byte * shndx_buf ATTRIBUTE_UNUSED, Elf_Internal_Sym * intsyms, Elf_Internal_Rela ** lrel, bfd * input_bfd, @@ -2068,7 +2068,7 @@ rl78_elf_relax_section bfd_byte * free_contents = NULL; Elf_Internal_Sym * intsyms = NULL; Elf_Internal_Sym * free_intsyms = NULL; - Elf_External_Sym_Shndx * shndx_buf = NULL; + bfd_byte * shndx_buf = NULL; bfd_vma pc; bfd_vma symval ATTRIBUTE_UNUSED = 0; int pcrel ATTRIBUTE_UNUSED = 0; @@ -2129,13 +2129,13 @@ rl78_elf_relax_section bfd_set_error (bfd_error_no_memory); goto error_return; } - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); + shndx_buf = bfd_malloc (amt); if (shndx_buf == NULL) goto error_return; if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 || bfd_bread (shndx_buf, amt, abfd) != amt) goto error_return; - shndx_hdr->contents = (bfd_byte *) shndx_buf; + shndx_hdr->contents = shndx_buf; } /* Get a copy of the native relocations. */ diff --git a/bfd/elf32-rx.c b/bfd/elf32-rx.c index a94aee729c..0a9900ff21 100644 --- a/bfd/elf32-rx.c +++ b/bfd/elf32-rx.c @@ -1738,7 +1738,7 @@ static bfd_vma rx_offset_for_reloc (bfd * abfd, Elf_Internal_Rela * rel, Elf_Internal_Shdr * symtab_hdr, - Elf_External_Sym_Shndx * shndx_buf ATTRIBUTE_UNUSED, + bfd_byte * shndx_buf ATTRIBUTE_UNUSED, Elf_Internal_Sym * intsyms, Elf_Internal_Rela ** lrel, bfd * input_bfd, @@ -2005,7 +2005,7 @@ elf32_rx_relax_section (bfd * abfd, bfd_byte * free_contents = NULL; Elf_Internal_Sym * intsyms = NULL; Elf_Internal_Sym * free_intsyms = NULL; - Elf_External_Sym_Shndx * shndx_buf = NULL; + bfd_byte * shndx_buf = NULL; bfd_vma pc; bfd_vma sec_start; bfd_vma symval = 0; @@ -2066,13 +2066,13 @@ elf32_rx_relax_section (bfd * abfd, bfd_set_error (bfd_error_file_too_big); goto error_return; } - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); + shndx_buf = bfd_malloc (amt); if (shndx_buf == NULL) goto error_return; if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 || bfd_bread (shndx_buf, amt, abfd) != amt) goto error_return; - shndx_hdr->contents = (bfd_byte *) shndx_buf; + shndx_hdr->contents = shndx_buf; } /* Get a copy of the native relocations. */ diff --git a/bfd/mach-o.c b/bfd/mach-o.c index 1cc9d43250..fd9f480245 100644 --- a/bfd/mach-o.c +++ b/bfd/mach-o.c @@ -3997,6 +3997,20 @@ bfd_mach_o_ppc_flavour_string (unsigned int flavour) } } +static unsigned char * +bfd_mach_o_alloc_and_read (bfd *abfd, file_ptr filepos, size_t size) +{ + unsigned char *buf; + + buf = bfd_alloc (abfd, size); + if (buf == NULL) + return NULL; + if (bfd_seek (abfd, filepos, SEEK_SET) != 0 + || bfd_bread (buf, size, abfd) != size) + return NULL; + return buf; +} + static bfd_boolean bfd_mach_o_read_dylinker (bfd *abfd, bfd_mach_o_load_command *command) { @@ -4017,13 +4031,8 @@ bfd_mach_o_read_dylinker (bfd *abfd, bfd_mach_o_load_command *command) cmd->name_offset = nameoff; namelen = command->len - nameoff; nameoff += command->offset; - cmd->name_str = bfd_alloc (abfd, namelen); - if (cmd->name_str == NULL) - return FALSE; - if (bfd_seek (abfd, nameoff, SEEK_SET) != 0 - || bfd_bread (cmd->name_str, namelen, abfd) != namelen) - return FALSE; - return TRUE; + cmd->name_str = (char *) bfd_mach_o_alloc_and_read (abfd, nameoff, namelen); + return cmd->name_str != NULL; } static bfd_boolean @@ -4034,6 +4043,7 @@ bfd_mach_o_read_dylib (bfd *abfd, bfd_mach_o_load_command *command) struct mach_o_dylib_command_external raw; unsigned int nameoff; unsigned int namelen; + file_ptr pos; if (command->len < sizeof (raw) + 8) return FALSE; @@ -4063,13 +4073,9 @@ bfd_mach_o_read_dylib (bfd *abfd, bfd_mach_o_load_command *command) cmd->name_offset = command->offset + nameoff; namelen = command->len - nameoff; - cmd->name_str = bfd_alloc (abfd, namelen); - if (cmd->name_str == NULL) - return FALSE; - if (bfd_seek (abfd, mdata->hdr_offset + cmd->name_offset, SEEK_SET) != 0 - || bfd_bread (cmd->name_str, namelen, abfd) != namelen) - return FALSE; - return TRUE; + pos = mdata->hdr_offset + cmd->name_offset; + cmd->name_str = (char *) bfd_mach_o_alloc_and_read (abfd, pos, namelen); + return cmd->name_str != NULL; } static bfd_boolean @@ -4163,13 +4169,9 @@ bfd_mach_o_read_fvmlib (bfd *abfd, bfd_mach_o_load_command *command) fvm->name_offset = command->offset + nameoff; namelen = command->len - nameoff; - fvm->name_str = bfd_alloc (abfd, namelen); - if (fvm->name_str == NULL) - return FALSE; - if (bfd_seek (abfd, fvm->name_offset, SEEK_SET) != 0 - || bfd_bread (fvm->name_str, namelen, abfd) != namelen) - return FALSE; - return TRUE; + fvm->name_str = (char *) bfd_mach_o_alloc_and_read (abfd, fvm->name_offset, + namelen); + return fvm->name_str != NULL; } static bfd_boolean @@ -4568,27 +4570,9 @@ bfd_mach_o_read_str (bfd *abfd, bfd_mach_o_load_command *command) cmd->stroff = command->offset + off; cmd->str_len = command->len - off; - cmd->str = bfd_alloc (abfd, cmd->str_len); - if (cmd->str == NULL) - return FALSE; - if (bfd_seek (abfd, cmd->stroff, SEEK_SET) != 0 - || bfd_bread ((void *) cmd->str, cmd->str_len, abfd) != cmd->str_len) - return FALSE; - return TRUE; -} - -static unsigned char * -bfd_mach_o_alloc_and_read (bfd *abfd, unsigned int off, unsigned int size) -{ - unsigned char *buf; - - buf = bfd_alloc (abfd, size); - if (buf == NULL) - return NULL; - if (bfd_seek (abfd, off, SEEK_SET) != 0 - || bfd_bread (buf, size, abfd) != size) - return NULL; - return buf; + cmd->str = (char *) bfd_mach_o_alloc_and_read (abfd, cmd->stroff, + cmd->str_len); + return cmd->str != NULL; } static bfd_boolean diff --git a/bfd/peicode.h b/bfd/peicode.h index c1bc81b169..3f772a0785 100644 --- a/bfd/peicode.h +++ b/bfd/peicode.h @@ -1408,7 +1408,7 @@ pe_bfd_object_p (bfd * abfd) struct external_PEI_IMAGE_hdr image_hdr; struct internal_filehdr internal_f; struct internal_aouthdr internal_a; - file_ptr opt_hdr_size; + bfd_size_type opt_hdr_size; file_ptr offset; const bfd_target *result; @@ -1494,12 +1494,14 @@ pe_bfd_object_p (bfd * abfd) if (amt < sizeof (PEAOUTHDR)) amt = sizeof (PEAOUTHDR); - opthdr = bfd_zalloc (abfd, amt); + opthdr = bfd_alloc (abfd, amt); if (opthdr == NULL) return NULL; if (bfd_bread (opthdr, opt_hdr_size, abfd) != (bfd_size_type) opt_hdr_size) return NULL; + if (amt > opt_hdr_size) + memset (opthdr + opt_hdr_size, 0, amt - opt_hdr_size); bfd_set_error (bfd_error_no_error); bfd_coff_swap_aouthdr_in (abfd, opthdr, & internal_a); diff --git a/bfd/som.c b/bfd/som.c index d7d4d8f845..bd685920ba 100644 --- a/bfd/som.c +++ b/bfd/som.c @@ -4659,7 +4659,7 @@ som_slurp_symbol_table (bfd *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; + som_symbol_type *sym, *symbase = NULL; size_t amt; /* Return saved value if it exists. */ @@ -4675,15 +4675,6 @@ som_slurp_symbol_table (bfd *abfd) stringtab = obj_som_stringtab (abfd); - 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. */ if (_bfd_mul_overflow (symbol_count, symsize, &amt)) { @@ -4698,6 +4689,15 @@ som_slurp_symbol_table (bfd *abfd) if (bfd_bread (buf, amt, abfd) != amt) goto error_return; + 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; + /* Iterate over all the symbols and internalize them. */ endbufp = buf + symbol_count; for (bufp = buf, sym = symbase; bufp < endbufp; ++bufp) @@ -4837,6 +4837,8 @@ som_slurp_symbol_table (bfd *abfd) return (TRUE); error_return: + if (symbase != NULL) + free (symbase); if (buf != NULL) free (buf); return FALSE; -- Alan Modra Australia Development Lab, IBM