From: Alan Modra Date: Fri, 16 Dec 2022 11:07:29 +0000 (+1030) Subject: bfd_get_relocated_section_contents allow NULL data buffer X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=56ba7527d29060cf6e8693d6e772a9b9b53c1373;p=binutils-gdb.git bfd_get_relocated_section_contents allow NULL data buffer This patch removes the bfd_malloc in default_indirect_link_order and bfd_simple_get_relocated_section_contents, pushing the allocation down to bfd_get_relocated_section_contents. The idea is to make use of the allocation done with sanity checking in bfd_get_full_section_contents, which is called by bfd_generic_get_relocated_section_contents. Doing this exposed a bug in bfd_get_full_section_contents. With relaxation it is possible that an input section rawsize is different to the section size. In that case we want to use the larger of rawsize (the on-disk size for input sections) and size. * reloc.c (bfd_generic_get_relocated_section_contents), * reloc16.c (bfd_coff_reloc16_get_relocated_section_contents), * coff-alpha.c (alpha_ecoff_get_relocated_section_contents), * coff-sh.c (sh_coff_get_relocated_section_contents), * elf-m10200.c (mn10200_elf_get_relocated_section_contents), * elf-m10300.c (mn10300_elf_get_relocated_section_contents), * elf32-avr.c (elf32_avr_get_relocated_section_contents), * elf32-cr16.c (elf32_cr16_get_relocated_section_contents), * elf32-crx.c (elf32_crx_get_relocated_section_contents), * elf32-h8300.c (elf32_h8_get_relocated_section_contents), * elf32-nds32.c (nds32_elf_get_relocated_section_contents), * elf32-sh.c (sh_elf_get_relocated_section_contents), * elfxx-mips.c (_bfd_elf_mips_get_relocated_section_contents): Handle NULL data buffer. * bfd.c (bfd_get_section_alloc_size): New function. * bfd-in2.h: Regenerate. * compress.c (bfd_get_full_section_contents): Correct section malloc size. * linker.c (default_indirect_link_order): Don't malloc memory here before calling bfd_get_relocated_section_contents. * simple.c (bfd_simple_get_relocated_section_contents): Likewise. --- diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 297ce125168..f4d531f5bf8 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -6962,6 +6962,14 @@ bfd_get_section_limit (const bfd *abfd, const asection *sec) / bfd_octets_per_byte (abfd, sec)); } +static inline bfd_size_type +bfd_get_section_alloc_size (const bfd *abfd, const asection *sec) +{ + if (abfd->direction != write_direction && sec->rawsize > sec->size) + return sec->rawsize; + return sec->size; +} + /* Functions to handle insertion and deletion of a bfd's sections. These only handle the list pointers, ie. do not adjust section_count, target_index etc. */ diff --git a/bfd/bfd.c b/bfd/bfd.c index 12cb4bca0ec..97ce2b10450 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -518,6 +518,14 @@ CODE_FRAGMENT . / bfd_octets_per_byte (abfd, sec)); .} . +.static inline bfd_size_type +.bfd_get_section_alloc_size (const bfd *abfd, const asection *sec) +.{ +. if (abfd->direction != write_direction && sec->rawsize > sec->size) +. return sec->rawsize; +. return sec->size; +.} +. .{* Functions to handle insertion and deletion of a bfd's sections. These . only handle the list pointers, ie. do not adjust section_count, . target_index etc. *} diff --git a/bfd/coff-alpha.c b/bfd/coff-alpha.c index ea217f77ace..2ac47754aa1 100644 --- a/bfd/coff-alpha.c +++ b/bfd/coff-alpha.c @@ -745,6 +745,7 @@ alpha_ecoff_get_relocated_section_contents (bfd *abfd, if (reloc_size < 0) return NULL; + bfd_byte *orig_data = data; if (!bfd_get_full_section_contents (input_bfd, input_section, &data)) return NULL; @@ -756,7 +757,7 @@ alpha_ecoff_get_relocated_section_contents (bfd *abfd, reloc_vector = (arelent **) bfd_malloc (reloc_size); if (reloc_vector == NULL) - return NULL; + goto error_return; reloc_count = bfd_canonicalize_reloc (input_bfd, input_section, reloc_vector, symbols); @@ -1138,6 +1139,8 @@ alpha_ecoff_get_relocated_section_contents (bfd *abfd, error_return: free (reloc_vector); + if (orig_data == NULL) + free (data); return NULL; } diff --git a/bfd/coff-sh.c b/bfd/coff-sh.c index d030c475539..c0f6fb42f6d 100644 --- a/bfd/coff-sh.c +++ b/bfd/coff-sh.c @@ -2922,6 +2922,13 @@ sh_coff_get_relocated_section_contents (bfd *output_bfd, relocatable, symbols); + bfd_byte *orig_data = data; + if (data == NULL) + { + data = bfd_malloc (input_section->size); + if (data == NULL) + return NULL; + } memcpy (data, coff_section_data (input_bfd, input_section)->contents, (size_t) input_section->size); @@ -2997,6 +3004,8 @@ sh_coff_get_relocated_section_contents (bfd *output_bfd, free (internal_relocs); free (internal_syms); free (sections); + if (orig_data == NULL) + free (data); return NULL; } diff --git a/bfd/compress.c b/bfd/compress.c index 6a30af5f8e6..86422ba01f4 100644 --- a/bfd/compress.c +++ b/bfd/compress.c @@ -720,7 +720,8 @@ DESCRIPTION bool bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr) { - bfd_size_type sz = bfd_get_section_limit_octets (abfd, sec); + bfd_size_type readsz = bfd_get_section_limit_octets (abfd, sec); + bfd_size_type allocsz = bfd_get_section_alloc_size (abfd, sec); bfd_byte *p = *ptr; bool ret; bfd_size_type save_size; @@ -729,7 +730,7 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr) unsigned int compression_header_size; const unsigned int compress_status = sec->compress_status; - if (sz == 0) + if (allocsz == 0) { *ptr = NULL; return true; @@ -744,7 +745,7 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr) _bfd_error_handler /* xgettext:c-format */ (_("error: %pB(%pA) is too large (%#" PRIx64 " bytes)"), - abfd, sec, (uint64_t) sz); + abfd, sec, (uint64_t) readsz); return false; } @@ -753,7 +754,7 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr) case COMPRESS_SECTION_NONE: if (p == NULL) { - p = (bfd_byte *) bfd_malloc (sz); + p = (bfd_byte *) bfd_malloc (allocsz); if (p == NULL) { /* PR 20801: Provide a more helpful error message. */ @@ -761,12 +762,12 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr) _bfd_error_handler /* xgettext:c-format */ (_("error: %pB(%pA) is too large (%#" PRIx64 " bytes)"), - abfd, sec, (uint64_t) sz); + abfd, sec, (uint64_t) allocsz); return false; } } - if (!bfd_get_section_contents (abfd, sec, p, 0, sz)) + if (!bfd_get_section_contents (abfd, sec, p, 0, readsz)) { if (*ptr != p) free (p); @@ -799,7 +800,7 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr) goto fail_compressed; if (p == NULL) - p = (bfd_byte *) bfd_malloc (sz); + p = (bfd_byte *) bfd_malloc (allocsz); if (p == NULL) goto fail_compressed; @@ -811,7 +812,7 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr) bool is_zstd = compress_status == DECOMPRESS_SECTION_ZSTD; if (!decompress_contents ( is_zstd, compressed_buffer + compression_header_size, - sec->compressed_size - compression_header_size, p, sz)) + sec->compressed_size - compression_header_size, p, readsz)) { bfd_set_error (bfd_error_bad_value); if (p != *ptr) @@ -830,14 +831,14 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr) return false; if (p == NULL) { - p = (bfd_byte *) bfd_malloc (sz); + p = (bfd_byte *) bfd_malloc (allocsz); if (p == NULL) return false; *ptr = p; } /* PR 17512; file: 5bc29788. */ if (p != sec->contents) - memcpy (p, sec->contents, sz); + memcpy (p, sec->contents, readsz); return true; default: diff --git a/bfd/elf-m10200.c b/bfd/elf-m10200.c index cd13ec94c77..948da5d9bc8 100644 --- a/bfd/elf-m10200.c +++ b/bfd/elf-m10200.c @@ -1289,6 +1289,13 @@ mn10200_elf_get_relocated_section_contents (bfd *output_bfd, symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; + bfd_byte *orig_data = data; + if (data == NULL) + { + data = bfd_malloc (input_section->size); + if (data == NULL) + return NULL; + } memcpy (data, elf_section_data (input_section)->this_hdr.contents, (size_t) input_section->size); @@ -1360,6 +1367,8 @@ mn10200_elf_get_relocated_section_contents (bfd *output_bfd, free (isymbuf); if (elf_section_data (input_section)->relocs != internal_relocs) free (internal_relocs); + if (orig_data == NULL) + free (data); return NULL; } diff --git a/bfd/elf-m10300.c b/bfd/elf-m10300.c index 3010b54cbf8..687223d83af 100644 --- a/bfd/elf-m10300.c +++ b/bfd/elf-m10300.c @@ -4431,6 +4431,13 @@ mn10300_elf_get_relocated_section_contents (bfd *output_bfd, symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; + bfd_byte *orig_data = data; + if (data == NULL) + { + data = bfd_malloc (input_section->size); + if (data == NULL) + return NULL; + } memcpy (data, elf_section_data (input_section)->this_hdr.contents, (size_t) input_section->size); @@ -4500,6 +4507,8 @@ mn10300_elf_get_relocated_section_contents (bfd *output_bfd, free (isymbuf); if (internal_relocs != elf_section_data (input_section)->relocs) free (internal_relocs); + if (orig_data == NULL) + free (data); return NULL; } diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c index f8b89930ef5..9ab73528c50 100644 --- a/bfd/elf32-avr.c +++ b/bfd/elf32-avr.c @@ -3216,6 +3216,13 @@ elf32_avr_get_relocated_section_contents (bfd *output_bfd, symbols); symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; + bfd_byte *orig_data = data; + if (data == NULL) + { + data = bfd_malloc (input_section->size); + if (data == NULL) + return NULL; + } memcpy (data, elf_section_data (input_section)->this_hdr.contents, (size_t) input_section->size); @@ -3285,6 +3292,8 @@ elf32_avr_get_relocated_section_contents (bfd *output_bfd, free (isymbuf); if (elf_section_data (input_section)->relocs != internal_relocs) free (internal_relocs); + if (orig_data == NULL) + free (data); return NULL; } diff --git a/bfd/elf32-cr16.c b/bfd/elf32-cr16.c index 88d161eeef7..555736cc2f8 100644 --- a/bfd/elf32-cr16.c +++ b/bfd/elf32-cr16.c @@ -1481,6 +1481,13 @@ elf32_cr16_get_relocated_section_contents (bfd *output_bfd, symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; + bfd_byte *orig_data = data; + if (data == NULL) + { + data = bfd_malloc (input_section->size); + if (data == NULL) + return NULL; + } memcpy (data, elf_section_data (input_section)->this_hdr.contents, (size_t) input_section->size); @@ -1551,6 +1558,8 @@ elf32_cr16_get_relocated_section_contents (bfd *output_bfd, free (isymbuf); if (elf_section_data (input_section)->relocs != internal_relocs) free (internal_relocs); + if (orig_data == NULL) + free (data); return NULL; } diff --git a/bfd/elf32-crx.c b/bfd/elf32-crx.c index cc6962f7b0e..a7406c003ad 100644 --- a/bfd/elf32-crx.c +++ b/bfd/elf32-crx.c @@ -742,6 +742,13 @@ elf32_crx_get_relocated_section_contents (bfd *output_bfd, symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; + bfd_byte *orig_data = data; + if (data == NULL) + { + data = bfd_malloc (input_section->size); + if (data == NULL) + return NULL; + } memcpy (data, elf_section_data (input_section)->this_hdr.contents, (size_t) input_section->size); @@ -813,6 +820,8 @@ elf32_crx_get_relocated_section_contents (bfd *output_bfd, free (isymbuf); if (elf_section_data (input_section)->relocs != internal_relocs) free (internal_relocs); + if (orig_data == NULL) + free (data); return NULL; } diff --git a/bfd/elf32-h8300.c b/bfd/elf32-h8300.c index 6c65520d720..5afb8a7ecac 100644 --- a/bfd/elf32-h8300.c +++ b/bfd/elf32-h8300.c @@ -1623,6 +1623,13 @@ elf32_h8_get_relocated_section_contents (bfd *output_bfd, symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; + bfd_byte *orig_data = data; + if (data == NULL) + { + data = bfd_malloc (input_section->size); + if (data == NULL) + return NULL; + } memcpy (data, elf_section_data (input_section)->this_hdr.contents, (size_t) input_section->size); @@ -1693,6 +1700,8 @@ elf32_h8_get_relocated_section_contents (bfd *output_bfd, free (isymbuf); if (elf_section_data (input_section)->relocs != internal_relocs) free (internal_relocs); + if (orig_data == NULL) + free (data); return NULL; } diff --git a/bfd/elf32-nds32.c b/bfd/elf32-nds32.c index 35e0302ed74..5d22002d1b9 100644 --- a/bfd/elf32-nds32.c +++ b/bfd/elf32-nds32.c @@ -13100,6 +13100,7 @@ nds32_elf_get_relocated_section_contents (bfd *abfd, return NULL; /* Read in the section. */ + bfd_byte *orig_data = data; if (!nds32_get_section_contents (input_bfd, input_section, &data, false)) return NULL; @@ -13108,7 +13109,7 @@ nds32_elf_get_relocated_section_contents (bfd *abfd, reloc_vector = (arelent **) bfd_malloc (reloc_size); if (reloc_vector == NULL) - return NULL; + goto error_return; reloc_count = bfd_canonicalize_reloc (input_bfd, input_section, reloc_vector, symbols); @@ -13202,6 +13203,8 @@ nds32_elf_get_relocated_section_contents (bfd *abfd, error_return: free (reloc_vector); + if (orig_data == NULL) + free (data); return NULL; } diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c index 73b861e18f3..8ababcf5199 100644 --- a/bfd/elf32-sh.c +++ b/bfd/elf32-sh.c @@ -5085,6 +5085,13 @@ sh_elf_get_relocated_section_contents (bfd *output_bfd, symtab_hdr = &elf_symtab_hdr (input_bfd); + bfd_byte *orig_data = data; + if (data == NULL) + { + data = bfd_malloc (input_section->size); + if (data == NULL) + return NULL; + } memcpy (data, elf_section_data (input_section)->this_hdr.contents, (size_t) input_section->size); @@ -5155,6 +5162,8 @@ sh_elf_get_relocated_section_contents (bfd *output_bfd, free (isymbuf); if (elf_section_data (input_section)->relocs != internal_relocs) free (internal_relocs); + if (orig_data == NULL) + free (data); return NULL; } diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index f77ccde8409..f0db5ff193b 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -13301,6 +13301,7 @@ _bfd_elf_mips_get_relocated_section_contents return NULL; /* Read in the section. */ + bfd_byte *orig_data = data; if (!bfd_get_full_section_contents (input_bfd, input_section, &data)) return NULL; @@ -13331,6 +13332,8 @@ _bfd_elf_mips_get_relocated_section_contents else hip = &hi->next; } + if (orig_data == NULL) + free (data); data = NULL; goto out; } diff --git a/bfd/linker.c b/bfd/linker.c index 0c2e3c10a67..df99ce9991a 100644 --- a/bfd/linker.c +++ b/bfd/linker.c @@ -2551,9 +2551,8 @@ default_indirect_link_order (bfd *output_bfd, { asection *input_section; bfd *input_bfd; - bfd_byte *contents = NULL; + bfd_byte *alloced = NULL; bfd_byte *new_contents; - bfd_size_type sec_size; file_ptr loc; BFD_ASSERT ((output_section->flags & SEC_HAS_CONTENTS) != 0); @@ -2654,16 +2653,11 @@ default_indirect_link_order (bfd *output_bfd, else { /* Get and relocate the section contents. */ - sec_size = (input_section->rawsize > input_section->size - ? input_section->rawsize - : input_section->size); - contents = (bfd_byte *) bfd_malloc (sec_size); - if (contents == NULL && sec_size != 0) - goto error_return; new_contents = (bfd_get_relocated_section_contents - (output_bfd, info, link_order, contents, + (output_bfd, info, link_order, NULL, bfd_link_relocatable (info), _bfd_generic_link_get_symbols (input_bfd))); + alloced = new_contents; if (!new_contents) goto error_return; } @@ -2675,11 +2669,11 @@ default_indirect_link_order (bfd *output_bfd, new_contents, loc, input_section->size)) goto error_return; - free (contents); + free (alloced); return true; error_return: - free (contents); + free (alloced); return false; } diff --git a/bfd/reloc.c b/bfd/reloc.c index 6446acc7a30..3b5520f7d25 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -8532,6 +8532,7 @@ bfd_generic_get_relocated_section_contents (bfd *abfd, return NULL; /* Read in the section. */ + bfd_byte *orig_data = data; if (!bfd_get_full_section_contents (input_bfd, input_section, &data)) return NULL; @@ -8543,7 +8544,7 @@ bfd_generic_get_relocated_section_contents (bfd *abfd, reloc_vector = (arelent **) bfd_malloc (reloc_size); if (reloc_vector == NULL) - return NULL; + goto error_return; reloc_count = bfd_canonicalize_reloc (input_bfd, input_section, @@ -8680,6 +8681,8 @@ bfd_generic_get_relocated_section_contents (bfd *abfd, error_return: free (reloc_vector); + if (orig_data == NULL) + free (data); return NULL; } diff --git a/bfd/reloc16.c b/bfd/reloc16.c index 3ae8492a23b..7c8586cf19c 100644 --- a/bfd/reloc16.c +++ b/bfd/reloc16.c @@ -251,11 +251,11 @@ bfd_coff_reloc16_get_relocated_section_contents /* Get enough memory to hold the stuff. */ bfd *input_bfd = link_order->u.indirect.section->owner; asection *input_section = link_order->u.indirect.section; - long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section); + long reloc_size; arelent **reloc_vector; long reloc_count; - bfd_size_type sz; + reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section); if (reloc_size < 0) return NULL; @@ -267,23 +267,26 @@ bfd_coff_reloc16_get_relocated_section_contents symbols); /* Read in the section. */ - sz = input_section->rawsize ? input_section->rawsize : input_section->size; - if (!bfd_get_section_contents (input_bfd, input_section, data, 0, sz)) + bfd_byte *orig_data = data; + if (!bfd_get_full_section_contents (input_bfd, input_section, &data)) return NULL; - reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size); - if (!reloc_vector && reloc_size != 0) + if (data == NULL) return NULL; + if (reloc_size == 0) + return data; + + reloc_vector = (arelent **) bfd_malloc (reloc_size); + if (reloc_vector == NULL) + goto error_return; + reloc_count = bfd_canonicalize_reloc (input_bfd, input_section, reloc_vector, symbols); if (reloc_count < 0) - { - free (reloc_vector); - return NULL; - } + goto error_return; if (reloc_count > 0) { @@ -324,6 +327,12 @@ bfd_coff_reloc16_get_relocated_section_contents } } } - free ((char *) reloc_vector); + free (reloc_vector); return data; + + error_return: + free (reloc_vector); + if (orig_data == NULL) + free (data); + return NULL; } diff --git a/bfd/simple.c b/bfd/simple.c index 67e326d4625..4c8b05832a5 100644 --- a/bfd/simple.c +++ b/bfd/simple.c @@ -209,7 +209,7 @@ bfd_simple_get_relocated_section_contents (bfd *abfd, struct bfd_link_info link_info; struct bfd_link_order link_order; struct bfd_link_callbacks callbacks; - bfd_byte *contents, *data; + bfd_byte *contents; struct saved_offsets saved_offsets; bfd *link_next; @@ -257,28 +257,19 @@ bfd_simple_get_relocated_section_contents (bfd *abfd, link_order.size = sec->size; link_order.u.indirect.section = sec; - data = NULL; contents = NULL; - if (outbuf == NULL) - { - bfd_size_type amt = sec->rawsize > sec->size ? sec->rawsize : sec->size; - data = (bfd_byte *) bfd_malloc (amt); - if (data == NULL) - goto out1; - outbuf = data; - } saved_offsets.section_count = abfd->section_count; saved_offsets.sections = malloc (sizeof (*saved_offsets.sections) * saved_offsets.section_count); if (saved_offsets.sections == NULL) - goto out2; + goto out1; bfd_map_over_sections (abfd, simple_save_output_info, &saved_offsets); if (symbol_table == NULL) { if (!bfd_generic_link_read_symbols (abfd)) - goto out3; + goto out2; symbol_table = _bfd_generic_link_get_symbols (abfd); } @@ -288,12 +279,9 @@ bfd_simple_get_relocated_section_contents (bfd *abfd, outbuf, false, symbol_table); - out3: + out2: bfd_map_over_sections (abfd, simple_restore_output_info, &saved_offsets); free (saved_offsets.sections); - out2: - if (contents == NULL) - free (data); out1: _bfd_generic_link_hash_table_free (abfd); abfd->link.next = link_next;