This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: binutils pr 17531 for 2.25?


Hi Matthias, Hi Tristan,

  Right - the last of the security fixes is now in the 2.25 branch.

Cheers
  Nick

bfd/ChangeLog
2015-03-25  Nick Clifton  <nickc@redhat.com>

	Apply from master:
	2015-02-26  Nick Clifton  <nickc@redhat.com>

	PR binutils/17512
	* elf.c (elf_fake_sections): Handle excessive alignmment powers.
	(assign_file_positions_for_non_load_sections): Replace assertion
	with an error message.
	(rewrite_elf_program_header): Handle excessive segment
	alignments.

	2015-02-13  Alan Modra  <amodra@gmail.com>

	PR binutils/17512
	* elf64-ppc.c (opd_entry_value): Tighten offset check.  Remove
	now redundant assert.

	2015-02-12  Nick Clifton  <nickc@redhat.com>

	PR binutils/17512
	* dwarf2.c (read_1_byte, read_1_signed_byte, read_2_bytes)
	(read_4_bytes, read_8_bytes, read_n_bytes, read_string)
	(read_indirect_string, read_alt_indirect_string)
	(read_alt_indirect_ref, read_address, read_abbrevs)
	(read_attribute_value, read_attribute, decode_line_info)
	(find_abstract_instance_name, read_rangelist)
	(scan_unit_for_symbols, parse_comp_unit)
	(_bfd_dwarf2_find_nearest_line): Harden DWARF reading code.  Pass
	end pointers to reading functions and check for offsets taking
	pointers out of range.  Replace calls to read_*_leb128 with calls
	to safe_read_leb128.

	* elf64-ppc.c (opd_entry_value): Add a check for an overlarge
	offset.

	2015-02-03  Nick Clifton  <nickc@redhat.com>

	PR binutils/17512
	* elf-m10300.c (mn10300_info_to_howto): Fix typo in error message.
	* elf32-arc.c (arc_info_to_howto_rel): Likewise.
	* elf32-avr.c (avr_info_to_howto_rela): Likewise.
	* elf32-cr16.c (elf_cr16_info_to_howto): Likewise.
	* elf32-cr16c.c (elf_cr16c_info_to_howto_rel): Likewise.
	* elf32-cris.c (cris_info_to_howto_rela): Likewise.
	* elf32-crx.c (elf_crx_info_to_howto): Likewise.
	* elf32-d10v.c (d10v_info_to_howto_rel): Likewise.
	* elf32-d30v.c (d30v_info_to_howto_rel): Likewise.
	* elf32-epiphany.c (epiphany_info_to_howto_rela): Likewise.
	* elf32-fr30.c (fr30_info_to_howto_rela): Likewise.
	* elf32-frv.c (frv_info_to_howto_rela): Likewise.
	* elf32-i370.c (i370_elf_info_to_howto): Likewise.
	* elf32-i960.c (elf32_i960_info_to_howto_rel): Likewise.
	* elf32-ip2k.c (ip2k_info_to_howto_rela): Likewise.
	* elf32-iq2000.c (iq2000_info_to_howto_rela): Likewise.
	* elf32-lm32.c (lm32_info_to_howto_rela): Likewise.
	* elf32-m32c.c (m32c_info_to_howto_rela): Likewise.
	* elf32-m32r.c (m32r_info_to_howto_rel): Likewise.
	* elf32-m68hc11.c (m68hc11_info_to_howto_rel): Likewise.
	* elf32-m68hc12.c (m68hc11_info_to_howto_rel): Likewise.
	* elf32-mcore.c (mcore_elf_info_to_howto): Likewise.
	* elf32-mep.c (mep_info_to_howto_rela): Likewise.
	* elf32-metag.c (metag_info_to_howto_rela): Likewise.
	* elf32-microblaze.c (microblaze_elf_info_to_howto): Likewise.
	* elf32-moxie.c (moxie_info_to_howto_rela): Likewise.
	* elf32-msp430.c (msp430_info_to_howto_rela): Likewise.
	* elf32-mt.c (mt_info_to_howto_rela): Likewise.
	* elf32-nds32.c (nds32_info_to_howto_rel): Likewise.
	* elf32-or1k.c (or1k_info_to_howto_rela): Likewise.
	* elf32-pj.c (pj_elf_info_to_howto): Likewise.
	* elf32-ppc.c (ppc_elf_info_to_howto): Likewise.
	* elf32-rl78.c (rl78_info_to_howto_rela): Likewise.
	* elf32-rx.c (rx_info_to_howto_rela): Likewise.
	* elf32-sh.c (sh_elf_info_to_howto): Likewise.
	* elf32-spu.c (spu_elf_info_to_howto): Likewise.
	* elf32-v850.c (v850_elf_perform_relocation): Likewise.
	* elf32-vax.c (rtype_to_howto): Likewise.
	* elf32-visium.c (visium_info_to_howto_rela): Likewise.
	* elf32-xgate.c (xgate_info_to_howto_rel): Likewise.
	* elf32-xtensa.c (elf_xtensa_info_to_howto_rela): Likewise.
	* elf64-alpha.c (elf64_alpha_info_to_howto): Likewise.
	* elf64-mmix.c (mmix_info_to_howto_rela): Likewise.

	2015-01-27  Nick Clifton  <nickc@redhat.com>

	PR binutils/17512
	* dwarf2.c (concat_filename): Check for an empty directory table.
	(scan_unit_for_symbols): Check for reading off the end of the
	unit.
	(parse_comp_unit): Check for a DW_AT_comp_dir attribute with a
	non-string form.

	2015-01-15  Nick Clifton  <nickc@redhat.com>

	PR binutils/17512
	* elf-m10300.c (mn10300_info_to_howto): Replace assertion with an
	error message.  Never return an invalid howto pointer.
	* elf32-cr16.c (cr16_info_to_howto): Likewise.
	* elf32-crx.c (elf_crx_info_to_howto): Likewise.
	* elf32-i370.c (i370_elf_info_to_howto): Likewise.
	* elf32-mcore.c (mcore_elf_info_to_howto): Likewise.
	* elf32-microblaze.c (microblaze_elf_info_to_howto): Likewise.
	* elf32-mips.c (mips_elf32_rtype_to_howto): Likewise.
	* elf32-pj.c (pj_elf_info_to_howto): Likewise.
	* elf32-ppc.c (ppc_elf_info_to_howto): Likewise.
	* elf32-spu.c (spu_elf_info_to_howto): Likewise.
	* elf32-v850.c (v850_elf_info_to_howto_rela): Likewise.
	* elf32-vax.c (rtype_to_howto): Likewise.
	* elf64-alpha.c (elf64_alpha_info_to_howto): Likewise.
	* elf64-mips.c (mips_elf64_rtype_to_howto): Likewise.
	* elfn32-mips.c (sh_elf_info_to_howto): Likewise.
	* elf32-sh.c (sh_elf_info_to_howto): Likewise.
	(sh_elf_reloc): Check that the reloc is in range.
	* reloc.c (bfd_perform_relocation): Check that the section is big
	enough for the entire reloc.
	(bfd_generic_get_relocated_section_contents): Report unexpected
	return values from perform_reloc.

	2015-01-08  Nick Clifton  <nickc@redhat.com>

	PR binutils/17512
	* elf.c (_bfd_elf_map_sections_to_segments): Enforce a minimum
	maxpagesize of 1.

	2015-01-06  H.J. Lu  <hongjiu.lu@intel.com>

	PR binutils/17512
	* elf32-i386.c (elf_i386_get_plt_sym_val): Skip unknown relocation.
	* elf64-x86-64.c (elf_x86_64_get_plt_sym_val): Likewise.

	2014-12-22  Nick Clifton  <nickc@redhat.com>

	PR binutils/17512
	* elf32-arc.c (arc_info_to_howto_rel): Replace BFD_ASSERT with
	error message.
	* elf32-avr.c (avr_info_to_howto_rela): Likewise.
	* elf32-cr16c.c (elf_cr16c_info_to_howto_rel): Likewise.
	* elf32-cris.c (cris_info_to_howto_rela): Likewise.
	* elf32-d10v.c (d10v_info_to_howto_rel): Likewise.
	* elf32-d30v.c (d30v_info_to_howto_rel): Likewise.
	* elf32-dlx.c (dlx_rtype_to_howto): Likewise.
	* elf32-epiphany.c (epiphany_info_to_howto_rela): Likewise.
	* elf32-fr30.c (fr30_info_to_howto_rela): Likewise.
	* elf32-frv.c (frv_info_to_howto_rela): Likewise.
	* elf32-i960.c (elf32_i960_info_to_howto_rel): Likewise.
	* elf32-ip2k.c (ip2k_info_to_howto_rela): Likewise.
	* elf32-iq2000.c (iq2000_info_to_howto_rela): Likewise.
	* elf32-lm32.c (lm32_info_to_howto_rela): Likewise.
	* elf32-m32c.c (m32c_info_to_howto_rela): Likewise.
	* elf32-m32r.c (m32r_info_to_howto_rel): Likewise.
	* elf32-m68hc11.c (m68hc11_info_to_howto_rel): Likewise.
	* elf32-m68hc12.c (m68hc11_info_to_howto_rel): Likewise.
	* elf32-mep.c (mep_info_to_howto_rela): Likewise.
	* elf32-metag.c (metag_info_to_howto_rela): Likewise.
	* elf32-moxie.c (moxie_info_to_howto_rela): Likewise.
	* elf32-msp430.c (msp430_info_to_howto_rela): Likewise.
	* elf32-mt.c (mt_info_to_howto_rela): Likewise.
	* elf32-nds32.c (nds32_info_to_howto_rel): Likewise.
	* elf32-or1k.c (or1k_info_to_howto_rela): Likewise.
	* elf32-rl78.c (rl78_info_to_howto_rela): Likewise.
	* elf32-rx.c (rx_info_to_howto_rela): Likewise.
	* elf32-v850.c (v850_elf_info_to_howto_rel): Likewise.
	* elf32-xgate.c (xgate_info_to_howto_rel): Likewise.
	* elf32-xtensa.c (elf_xtensa_info_to_howto_rela): Likewise.
	* elf64-mmix.c (mmix_info_to_howto_rela): Likewise.
	* elf64-x86-64.c (elf_x86_64_reloc_type_lookup): Likewise.
	* elfnn-aarch64.c (elfNN_aarch64_bfd_reloc_from_type): Likewise.
	* elf64-sparc.c (elf64_sparc_slurp_one_reloc_table): Add range
	checking of reloc symbol index.

	2014-12-09  Nick Clifton  <nickc@redhat.com>

	PR binutils/17512
	* elf-attrs.c (_bfd_elf_parse_attributes): Use safe_read_leb128.
	Check for an over-long subsection length.
	* elf.c (elf_parse_notes): Check that the namedata is long enough
	for the string comparison that is about to be performed.
	(elf_read_notes): Zero-terminate the note buffer.

	2014-12-01  Nick Clifton  <nickc@redhat.com>

	PR binutils/17512
	* elf-attrs.c (_bfd_elf_parse_attributes): Check for an empty
	header.  Add range checks to avoid running off the end of the
	section.
	* elf.c (bfd_elf_get_str_section): Seek before allocating so that
	if the seek fails, no memory is allocated.
	(bfd_elf_string_from_elf_section): Do not allocate a string from a
	non string section.  It only leads to trouble later on.
	(_bfd_elf_print_private_bfd_data): Check for there being too
	little external dynamic data.
	(bfd_section_from_shdr): Replace assertion with a failure mode.
	(bfd_section_from_shdr): When walking a loaded group section use
	the internal structure size, not the external size.  Check for the
	group section being empty.
	* elf32-i386.c (elf_i386_rtype_to_howto): Replace assertion with a
	failure mode.
	* elfcode.h (elf_slurp_reloc_table): Likewise.

	2014-11-27  Nick Clifton  <nickc@redhat.com>

	PR binutils/17512
	* elf.c (_bfd_elf_print_private_bfd_data): Fix the range check
	scanning the external dynamic entries.

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 9363c1a..c54b53a 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -4,6 +4,211 @@
 	2015-02-26  Nick Clifton  <nickc@redhat.com>
 
 	PR binutils/17512
+	* elf.c (elf_fake_sections): Handle excessive alignmment powers.
+	(assign_file_positions_for_non_load_sections): Replace assertion
+	with an error message.
+	(rewrite_elf_program_header): Handle excessive segment
+	alignments.
+
+	2015-02-13  Alan Modra  <amodra@gmail.com>
+
+	PR binutils/17512
+	* elf64-ppc.c (opd_entry_value): Tighten offset check.  Remove
+	now redundant assert.
+
+	2015-02-12  Nick Clifton  <nickc@redhat.com>
+
+	PR binutils/17512
+	* dwarf2.c (read_1_byte, read_1_signed_byte, read_2_bytes)
+	(read_4_bytes, read_8_bytes, read_n_bytes, read_string)
+	(read_indirect_string, read_alt_indirect_string)
+	(read_alt_indirect_ref, read_address, read_abbrevs)
+	(read_attribute_value, read_attribute, decode_line_info)
+	(find_abstract_instance_name, read_rangelist)
+	(scan_unit_for_symbols, parse_comp_unit)
+	(_bfd_dwarf2_find_nearest_line): Harden DWARF reading code.  Pass
+	end pointers to reading functions and check for offsets taking
+	pointers out of range.  Replace calls to read_*_leb128 with calls
+	to safe_read_leb128.
+
+	* elf64-ppc.c (opd_entry_value): Add a check for an overlarge
+	offset.
+
+	2015-02-03  Nick Clifton  <nickc@redhat.com>
+
+	PR binutils/17512
+	* elf-m10300.c (mn10300_info_to_howto): Fix typo in error message.
+	* elf32-arc.c (arc_info_to_howto_rel): Likewise.
+	* elf32-avr.c (avr_info_to_howto_rela): Likewise.
+	* elf32-cr16.c (elf_cr16_info_to_howto): Likewise.
+	* elf32-cr16c.c (elf_cr16c_info_to_howto_rel): Likewise.
+	* elf32-cris.c (cris_info_to_howto_rela): Likewise.
+	* elf32-crx.c (elf_crx_info_to_howto): Likewise.
+	* elf32-d10v.c (d10v_info_to_howto_rel): Likewise.
+	* elf32-d30v.c (d30v_info_to_howto_rel): Likewise.
+	* elf32-epiphany.c (epiphany_info_to_howto_rela): Likewise.
+	* elf32-fr30.c (fr30_info_to_howto_rela): Likewise.
+	* elf32-frv.c (frv_info_to_howto_rela): Likewise.
+	* elf32-i370.c (i370_elf_info_to_howto): Likewise.
+	* elf32-i960.c (elf32_i960_info_to_howto_rel): Likewise.
+	* elf32-ip2k.c (ip2k_info_to_howto_rela): Likewise.
+	* elf32-iq2000.c (iq2000_info_to_howto_rela): Likewise.
+	* elf32-lm32.c (lm32_info_to_howto_rela): Likewise.
+	* elf32-m32c.c (m32c_info_to_howto_rela): Likewise.
+	* elf32-m32r.c (m32r_info_to_howto_rel): Likewise.
+	* elf32-m68hc11.c (m68hc11_info_to_howto_rel): Likewise.
+	* elf32-m68hc12.c (m68hc11_info_to_howto_rel): Likewise.
+	* elf32-mcore.c (mcore_elf_info_to_howto): Likewise.
+	* elf32-mep.c (mep_info_to_howto_rela): Likewise.
+	* elf32-metag.c (metag_info_to_howto_rela): Likewise.
+	* elf32-microblaze.c (microblaze_elf_info_to_howto): Likewise.
+	* elf32-moxie.c (moxie_info_to_howto_rela): Likewise.
+	* elf32-msp430.c (msp430_info_to_howto_rela): Likewise.
+	* elf32-mt.c (mt_info_to_howto_rela): Likewise.
+	* elf32-nds32.c (nds32_info_to_howto_rel): Likewise.
+	* elf32-or1k.c (or1k_info_to_howto_rela): Likewise.
+	* elf32-pj.c (pj_elf_info_to_howto): Likewise.
+	* elf32-ppc.c (ppc_elf_info_to_howto): Likewise.
+	* elf32-rl78.c (rl78_info_to_howto_rela): Likewise.
+	* elf32-rx.c (rx_info_to_howto_rela): Likewise.
+	* elf32-sh.c (sh_elf_info_to_howto): Likewise.
+	* elf32-spu.c (spu_elf_info_to_howto): Likewise.
+	* elf32-v850.c (v850_elf_perform_relocation): Likewise.
+	* elf32-vax.c (rtype_to_howto): Likewise.
+	* elf32-visium.c (visium_info_to_howto_rela): Likewise.
+	* elf32-xgate.c (xgate_info_to_howto_rel): Likewise.
+	* elf32-xtensa.c (elf_xtensa_info_to_howto_rela): Likewise.
+	* elf64-alpha.c (elf64_alpha_info_to_howto): Likewise.
+	* elf64-mmix.c (mmix_info_to_howto_rela): Likewise.
+
+	2015-01-27  Nick Clifton  <nickc@redhat.com>
+
+	PR binutils/17512
+	* dwarf2.c (concat_filename): Check for an empty directory table.
+	(scan_unit_for_symbols): Check for reading off the end of the
+	unit.
+	(parse_comp_unit): Check for a DW_AT_comp_dir attribute with a
+	non-string form.
+
+	2015-01-15  Nick Clifton  <nickc@redhat.com>
+
+	PR binutils/17512
+	* elf-m10300.c (mn10300_info_to_howto): Replace assertion with an
+	error message.  Never return an invalid howto pointer.
+	* elf32-cr16.c (cr16_info_to_howto): Likewise.
+	* elf32-crx.c (elf_crx_info_to_howto): Likewise.
+	* elf32-i370.c (i370_elf_info_to_howto): Likewise.
+	* elf32-mcore.c (mcore_elf_info_to_howto): Likewise.
+	* elf32-microblaze.c (microblaze_elf_info_to_howto): Likewise.
+	* elf32-mips.c (mips_elf32_rtype_to_howto): Likewise.
+	* elf32-pj.c (pj_elf_info_to_howto): Likewise.
+	* elf32-ppc.c (ppc_elf_info_to_howto): Likewise.
+	* elf32-spu.c (spu_elf_info_to_howto): Likewise.
+	* elf32-v850.c (v850_elf_info_to_howto_rela): Likewise.
+	* elf32-vax.c (rtype_to_howto): Likewise.
+	* elf64-alpha.c (elf64_alpha_info_to_howto): Likewise.
+	* elf64-mips.c (mips_elf64_rtype_to_howto): Likewise.
+	* elfn32-mips.c (sh_elf_info_to_howto): Likewise.
+	* elf32-sh.c (sh_elf_info_to_howto): Likewise.
+	(sh_elf_reloc): Check that the reloc is in range.
+	* reloc.c (bfd_perform_relocation): Check that the section is big
+	enough for the entire reloc.
+	(bfd_generic_get_relocated_section_contents): Report unexpected
+	return values from perform_reloc.
+
+	2015-01-08  Nick Clifton  <nickc@redhat.com>
+
+	PR binutils/17512
+	* elf.c (_bfd_elf_map_sections_to_segments): Enforce a minimum
+	maxpagesize of 1.
+
+	2015-01-06  H.J. Lu  <hongjiu.lu@intel.com>
+
+	PR binutils/17512
+	* elf32-i386.c (elf_i386_get_plt_sym_val): Skip unknown relocation.
+	* elf64-x86-64.c (elf_x86_64_get_plt_sym_val): Likewise.
+
+	2014-12-22  Nick Clifton  <nickc@redhat.com>
+
+	PR binutils/17512
+	* elf32-arc.c (arc_info_to_howto_rel): Replace BFD_ASSERT with
+	error message.
+	* elf32-avr.c (avr_info_to_howto_rela): Likewise.
+	* elf32-cr16c.c (elf_cr16c_info_to_howto_rel): Likewise.
+	* elf32-cris.c (cris_info_to_howto_rela): Likewise.
+	* elf32-d10v.c (d10v_info_to_howto_rel): Likewise.
+	* elf32-d30v.c (d30v_info_to_howto_rel): Likewise.
+	* elf32-dlx.c (dlx_rtype_to_howto): Likewise.
+	* elf32-epiphany.c (epiphany_info_to_howto_rela): Likewise.
+	* elf32-fr30.c (fr30_info_to_howto_rela): Likewise.
+	* elf32-frv.c (frv_info_to_howto_rela): Likewise.
+	* elf32-i960.c (elf32_i960_info_to_howto_rel): Likewise.
+	* elf32-ip2k.c (ip2k_info_to_howto_rela): Likewise.
+	* elf32-iq2000.c (iq2000_info_to_howto_rela): Likewise.
+	* elf32-lm32.c (lm32_info_to_howto_rela): Likewise.
+	* elf32-m32c.c (m32c_info_to_howto_rela): Likewise.
+	* elf32-m32r.c (m32r_info_to_howto_rel): Likewise.
+	* elf32-m68hc11.c (m68hc11_info_to_howto_rel): Likewise.
+	* elf32-m68hc12.c (m68hc11_info_to_howto_rel): Likewise.
+	* elf32-mep.c (mep_info_to_howto_rela): Likewise.
+	* elf32-metag.c (metag_info_to_howto_rela): Likewise.
+	* elf32-moxie.c (moxie_info_to_howto_rela): Likewise.
+	* elf32-msp430.c (msp430_info_to_howto_rela): Likewise.
+	* elf32-mt.c (mt_info_to_howto_rela): Likewise.
+	* elf32-nds32.c (nds32_info_to_howto_rel): Likewise.
+	* elf32-or1k.c (or1k_info_to_howto_rela): Likewise.
+	* elf32-rl78.c (rl78_info_to_howto_rela): Likewise.
+	* elf32-rx.c (rx_info_to_howto_rela): Likewise.
+	* elf32-v850.c (v850_elf_info_to_howto_rel): Likewise.
+	* elf32-xgate.c (xgate_info_to_howto_rel): Likewise.
+	* elf32-xtensa.c (elf_xtensa_info_to_howto_rela): Likewise.
+	* elf64-mmix.c (mmix_info_to_howto_rela): Likewise.
+	* elf64-x86-64.c (elf_x86_64_reloc_type_lookup): Likewise.
+	* elfnn-aarch64.c (elfNN_aarch64_bfd_reloc_from_type): Likewise.
+	* elf64-sparc.c (elf64_sparc_slurp_one_reloc_table): Add range
+	checking of reloc symbol index.
+
+	2014-12-09  Nick Clifton  <nickc@redhat.com>
+
+	PR binutils/17512
+	* elf-attrs.c (_bfd_elf_parse_attributes): Use safe_read_leb128.
+	Check for an over-long subsection length.
+	* elf.c (elf_parse_notes): Check that the namedata is long enough
+	for the string comparison that is about to be performed.
+	(elf_read_notes): Zero-terminate the note buffer.
+
+	2014-12-01  Nick Clifton  <nickc@redhat.com>
+
+	PR binutils/17512
+	* elf-attrs.c (_bfd_elf_parse_attributes): Check for an empty
+	header.  Add range checks to avoid running off the end of the
+	section.
+	* elf.c (bfd_elf_get_str_section): Seek before allocating so that
+	if the seek fails, no memory is allocated.
+	(bfd_elf_string_from_elf_section): Do not allocate a string from a
+	non string section.  It only leads to trouble later on.
+	(_bfd_elf_print_private_bfd_data): Check for there being too
+	little external dynamic data.
+	(bfd_section_from_shdr): Replace assertion with a failure mode.
+	(bfd_section_from_shdr): When walking a loaded group section use
+	the internal structure size, not the external size.  Check for the
+	group section being empty.
+	* elf32-i386.c (elf_i386_rtype_to_howto): Replace assertion with a
+	failure mode.
+	* elfcode.h (elf_slurp_reloc_table): Likewise.
+
+	2014-11-27  Nick Clifton  <nickc@redhat.com>
+
+	PR binutils/17512
+	* elf.c (_bfd_elf_print_private_bfd_data): Fix the range check
+	scanning the external dynamic entries.
+
+2015-03-25  Nick Clifton  <nickc@redhat.com>
+
+	Apply from master:
+	2015-02-26  Nick Clifton  <nickc@redhat.com>
+
+	PR binutils/17512
 	* mach-o.c (bfd_mach_o_read_section_32): Likewise.
 	(bfd_mach_o_read_section_64): Likewise.
 
diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index 915d3e2..2ba36fd 100644
--- a/bfd/dwarf2.c
+++ b/bfd/dwarf2.c
@@ -556,83 +556,124 @@ read_section (bfd *           abfd,
   return TRUE;
 }
 
-/* VERBATIM
-   The following function up to the END VERBATIM mark are
-   copied directly from dwarf2read.c.  */
-
 /* Read dwarf information from a buffer.  */
 
 static unsigned int
-read_1_byte (bfd *abfd ATTRIBUTE_UNUSED, bfd_byte *buf)
+read_1_byte (bfd *abfd ATTRIBUTE_UNUSED, bfd_byte *buf, bfd_byte *end)
 {
+  if (buf + 1 > end)
+    return 0;
   return bfd_get_8 (abfd, buf);
 }
 
 static int
-read_1_signed_byte (bfd *abfd ATTRIBUTE_UNUSED, bfd_byte *buf)
+read_1_signed_byte (bfd *abfd ATTRIBUTE_UNUSED, bfd_byte *buf, bfd_byte *end)
 {
+  if (buf + 1 > end)
+    return 0;
   return bfd_get_signed_8 (abfd, buf);
 }
 
 static unsigned int
-read_2_bytes (bfd *abfd, bfd_byte *buf)
+read_2_bytes (bfd *abfd, bfd_byte *buf, bfd_byte *end)
 {
+  if (buf + 2 > end)
+    return 0;
   return bfd_get_16 (abfd, buf);
 }
 
 static unsigned int
-read_4_bytes (bfd *abfd, bfd_byte *buf)
+read_4_bytes (bfd *abfd, bfd_byte *buf, bfd_byte *end)
 {
+  if (buf + 4 > end)
+    return 0;
   return bfd_get_32 (abfd, buf);
 }
 
 static bfd_uint64_t
-read_8_bytes (bfd *abfd, bfd_byte *buf)
+read_8_bytes (bfd *abfd, bfd_byte *buf, bfd_byte *end)
 {
+  if (buf + 8 > end)
+    return 0;
   return bfd_get_64 (abfd, buf);
 }
 
 static bfd_byte *
 read_n_bytes (bfd *abfd ATTRIBUTE_UNUSED,
 	      bfd_byte *buf,
+	      bfd_byte *end,
 	      unsigned int size ATTRIBUTE_UNUSED)
 {
+  if (buf + size > end)
+    return NULL;
   return buf;
 }
 
+/* Scans a NUL terminated string starting at BUF, returning a pointer to it.
+   Returns the number of characters in the string, *including* the NUL byte,
+   in BYTES_READ_PTR.  This value is set even if the function fails.  Bytes
+   at or beyond BUF_END will not be read.  Returns NULL if there was a
+   problem, or if the string is empty.  */
+
 static char *
-read_string (bfd *abfd ATTRIBUTE_UNUSED,
-	     bfd_byte *buf,
-	     unsigned int *bytes_read_ptr)
+read_string (bfd *          abfd ATTRIBUTE_UNUSED,
+	     bfd_byte *     buf,
+	     bfd_byte *     buf_end,
+	     unsigned int * bytes_read_ptr)
 {
-  /* Return a pointer to the embedded string.  */
-  char *str = (char *) buf;
+  bfd_byte *str = buf;
+
+  if (buf >= buf_end)
+    {
+      * bytes_read_ptr = 0;
+      return NULL;
+    }
 
   if (*str == '\0')
     {
-      *bytes_read_ptr = 1;
+      * bytes_read_ptr = 1;
       return NULL;
     }
 
-  *bytes_read_ptr = strlen (str) + 1;
-  return str;
+  while (buf < buf_end)
+    if (* buf ++ == 0)
+      {
+	* bytes_read_ptr = buf - str;
+	return (char *) str;
+      }
+
+  * bytes_read_ptr = buf - str;
+  return NULL;
 }
 
-/* END VERBATIM */
+/* Reads an offset from BUF and then locates the string at this offset
+   inside the debug string section.  Returns a pointer to the string.
+   Returns the number of bytes read from BUF, *not* the length of the string,
+   in BYTES_READ_PTR.  This value is set even if the function fails.  Bytes
+   at or beyond BUF_END will not be read from BUF.  Returns NULL if there was
+   a problem, or if the string is empty.  Does not check for NUL termination
+   of the string.  */
 
 static char *
 read_indirect_string (struct comp_unit * unit,
 		      bfd_byte *         buf,
+		      bfd_byte *         buf_end,
 		      unsigned int *     bytes_read_ptr)
 {
   bfd_uint64_t offset;
   struct dwarf2_debug *stash = unit->stash;
   char *str;
 
+  if (buf + unit->offset_size > buf_end)
+    {
+      * bytes_read_ptr = 0;
+      return NULL;
+    }
+
   if (unit->offset_size == 4)
-    offset = read_4_bytes (unit->abfd, buf);
+    offset = read_4_bytes (unit->abfd, buf, buf_end);
   else
-    offset = read_8_bytes (unit->abfd, buf);
+    offset = read_8_bytes (unit->abfd, buf, buf_end);
 
   *bytes_read_ptr = unit->offset_size;
 
@@ -641,6 +682,8 @@ read_indirect_string (struct comp_unit * unit,
 		      &stash->dwarf_str_buffer, &stash->dwarf_str_size))
     return NULL;
 
+  if (offset >= stash->dwarf_str_size)
+    return NULL;
   str = (char *) stash->dwarf_str_buffer + offset;
   if (*str == '\0')
     return NULL;
@@ -654,16 +697,23 @@ read_indirect_string (struct comp_unit * unit,
 static char *
 read_alt_indirect_string (struct comp_unit * unit,
 			  bfd_byte *         buf,
+			  bfd_byte *         buf_end,
 			  unsigned int *     bytes_read_ptr)
 {
   bfd_uint64_t offset;
   struct dwarf2_debug *stash = unit->stash;
   char *str;
 
+  if (buf + unit->offset_size > buf_end)
+    {
+      * bytes_read_ptr = 0;
+      return NULL;
+    }
+
   if (unit->offset_size == 4)
-    offset = read_4_bytes (unit->abfd, buf);
+    offset = read_4_bytes (unit->abfd, buf, buf_end);
   else
-    offset = read_8_bytes (unit->abfd, buf);
+    offset = read_8_bytes (unit->abfd, buf, buf_end);
 
   *bytes_read_ptr = unit->offset_size;
 
@@ -687,7 +737,7 @@ read_alt_indirect_string (struct comp_unit * unit,
 	}
       stash->alt_bfd_ptr = debug_bfd;
     }
-  
+
   if (! read_section (unit->stash->alt_bfd_ptr,
 		      stash->debug_sections + debug_str_alt,
 		      NULL, /* FIXME: Do we need to load alternate symbols ?  */
@@ -696,6 +746,8 @@ read_alt_indirect_string (struct comp_unit * unit,
 		      &stash->alt_dwarf_str_size))
     return NULL;
 
+  if (offset >= stash->alt_dwarf_str_size)
+    return NULL;
   str = (char *) stash->alt_dwarf_str_buffer + offset;
   if (*str == '\0')
     return NULL;
@@ -733,7 +785,7 @@ read_alt_indirect_ref (struct comp_unit * unit,
 	}
       stash->alt_bfd_ptr = debug_bfd;
     }
-  
+
   if (! read_section (unit->stash->alt_bfd_ptr,
 		      stash->debug_sections + debug_info_alt,
 		      NULL, /* FIXME: Do we need to load alternate symbols ?  */
@@ -742,17 +794,22 @@ read_alt_indirect_ref (struct comp_unit * unit,
 		      &stash->alt_dwarf_info_size))
     return NULL;
 
+  if (offset >= stash->alt_dwarf_info_size)
+    return NULL;
   return stash->alt_dwarf_info_buffer + offset;
 }
 
 static bfd_uint64_t
-read_address (struct comp_unit *unit, bfd_byte *buf)
+read_address (struct comp_unit *unit, bfd_byte *buf, bfd_byte * buf_end)
 {
   int signed_vma = 0;
 
   if (bfd_get_flavour (unit->abfd) == bfd_target_elf_flavour)
     signed_vma = get_elf_backend_data (unit->abfd)->sign_extend_vma;
 
+  if (buf + unit->addr_size > buf_end)
+    return 0;
+
   if (signed_vma)
     {
       switch (unit->addr_size)
@@ -815,6 +872,7 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
 {
   struct abbrev_info **abbrevs;
   bfd_byte *abbrev_ptr;
+  bfd_byte *abbrev_end;
   struct abbrev_info *cur_abbrev;
   unsigned int abbrev_number, bytes_read, abbrev_name;
   unsigned int abbrev_form, hash_number;
@@ -825,13 +883,17 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
 		      &stash->dwarf_abbrev_buffer, &stash->dwarf_abbrev_size))
     return NULL;
 
+  if (offset >= stash->dwarf_abbrev_size)
+    return NULL;
+
   amt = sizeof (struct abbrev_info*) * ABBREV_HASH_SIZE;
   abbrevs = (struct abbrev_info **) bfd_zalloc (abfd, amt);
   if (abbrevs == NULL)
     return NULL;
 
   abbrev_ptr = stash->dwarf_abbrev_buffer + offset;
-  abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+  abbrev_end = stash->dwarf_abbrev_buffer + stash->dwarf_abbrev_size;
+  abbrev_number = safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
   abbrev_ptr += bytes_read;
 
   /* Loop until we reach an abbrev number of 0.  */
@@ -845,15 +907,15 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
       /* Read in abbrev header.  */
       cur_abbrev->number = abbrev_number;
       cur_abbrev->tag = (enum dwarf_tag)
-	read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+	safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
       abbrev_ptr += bytes_read;
-      cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr);
+      cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr, abbrev_end);
       abbrev_ptr += 1;
 
       /* Now read in declarations.  */
-      abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+      abbrev_name = safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
       abbrev_ptr += bytes_read;
-      abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+      abbrev_form = safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
       abbrev_ptr += bytes_read;
 
       while (abbrev_name)
@@ -888,9 +950,9 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
 	    = (enum dwarf_attribute) abbrev_name;
 	  cur_abbrev->attrs[cur_abbrev->num_attrs++].form
 	    = (enum dwarf_form) abbrev_form;
-	  abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+	  abbrev_name = safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
 	  abbrev_ptr += bytes_read;
-	  abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+	  abbrev_form = safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
 	  abbrev_ptr += bytes_read;
 	}
 
@@ -908,9 +970,9 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
       if ((unsigned int) (abbrev_ptr - stash->dwarf_abbrev_buffer)
 	  >= stash->dwarf_abbrev_size)
 	break;
-      abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+      abbrev_number = safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, FALSE, abbrev_end);
       abbrev_ptr += bytes_read;
-      if (lookup_abbrev (abbrev_number,abbrevs) != NULL)
+      if (lookup_abbrev (abbrev_number, abbrevs) != NULL)
 	break;
     }
 
@@ -925,19 +987,29 @@ is_str_attr (enum dwarf_form form)
   return form == DW_FORM_string || form == DW_FORM_strp || form == DW_FORM_GNU_strp_alt;
 }
 
-/* Read an attribute value described by an attribute form.  */
+/* Read and fill in the value of attribute ATTR as described by FORM.
+   Read data starting from INFO_PTR, but never at or beyond INFO_PTR_END.
+   Returns an updated INFO_PTR taking into account the amount of data read.  */
 
 static bfd_byte *
-read_attribute_value (struct attribute *attr,
-		      unsigned form,
-		      struct comp_unit *unit,
-		      bfd_byte *info_ptr)
+read_attribute_value (struct attribute *  attr,
+		      unsigned            form,
+		      struct comp_unit *  unit,
+		      bfd_byte *          info_ptr,
+		      bfd_byte *          info_ptr_end)
 {
   bfd *abfd = unit->abfd;
   unsigned int bytes_read;
   struct dwarf_block *blk;
   bfd_size_type amt;
 
+  if (info_ptr >= info_ptr_end)
+    {
+      (*_bfd_error_handler) (_("Dwarf Error: Info pointer extends beyond end of attributes"));
+      bfd_set_error (bfd_error_bad_value);
+      return info_ptr;
+    }
+
   attr->form = (enum dwarf_form) form;
 
   switch (form)
@@ -948,23 +1020,23 @@ read_attribute_value (struct attribute *attr,
       if (unit->version == 3 || unit->version == 4)
 	{
 	  if (unit->offset_size == 4)
-	    attr->u.val = read_4_bytes (unit->abfd, info_ptr);
+	    attr->u.val = read_4_bytes (unit->abfd, info_ptr, info_ptr_end);
 	  else
-	    attr->u.val = read_8_bytes (unit->abfd, info_ptr);
+	    attr->u.val = read_8_bytes (unit->abfd, info_ptr, info_ptr_end);
 	  info_ptr += unit->offset_size;
 	  break;
 	}
       /* FALLTHROUGH */
     case DW_FORM_addr:
-      attr->u.val = read_address (unit, info_ptr);
+      attr->u.val = read_address (unit, info_ptr, info_ptr_end);
       info_ptr += unit->addr_size;
       break;
     case DW_FORM_GNU_ref_alt:
     case DW_FORM_sec_offset:
       if (unit->offset_size == 4)
-	attr->u.val = read_4_bytes (unit->abfd, info_ptr);
+	attr->u.val = read_4_bytes (unit->abfd, info_ptr, info_ptr_end);
       else
-	attr->u.val = read_8_bytes (unit->abfd, info_ptr);
+	attr->u.val = read_8_bytes (unit->abfd, info_ptr, info_ptr_end);
       info_ptr += unit->offset_size;
       break;
     case DW_FORM_block2:
@@ -972,9 +1044,9 @@ read_attribute_value (struct attribute *attr,
       blk = (struct dwarf_block *) bfd_alloc (abfd, amt);
       if (blk == NULL)
 	return NULL;
-      blk->size = read_2_bytes (abfd, info_ptr);
+      blk->size = read_2_bytes (abfd, info_ptr, info_ptr_end);
       info_ptr += 2;
-      blk->data = read_n_bytes (abfd, info_ptr, blk->size);
+      blk->data = read_n_bytes (abfd, info_ptr, info_ptr_end, blk->size);
       info_ptr += blk->size;
       attr->u.blk = blk;
       break;
@@ -983,34 +1055,34 @@ read_attribute_value (struct attribute *attr,
       blk = (struct dwarf_block *) bfd_alloc (abfd, amt);
       if (blk == NULL)
 	return NULL;
-      blk->size = read_4_bytes (abfd, info_ptr);
+      blk->size = read_4_bytes (abfd, info_ptr, info_ptr_end);
       info_ptr += 4;
-      blk->data = read_n_bytes (abfd, info_ptr, blk->size);
+      blk->data = read_n_bytes (abfd, info_ptr, info_ptr_end, blk->size);
       info_ptr += blk->size;
       attr->u.blk = blk;
       break;
     case DW_FORM_data2:
-      attr->u.val = read_2_bytes (abfd, info_ptr);
+      attr->u.val = read_2_bytes (abfd, info_ptr, info_ptr_end);
       info_ptr += 2;
       break;
     case DW_FORM_data4:
-      attr->u.val = read_4_bytes (abfd, info_ptr);
+      attr->u.val = read_4_bytes (abfd, info_ptr, info_ptr_end);
       info_ptr += 4;
       break;
     case DW_FORM_data8:
-      attr->u.val = read_8_bytes (abfd, info_ptr);
+      attr->u.val = read_8_bytes (abfd, info_ptr, info_ptr_end);
       info_ptr += 8;
       break;
     case DW_FORM_string:
-      attr->u.str = read_string (abfd, info_ptr, &bytes_read);
+      attr->u.str = read_string (abfd, info_ptr, info_ptr_end, &bytes_read);
       info_ptr += bytes_read;
       break;
     case DW_FORM_strp:
-      attr->u.str = read_indirect_string (unit, info_ptr, &bytes_read);
+      attr->u.str = read_indirect_string (unit, info_ptr, info_ptr_end, &bytes_read);
       info_ptr += bytes_read;
       break;
     case DW_FORM_GNU_strp_alt:
-      attr->u.str = read_alt_indirect_string (unit, info_ptr, &bytes_read);
+      attr->u.str = read_alt_indirect_string (unit, info_ptr, info_ptr_end, &bytes_read);
       info_ptr += bytes_read;
       break;
     case DW_FORM_exprloc:
@@ -1019,9 +1091,9 @@ read_attribute_value (struct attribute *attr,
       blk = (struct dwarf_block *) bfd_alloc (abfd, amt);
       if (blk == NULL)
 	return NULL;
-      blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+      blk->size = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, info_ptr_end);
       info_ptr += bytes_read;
-      blk->data = read_n_bytes (abfd, info_ptr, blk->size);
+      blk->data = read_n_bytes (abfd, info_ptr, info_ptr_end, blk->size);
       info_ptr += blk->size;
       attr->u.blk = blk;
       break;
@@ -1030,59 +1102,59 @@ read_attribute_value (struct attribute *attr,
       blk = (struct dwarf_block *) bfd_alloc (abfd, amt);
       if (blk == NULL)
 	return NULL;
-      blk->size = read_1_byte (abfd, info_ptr);
+      blk->size = read_1_byte (abfd, info_ptr, info_ptr_end);
       info_ptr += 1;
-      blk->data = read_n_bytes (abfd, info_ptr, blk->size);
+      blk->data = read_n_bytes (abfd, info_ptr, info_ptr_end, blk->size);
       info_ptr += blk->size;
       attr->u.blk = blk;
       break;
     case DW_FORM_data1:
-      attr->u.val = read_1_byte (abfd, info_ptr);
+      attr->u.val = read_1_byte (abfd, info_ptr, info_ptr_end);
       info_ptr += 1;
       break;
     case DW_FORM_flag:
-      attr->u.val = read_1_byte (abfd, info_ptr);
+      attr->u.val = read_1_byte (abfd, info_ptr, info_ptr_end);
       info_ptr += 1;
       break;
     case DW_FORM_flag_present:
       attr->u.val = 1;
       break;
     case DW_FORM_sdata:
-      attr->u.sval = read_signed_leb128 (abfd, info_ptr, &bytes_read);
+      attr->u.sval = safe_read_leb128 (abfd, info_ptr, &bytes_read, TRUE, info_ptr_end);
       info_ptr += bytes_read;
       break;
     case DW_FORM_udata:
-      attr->u.val = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+      attr->u.val = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, info_ptr_end);
       info_ptr += bytes_read;
       break;
     case DW_FORM_ref1:
-      attr->u.val = read_1_byte (abfd, info_ptr);
+      attr->u.val = read_1_byte (abfd, info_ptr, info_ptr_end);
       info_ptr += 1;
       break;
     case DW_FORM_ref2:
-      attr->u.val = read_2_bytes (abfd, info_ptr);
+      attr->u.val = read_2_bytes (abfd, info_ptr, info_ptr_end);
       info_ptr += 2;
       break;
     case DW_FORM_ref4:
-      attr->u.val = read_4_bytes (abfd, info_ptr);
+      attr->u.val = read_4_bytes (abfd, info_ptr, info_ptr_end);
       info_ptr += 4;
       break;
     case DW_FORM_ref8:
-      attr->u.val = read_8_bytes (abfd, info_ptr);
+      attr->u.val = read_8_bytes (abfd, info_ptr, info_ptr_end);
       info_ptr += 8;
       break;
     case DW_FORM_ref_sig8:
-      attr->u.val = read_8_bytes (abfd, info_ptr);
+      attr->u.val = read_8_bytes (abfd, info_ptr, info_ptr_end);
       info_ptr += 8;
       break;
     case DW_FORM_ref_udata:
-      attr->u.val = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+      attr->u.val = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, info_ptr_end);
       info_ptr += bytes_read;
       break;
     case DW_FORM_indirect:
-      form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+      form = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, info_ptr_end);
       info_ptr += bytes_read;
-      info_ptr = read_attribute_value (attr, form, unit, info_ptr);
+      info_ptr = read_attribute_value (attr, form, unit, info_ptr, info_ptr_end);
       break;
     default:
       (*_bfd_error_handler) (_("Dwarf Error: Invalid or unhandled FORM value: %#x."),
@@ -1096,13 +1168,14 @@ read_attribute_value (struct attribute *attr,
 /* Read an attribute described by an abbreviated attribute.  */
 
 static bfd_byte *
-read_attribute (struct attribute *attr,
-		struct attr_abbrev *abbrev,
-		struct comp_unit *unit,
-		bfd_byte *info_ptr)
+read_attribute (struct attribute *    attr,
+		struct attr_abbrev *  abbrev,
+		struct comp_unit *    unit,
+		bfd_byte *            info_ptr,
+		bfd_byte *            info_ptr_end)
 {
   attr->name = abbrev->name;
-  info_ptr = read_attribute_value (attr, abbrev->form, unit, info_ptr);
+  info_ptr = read_attribute_value (attr, abbrev->form, unit, info_ptr, info_ptr_end);
   return info_ptr;
 }
 
@@ -1387,7 +1460,11 @@ concat_filename (struct line_info_table *table, unsigned int file)
       char *name;
       size_t len;
 
-      if (table->files[file - 1].dir)
+      if (table->files[file - 1].dir
+	  /* PR 17512: file: 0317e960.  */
+	  && table->files[file - 1].dir <= table->num_dirs
+	  /* PR 17512: file: 7f3d2e4b.  */
+	  && table->dirs != NULL)
 	subdir_name = table->dirs[table->files[file - 1].dir - 1];
 
       if (!subdir_name || !IS_ABSOLUTE_PATH (subdir_name))
@@ -1608,27 +1685,47 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
 
   table->lcl_head = NULL;
 
+  if (stash->dwarf_line_size < 16)
+    {
+      (*_bfd_error_handler)
+	(_("Dwarf Error: Line info section is too small (%ld)"),
+	 (long) stash->dwarf_line_size);
+      bfd_set_error (bfd_error_bad_value);
+      return NULL;
+    }
   line_ptr = stash->dwarf_line_buffer + unit->line_offset;
+  line_end = stash->dwarf_line_buffer + stash->dwarf_line_size;
 
   /* Read in the prologue.  */
-  lh.total_length = read_4_bytes (abfd, line_ptr);
+  lh.total_length = read_4_bytes (abfd, line_ptr, line_end);
   line_ptr += 4;
   offset_size = 4;
   if (lh.total_length == 0xffffffff)
     {
-      lh.total_length = read_8_bytes (abfd, line_ptr);
+      lh.total_length = read_8_bytes (abfd, line_ptr, line_end);
       line_ptr += 8;
       offset_size = 8;
     }
   else if (lh.total_length == 0 && unit->addr_size == 8)
     {
       /* Handle (non-standard) 64-bit DWARF2 formats.  */
-      lh.total_length = read_4_bytes (abfd, line_ptr);
+      lh.total_length = read_4_bytes (abfd, line_ptr, line_end);
       line_ptr += 4;
       offset_size = 8;
     }
+
+  if (lh.total_length > stash->dwarf_line_size)
+    {
+      (*_bfd_error_handler)
+	(_("Dwarf Error: Line info data is bigger (0x%lx) than the section (0x%lx)"),
+	 (long) lh.total_length, (long) stash->dwarf_line_size);
+      bfd_set_error (bfd_error_bad_value);
+      return NULL;
+    }
+
   line_end = line_ptr + lh.total_length;
-  lh.version = read_2_bytes (abfd, line_ptr);
+
+  lh.version = read_2_bytes (abfd, line_ptr, line_end);
   if (lh.version < 2 || lh.version > 4)
     {
       (*_bfd_error_handler)
@@ -1637,20 +1734,32 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
       return NULL;
     }
   line_ptr += 2;
+
+  if (line_ptr + offset_size + (lh.version >=4 ? 6 : 5) >= line_end)
+    {
+      (*_bfd_error_handler)
+	(_("Dwarf Error: Ran out of room reading prologue"));
+      bfd_set_error (bfd_error_bad_value);
+      return NULL;
+    }
+
   if (offset_size == 4)
-    lh.prologue_length = read_4_bytes (abfd, line_ptr);
+    lh.prologue_length = read_4_bytes (abfd, line_ptr, line_end);
   else
-    lh.prologue_length = read_8_bytes (abfd, line_ptr);
+    lh.prologue_length = read_8_bytes (abfd, line_ptr, line_end);
   line_ptr += offset_size;
-  lh.minimum_instruction_length = read_1_byte (abfd, line_ptr);
+
+  lh.minimum_instruction_length = read_1_byte (abfd, line_ptr, line_end);
   line_ptr += 1;
+
   if (lh.version >= 4)
     {
-      lh.maximum_ops_per_insn = read_1_byte (abfd, line_ptr);
+      lh.maximum_ops_per_insn = read_1_byte (abfd, line_ptr, line_end);
       line_ptr += 1;
     }
   else
     lh.maximum_ops_per_insn = 1;
+
   if (lh.maximum_ops_per_insn == 0)
     {
       (*_bfd_error_handler)
@@ -1658,14 +1767,26 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
       bfd_set_error (bfd_error_bad_value);
       return NULL;
     }
-  lh.default_is_stmt = read_1_byte (abfd, line_ptr);
+
+  lh.default_is_stmt = read_1_byte (abfd, line_ptr, line_end);
   line_ptr += 1;
-  lh.line_base = read_1_signed_byte (abfd, line_ptr);
+
+  lh.line_base = read_1_signed_byte (abfd, line_ptr, line_end);
   line_ptr += 1;
-  lh.line_range = read_1_byte (abfd, line_ptr);
+
+  lh.line_range = read_1_byte (abfd, line_ptr, line_end);
   line_ptr += 1;
-  lh.opcode_base = read_1_byte (abfd, line_ptr);
+
+  lh.opcode_base = read_1_byte (abfd, line_ptr, line_end);
   line_ptr += 1;
+
+  if (line_ptr + (lh.opcode_base - 1) >= line_end)
+    {
+      (*_bfd_error_handler) (_("Dwarf Error: Ran out of room reading opcodes"));
+      bfd_set_error (bfd_error_bad_value);
+      return NULL;
+    }
+
   amt = lh.opcode_base * sizeof (unsigned char);
   lh.standard_opcode_lengths = (unsigned char *) bfd_alloc (abfd, amt);
 
@@ -1673,12 +1794,12 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
 
   for (i = 1; i < lh.opcode_base; ++i)
     {
-      lh.standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
+      lh.standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr, line_end);
       line_ptr += 1;
     }
 
   /* Read directory table.  */
-  while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL)
+  while ((cur_dir = read_string (abfd, line_ptr, line_end, &bytes_read)) != NULL)
     {
       line_ptr += bytes_read;
 
@@ -1701,7 +1822,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
   line_ptr += bytes_read;
 
   /* Read file name table.  */
-  while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL)
+  while ((cur_file = read_string (abfd, line_ptr, line_end, &bytes_read)) != NULL)
     {
       line_ptr += bytes_read;
 
@@ -1720,13 +1841,11 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
 
       table->files[table->num_files].name = cur_file;
       table->files[table->num_files].dir =
-	read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+	safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
       line_ptr += bytes_read;
-      table->files[table->num_files].time =
-	read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+      table->files[table->num_files].time = safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
       line_ptr += bytes_read;
-      table->files[table->num_files].size =
-	read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+      table->files[table->num_files].size = safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
       line_ptr += bytes_read;
       table->num_files++;
     }
@@ -1756,13 +1875,15 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
       /* Decode the table.  */
       while (! end_sequence)
 	{
-	  op_code = read_1_byte (abfd, line_ptr);
+	  op_code = read_1_byte (abfd, line_ptr, line_end);
 	  line_ptr += 1;
 
 	  if (op_code >= lh.opcode_base)
 	    {
 	      /* Special operand.  */
 	      adj_opcode = op_code - lh.opcode_base;
+	      if (lh.line_range == 0)
+		goto line_fail;
 	      if (lh.maximum_ops_per_insn == 1)
 		address += (adj_opcode / lh.line_range
 			    * lh.minimum_instruction_length);
@@ -1788,9 +1909,9 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
 	  else switch (op_code)
 	    {
 	    case DW_LNS_extended_op:
-	      exop_len = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+	      exop_len = safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
 	      line_ptr += bytes_read;
-	      extended_op = read_1_byte (abfd, line_ptr);
+	      extended_op = read_1_byte (abfd, line_ptr, line_end);
 	      line_ptr += 1;
 
 	      switch (extended_op)
@@ -1809,12 +1930,12 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
 		    goto line_fail;
 		  break;
 		case DW_LNE_set_address:
-		  address = read_address (unit, line_ptr);
+		  address = read_address (unit, line_ptr, line_end);
 		  op_index = 0;
 		  line_ptr += unit->addr_size;
 		  break;
 		case DW_LNE_define_file:
-		  cur_file = read_string (abfd, line_ptr, &bytes_read);
+		  cur_file = read_string (abfd, line_ptr, line_end, &bytes_read);
 		  line_ptr += bytes_read;
 		  if ((table->num_files % FILE_ALLOC_CHUNK) == 0)
 		    {
@@ -1829,19 +1950,19 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
 		    }
 		  table->files[table->num_files].name = cur_file;
 		  table->files[table->num_files].dir =
-		    read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+		    safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
 		  line_ptr += bytes_read;
 		  table->files[table->num_files].time =
-		    read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+		    safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
 		  line_ptr += bytes_read;
 		  table->files[table->num_files].size =
-		    read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+		    safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
 		  line_ptr += bytes_read;
 		  table->num_files++;
 		  break;
 		case DW_LNE_set_discriminator:
 		  discriminator =
-		    read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+		    safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
 		  line_ptr += bytes_read;
 		  break;
 		case DW_LNE_HP_source_file_correlation:
@@ -1870,12 +1991,12 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
 	    case DW_LNS_advance_pc:
 	      if (lh.maximum_ops_per_insn == 1)
 		address += (lh.minimum_instruction_length
-			    * read_unsigned_leb128 (abfd, line_ptr,
-						    &bytes_read));
+			    * safe_read_leb128 (abfd, line_ptr, &bytes_read,
+						FALSE, line_end));
 	      else
 		{
-		  bfd_vma adjust = read_unsigned_leb128 (abfd, line_ptr,
-							 &bytes_read);
+		  bfd_vma adjust = safe_read_leb128 (abfd, line_ptr, &bytes_read,
+						     FALSE, line_end);
 		  address = ((op_index + adjust) / lh.maximum_ops_per_insn
 			     * lh.minimum_instruction_length);
 		  op_index = (op_index + adjust) % lh.maximum_ops_per_insn;
@@ -1883,7 +2004,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
 	      line_ptr += bytes_read;
 	      break;
 	    case DW_LNS_advance_line:
-	      line += read_signed_leb128 (abfd, line_ptr, &bytes_read);
+	      line += safe_read_leb128 (abfd, line_ptr, &bytes_read, TRUE, line_end);
 	      line_ptr += bytes_read;
 	      break;
 	    case DW_LNS_set_file:
@@ -1892,7 +2013,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
 
 		/* The file and directory tables are 0
 		   based, the references are 1 based.  */
-		file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+		file = safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
 		line_ptr += bytes_read;
 		if (filename)
 		  free (filename);
@@ -1900,7 +2021,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
 		break;
 	      }
 	    case DW_LNS_set_column:
-	      column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+	      column = safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
 	      line_ptr += bytes_read;
 	      break;
 	    case DW_LNS_negate_stmt:
@@ -1922,7 +2043,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
 		}
 	      break;
 	    case DW_LNS_fixed_advance_pc:
-	      address += read_2_bytes (abfd, line_ptr);
+	      address += read_2_bytes (abfd, line_ptr, line_end);
 	      op_index = 0;
 	      line_ptr += 2;
 	      break;
@@ -1930,7 +2051,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
 	      /* Unknown standard opcode, ignore it.  */
 	      for (i = 0; i < lh.standard_opcode_lengths[op_code]; i++)
 		{
-		  (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+		  (void) safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
 		  line_ptr += bytes_read;
 		}
 	      break;
@@ -2159,6 +2280,7 @@ find_abstract_instance_name (struct comp_unit *unit,
 {
   bfd *abfd = unit->abfd;
   bfd_byte *info_ptr;
+  bfd_byte *info_ptr_end;
   unsigned int abbrev_number, bytes_read, i;
   struct abbrev_info *abbrev;
   bfd_uint64_t die_ref = attr_ptr->u.val;
@@ -2175,6 +2297,7 @@ find_abstract_instance_name (struct comp_unit *unit,
 	abort ();
 
       info_ptr = unit->sec_info_ptr + die_ref;
+      info_ptr_end = unit->end_ptr;
 
       /* Now find the CU containing this pointer.  */
       if (info_ptr >= unit->info_ptr_unit && info_ptr < unit->end_ptr)
@@ -2208,13 +2331,18 @@ find_abstract_instance_name (struct comp_unit *unit,
 	  bfd_set_error (bfd_error_bad_value);
 	  return NULL;
 	}
+      info_ptr_end = unit->stash->alt_dwarf_info_buffer + unit->stash->alt_dwarf_info_size;
+
       /* FIXME: Do we need to locate the correct CU, in a similar
 	 fashion to the code in the DW_FORM_ref_addr case above ?  */
     }
   else
-    info_ptr = unit->info_ptr_unit + die_ref;
+    {
+      info_ptr = unit->info_ptr_unit + die_ref;
+      info_ptr_end = unit->end_ptr;
+    }
 
-  abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+  abbrev_number = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, info_ptr_end);
   info_ptr += bytes_read;
 
   if (abbrev_number)
@@ -2231,7 +2359,7 @@ find_abstract_instance_name (struct comp_unit *unit,
 	  for (i = 0; i < abbrev->num_attrs; ++i)
 	    {
 	      info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit,
-					 info_ptr);
+					 info_ptr, info_ptr_end);
 	      if (info_ptr == NULL)
 		break;
 	      switch (attr.name)
@@ -2273,6 +2401,7 @@ read_rangelist (struct comp_unit *unit, struct arange *arange,
 		bfd_uint64_t offset)
 {
   bfd_byte *ranges_ptr;
+  bfd_byte *ranges_end;
   bfd_vma base_address = unit->base_address;
 
   if (! unit->stash->dwarf_ranges_buffer)
@@ -2280,16 +2409,24 @@ read_rangelist (struct comp_unit *unit, struct arange *arange,
       if (! read_debug_ranges (unit))
 	return FALSE;
     }
+
   ranges_ptr = unit->stash->dwarf_ranges_buffer + offset;
+  if (ranges_ptr < unit->stash->dwarf_ranges_buffer)
+    return FALSE;
+  ranges_end = unit->stash->dwarf_ranges_buffer + unit->stash->dwarf_ranges_size;
 
   for (;;)
     {
       bfd_vma low_pc;
       bfd_vma high_pc;
 
-      low_pc = read_address (unit, ranges_ptr);
+      /* PR 17512: file: 62cada7d.  */
+      if (ranges_ptr + 2 * unit->addr_size > ranges_end)
+	return FALSE;
+
+      low_pc = read_address (unit, ranges_ptr, ranges_end);
       ranges_ptr += unit->addr_size;
-      high_pc = read_address (unit, ranges_ptr);
+      high_pc = read_address (unit, ranges_ptr, ranges_end);
       ranges_ptr += unit->addr_size;
 
       if (low_pc == 0 && high_pc == 0)
@@ -2316,6 +2453,7 @@ scan_unit_for_symbols (struct comp_unit *unit)
 {
   bfd *abfd = unit->abfd;
   bfd_byte *info_ptr = unit->first_child_die_ptr;
+  bfd_byte *info_ptr_end = unit->stash->info_ptr_end;
   int nesting_level = 1;
   struct funcinfo **nested_funcs;
   int nested_funcs_size;
@@ -2340,7 +2478,11 @@ scan_unit_for_symbols (struct comp_unit *unit)
       bfd_vma high_pc = 0;
       bfd_boolean high_pc_relative = FALSE;
 
-      abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+      /* PR 17512: file: 9f405d9d.  */
+      if (info_ptr >= info_ptr_end)
+	goto fail;
+
+      abbrev_number = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, info_ptr_end);
       info_ptr += bytes_read;
 
       if (! abbrev_number)
@@ -2404,7 +2546,7 @@ scan_unit_for_symbols (struct comp_unit *unit)
 
       for (i = 0; i < abbrev->num_attrs; ++i)
 	{
-	  info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr);
+	  info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr, info_ptr_end);
 	  if (info_ptr == NULL)
 	    goto fail;
 
@@ -2602,15 +2744,15 @@ parse_comp_unit (struct dwarf2_debug *stash,
   bfd *abfd = stash->bfd_ptr;
   bfd_boolean high_pc_relative = FALSE;
 
-  version = read_2_bytes (abfd, info_ptr);
+  version = read_2_bytes (abfd, info_ptr, end_ptr);
   info_ptr += 2;
   BFD_ASSERT (offset_size == 4 || offset_size == 8);
   if (offset_size == 4)
-    abbrev_offset = read_4_bytes (abfd, info_ptr);
+    abbrev_offset = read_4_bytes (abfd, info_ptr, end_ptr);
   else
-    abbrev_offset = read_8_bytes (abfd, info_ptr);
+    abbrev_offset = read_8_bytes (abfd, info_ptr, end_ptr);
   info_ptr += offset_size;
-  addr_size = read_1_byte (abfd, info_ptr);
+  addr_size = read_1_byte (abfd, info_ptr, end_ptr);
   info_ptr += 1;
 
   if (version != 2 && version != 3 && version != 4)
@@ -2647,7 +2789,7 @@ parse_comp_unit (struct dwarf2_debug *stash,
   if (! abbrevs)
     return 0;
 
-  abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+  abbrev_number = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, end_ptr);
   info_ptr += bytes_read;
   if (! abbrev_number)
     {
@@ -2682,7 +2824,7 @@ parse_comp_unit (struct dwarf2_debug *stash,
 
   for (i = 0; i < abbrev->num_attrs; ++i)
     {
-      info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr);
+      info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr, end_ptr);
       if (info_ptr == NULL)
 	return NULL;
 
@@ -2721,6 +2863,15 @@ parse_comp_unit (struct dwarf2_debug *stash,
 	case DW_AT_comp_dir:
 	  {
 	    char *comp_dir = attr.u.str;
+
+	    /* PR 17512: file: 1fe726be.  */
+	    if (! is_str_attr (attr.form))
+	      {
+		(*_bfd_error_handler)
+		  (_("Dwarf Error: DW_AT_comp_dir attribute encountered with a non-string form."));
+		comp_dir = NULL;
+	      }
+
 	    if (comp_dir)
 	      {
 		/* Irix 6.2 native cc prepends <machine>.: to the compilation
@@ -3637,6 +3788,57 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd,
   return TRUE;
 }
 
+/* Scan the debug information in PINFO looking for a DW_TAG_subprogram
+   abbrev with a DW_AT_low_pc attached to it.  Then lookup that same
+   symbol in SYMBOLS and return the difference between the low_pc and
+   the symbol's address.  Returns 0 if no suitable symbol could be found.  */
+
+bfd_signed_vma
+_bfd_dwarf2_find_symbol_bias (asymbol ** symbols, void ** pinfo)
+{
+  struct dwarf2_debug *stash;
+  struct comp_unit * unit;
+
+  stash = (struct dwarf2_debug *) *pinfo;
+
+  if (stash == NULL)
+    return 0;
+
+  for (unit = stash->all_comp_units; unit; unit = unit->next_unit)
+    {
+      struct funcinfo * func;
+
+      if (unit->function_table == NULL)
+	{
+	  if (unit->line_table == NULL)
+	    unit->line_table = decode_line_info (unit, stash);
+	  if (unit->line_table != NULL)
+	    scan_unit_for_symbols (unit);
+	}
+
+      for (func = unit->function_table; func != NULL; func = func->prev_func)
+	if (func->name && func->arange.low)
+	  {
+	    asymbol ** psym;
+
+	    /* FIXME: Do we need to scan the aranges looking for the lowest pc value ?  */
+
+	    for (psym = symbols; * psym != NULL; psym++)
+	      {
+		asymbol * sym = * psym;
+
+		if (sym->flags & BSF_FUNCTION
+		    && sym->section != NULL
+		    && strcmp (sym->name, func->name) == 0)
+		  return ((bfd_signed_vma) func->arange.low) -
+		    ((bfd_signed_vma) (sym->value + sym->section->vma));
+	      }
+	  }
+    }
+
+  return 0;
+}
+
 /* Find the source code location of SYMBOL.  If SYMBOL is NULL
    then find the nearest source code location corresponding to
    the address SECTION + OFFSET.
@@ -3823,13 +4025,13 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
       unsigned int offset_size = addr_size;
       bfd_byte *info_ptr_unit = stash->info_ptr;
 
-      length = read_4_bytes (stash->bfd_ptr, stash->info_ptr);
+      length = read_4_bytes (stash->bfd_ptr, stash->info_ptr, stash->info_ptr_end);
       /* A 0xffffff length is the DWARF3 way of indicating
 	 we use 64-bit offsets, instead of 32-bit offsets.  */
       if (length == 0xffffffff)
 	{
 	  offset_size = 8;
-	  length = read_8_bytes (stash->bfd_ptr, stash->info_ptr + 4);
+	  length = read_8_bytes (stash->bfd_ptr, stash->info_ptr + 4, stash->info_ptr_end);
 	  stash->info_ptr += 12;
 	}
       /* A zero length is the IRIX way of indicating 64-bit offsets,
@@ -3838,7 +4040,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
       else if (length == 0)
 	{
 	  offset_size = 8;
-	  length = read_4_bytes (stash->bfd_ptr, stash->info_ptr + 4);
+	  length = read_4_bytes (stash->bfd_ptr, stash->info_ptr + 4, stash->info_ptr_end);
 	  stash->info_ptr += 8;
 	}
       /* In the absence of the hints above, we assume 32-bit DWARF2
@@ -3860,13 +4062,25 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
 
       if (length > 0)
 	{
+	  bfd_byte * new_ptr;
+
 	  each = parse_comp_unit (stash, length, info_ptr_unit,
 				  offset_size);
 	  if (!each)
 	    /* The dwarf information is damaged, don't trust it any
 	       more.  */
 	    break;
-	  stash->info_ptr += length;
+
+	  new_ptr = stash->info_ptr + length;
+	  /* PR 17512: file: 1500698c.  */
+	  if (new_ptr < stash->info_ptr)
+	    {
+	      /* A corrupt length value - do not trust the info any more.  */
+	      found = FALSE;
+	      break;
+	    }
+	  else
+	    stash->info_ptr = new_ptr;
 
 	  if (stash->all_comp_units)
 	    stash->all_comp_units->prev_unit = each;
diff --git a/bfd/elf-attrs.c b/bfd/elf-attrs.c
index cd0cbca..d20bbdd 100644
--- a/bfd/elf-attrs.c
+++ b/bfd/elf-attrs.c
@@ -430,9 +430,13 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
 {
   bfd_byte *contents;
   bfd_byte *p;
+  bfd_byte *p_end;
   bfd_vma len;
   const char *std_sec;
 
+  /* PR 17512: file: 2844a11d.  */
+  if (hdr->sh_size == 0)
+    return;
   contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
   if (!contents)
     return;
@@ -443,11 +447,12 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
       return;
     }
   p = contents;
+  p_end = p + hdr->sh_size;
   std_sec = get_elf_backend_data (abfd)->obj_attrs_vendor;
   if (*(p++) == 'A')
     {
       len = hdr->sh_size - 1;
-      while (len > 0)
+      while (len > 0 && p < p_end - 4)
 	{
 	  unsigned namelen;
 	  bfd_vma section_len;
@@ -455,6 +460,8 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
 
 	  section_len = bfd_get_32 (abfd, p);
 	  p += 4;
+	  if (section_len == 0)
+	    break;
 	  if (section_len > len)
 	    section_len = len;
 	  len -= section_len;
@@ -475,7 +482,7 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
 	    }
 
 	  p += namelen;
-	  while (section_len > 0)
+	  while (section_len > 0 && p < p_end)
 	    {
 	      int tag;
 	      unsigned int n;
@@ -483,15 +490,23 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
 	      bfd_vma subsection_len;
 	      bfd_byte *end;
 
-	      tag = read_unsigned_leb128 (abfd, p, &n);
+	      tag = safe_read_leb128 (abfd, p, &n, FALSE, p_end);
 	      p += n;
-	      subsection_len = bfd_get_32 (abfd, p);
+	      if (p < p_end - 4)
+		subsection_len = bfd_get_32 (abfd, p);
+	      else
+		subsection_len = 0;
 	      p += 4;
+	      if (subsection_len == 0)
+		break;
 	      if (subsection_len > section_len)
 		subsection_len = section_len;
 	      section_len -= subsection_len;
 	      subsection_len -= n + 4;
 	      end = p + subsection_len;
+	      /* PR 17512: file: 0e8c0c90.  */
+	      if (end > p_end)
+		end = p_end;
 	      switch (tag)
 		{
 		case Tag_File:
@@ -499,25 +514,25 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
 		    {
 		      int type;
 
-		      tag = read_unsigned_leb128 (abfd, p, &n);
+		      tag = safe_read_leb128 (abfd, p, &n, FALSE, end);
 		      p += n;
 		      type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag);
 		      switch (type & (ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL))
 			{
 			case ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL:
-			  val = read_unsigned_leb128 (abfd, p, &n);
+			  val = safe_read_leb128 (abfd, p, &n, FALSE, end);
 			  p += n;
 			  bfd_elf_add_obj_attr_int_string (abfd, vendor, tag,
-							   val, (char *)p);
+							   val, (char *) p);
 			  p += strlen ((char *)p) + 1;
 			  break;
 			case ATTR_TYPE_FLAG_STR_VAL:
 			  bfd_elf_add_obj_attr_string (abfd, vendor, tag,
-						       (char *)p);
+						       (char *) p);
 			  p += strlen ((char *)p) + 1;
 			  break;
 			case ATTR_TYPE_FLAG_INT_VAL:
-			  val = read_unsigned_leb128 (abfd, p, &n);
+			  val = safe_read_leb128 (abfd, p, &n, FALSE, end);
 			  p += n;
 			  bfd_elf_add_obj_attr_int (abfd, vendor, tag, val);
 			  break;
diff --git a/bfd/elf-m10300.c b/bfd/elf-m10300.c
index 0b13c1a..fb8c1c6 100644
--- a/bfd/elf-m10300.c
+++ b/bfd/elf-m10300.c
@@ -806,7 +806,13 @@ mn10300_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_MN10300_MAX);
+  if (r_type >= R_MN10300_MAX)
+    {
+      (*_bfd_error_handler) (_("%B: unrecognised MN10300 reloc number: %d"),
+			     abfd, r_type);
+      bfd_set_error (bfd_error_bad_value);
+      r_type = R_MN10300_NONE;
+    }
   cache_ptr->howto = elf_mn10300_howto_table + r_type;
 }
 
diff --git a/bfd/elf.c b/bfd/elf.c
index 78da35b..9de3ddb 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -297,13 +297,14 @@ bfd_elf_get_str_section (bfd *abfd, unsigned int shindex)
       /* Allocate and clear an extra byte at the end, to prevent crashes
 	 in case the string table is not terminated.  */
       if (shstrtabsize + 1 <= 1
-	  || (shstrtab = (bfd_byte *) bfd_alloc (abfd, shstrtabsize + 1)) == NULL
-	  || bfd_seek (abfd, offset, SEEK_SET) != 0)
+	  || bfd_seek (abfd, offset, SEEK_SET) != 0
+	  || (shstrtab = (bfd_byte *) bfd_alloc (abfd, shstrtabsize + 1)) == NULL)
 	shstrtab = NULL;
       else if (bfd_bread (shstrtab, shstrtabsize, abfd) != shstrtabsize)
 	{
 	  if (bfd_get_error () != bfd_error_system_call)
 	    bfd_set_error (bfd_error_file_truncated);
+	  bfd_release (abfd, shstrtab);
 	  shstrtab = NULL;
 	  /* Once we've failed to read it, make sure we don't keep
 	     trying.  Otherwise, we'll keep allocating space for
@@ -332,9 +333,19 @@ bfd_elf_string_from_elf_section (bfd *abfd,
 
   hdr = elf_elfsections (abfd)[shindex];
 
-  if (hdr->contents == NULL
-      && bfd_elf_get_str_section (abfd, shindex) == NULL)
-    return NULL;
+  if (hdr->contents == NULL)
+    {
+      if (hdr->sh_type != SHT_STRTAB && hdr->sh_type < SHT_LOOS)
+	{
+	  /* PR 17512: file: f057ec89.  */
+	  _bfd_error_handler (_("%B: attempt to load strings from a non-string section (number %d)"),
+			      abfd, shindex);
+	  return NULL;
+	}
+  
+      if (bfd_elf_get_str_section (abfd, shindex) == NULL)
+	return NULL;
+    }
 
   if (strindex >= hdr->sh_size)
     {
@@ -1253,8 +1264,13 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
       swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
 
       extdyn = dynbuf;
+      /* PR 17512: file: 6f427532.  */
+      if (s->size < extdynsize)
+	goto error_return;
       extdynend = extdyn + s->size;
-      for (; extdyn < extdynend; extdyn += extdynsize)
+      /* PR 17512: file: id:000006,sig:06,src:000000,op:flip4,pos:5664.
+         Fix range check.  */
+      for (; extdyn <= (extdynend - extdynsize); extdyn += extdynsize)
 	{
 	  Elf_Internal_Dyn dyn;
 	  const char *name = "";
@@ -1589,7 +1605,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
   if (++ nesting > 3)
     {
       /* PR17512: A corrupt ELF binary might contain a recursive group of
-	 sections, each the string indicies pointing to the next in the
+	 sections, each with string indicies pointing to the next in the
 	 loop.  Detect this here, by refusing to load a section that we are
 	 already in the process of loading.  We only trigger this test if
 	 we have nested at least three sections deep as normal ELF binaries
@@ -1956,7 +1972,9 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
 	else
 	  p_hdr = &esdt->rel.hdr;
 
-	BFD_ASSERT (*p_hdr == NULL);
+	/* PR 17512: file: 0b4f81b7.  */
+	if (*p_hdr != NULL)
+	  goto fail;
 	amt = sizeof (*hdr2);
 	hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
 	if (hdr2 == NULL)
@@ -2013,9 +2031,11 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
       if (hdr->contents != NULL)
 	{
 	  Elf_Internal_Group *idx = (Elf_Internal_Group *) hdr->contents;
-	  unsigned int n_elt = hdr->sh_size / GRP_ENTRY_SIZE;
+	  unsigned int n_elt = hdr->sh_size / sizeof (* idx);
 	  asection *s;
 
+	  if (n_elt == 0)
+	    goto fail;
 	  if (idx->flags & GRP_COMDAT)
 	    hdr->bfd_section->flags
 	      |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
@@ -2720,6 +2740,15 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
   this_hdr->sh_offset = 0;
   this_hdr->sh_size = asect->size;
   this_hdr->sh_link = 0;
+  /* PR 17512: file: 0eb809fe, 8b0535ee.  */
+  if (asect->alignment_power >= (sizeof (bfd_vma) * 8) - 1)
+    {
+      (*_bfd_error_handler)
+	(_("%B: error: Alignment power %d of section `%A' is too big"),
+	 abfd, asect, asect->alignment_power);
+      arg->failed = TRUE;
+      return;
+    }
   this_hdr->sh_addralign = (bfd_vma) 1 << asect->alignment_power;
   /* The sh_entsize and sh_info fields may have been set already by
      copy_private_section_data.  */
@@ -3973,6 +4002,11 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
       last_size = 0;
       phdr_index = 0;
       maxpagesize = bed->maxpagesize;
+      /* PR 17512: file: c8455299.
+	 Avoid divide-by-zero errors later on.
+	 FIXME: Should we abort if the maxpagesize is zero ?  */
+      if (maxpagesize == 0)
+	maxpagesize = 1;
       writable = FALSE;
       dynsec = bfd_get_section_by_name (abfd, ".dynamic");
       if (dynsec != NULL
@@ -5168,7 +5202,14 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
 	      && (p->p_type != PT_NOTE
 		  || bfd_get_format (abfd) != bfd_core))
 	    {
-	      BFD_ASSERT (!m->includes_filehdr && !m->includes_phdrs);
+	      if (m->includes_filehdr || m->includes_phdrs)
+		{
+		  /* PR 17512: file: 2195325e.  */ 
+		  (*_bfd_error_handler)
+		    (_("%B: warning: non-load segment includes file header and/or program header"),
+		     abfd);
+		  return FALSE;
+		}
 
 	      p->p_filesz = 0;
 	      p->p_offset = m->sections[0]->filepos;
@@ -6523,7 +6564,15 @@ rewrite:
 	   i++, segment++)
 	if (segment->p_type == PT_LOAD
 	    && maxpagesize < segment->p_align)
-	  maxpagesize = segment->p_align;
+	  {
+	    /* PR 17512: file: f17299af.  */
+	    if (segment->p_align > (bfd_vma) 1 << ((sizeof (bfd_vma) * 8) - 2))
+	      (*_bfd_error_handler) (_("\
+%B: warning: segment alignment of 0x%llx is too large"),
+				     ibfd, (long long) segment->p_align);
+	    else
+	      maxpagesize = segment->p_align;
+	  }
 
       if (maxpagesize != get_elf_backend_data (obfd)->maxpagesize)
 	bfd_emul_set_maxpagesize (bfd_get_target (obfd), maxpagesize);
@@ -9710,10 +9759,14 @@ elf_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size)
   if (bfd_seek (abfd, offset, SEEK_SET) != 0)
     return FALSE;
 
-  buf = (char *) bfd_malloc (size);
+  buf = (char *) bfd_malloc (size + 1);
   if (buf == NULL)
     return FALSE;
 
+  /* PR 17512: file: ec08f814
+     0-termintate the buffer so that string searches will not overflow.  */
+  buf[size] = 0;
+
   if (bfd_bread (buf, size, abfd) != size
       || !elf_parse_notes (abfd, buf, size, offset))
     {
diff --git a/bfd/elf32-arc.c b/bfd/elf32-arc.c
index d193965..e805706 100644
--- a/bfd/elf32-arc.c
+++ b/bfd/elf32-arc.c
@@ -172,7 +172,11 @@ arc_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_ARC_max);
+  if (r_type >= (unsigned int) R_ARC_max)
+    {
+      _bfd_error_handler (_("%B: invalid ARC reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = &elf_arc_howto_table[r_type];
 }
 
diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c
index dad04e2..bb84f69 100644
--- a/bfd/elf32-avr.c
+++ b/bfd/elf32-avr.c
@@ -859,7 +859,11 @@ avr_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_AVR_max);
+  if (r_type >= (unsigned int) R_AVR_max)
+    {
+      _bfd_error_handler (_("%B: invalid AVR reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = &elf_avr_howto_table[r_type];
 }
 
diff --git a/bfd/elf32-cr16.c b/bfd/elf32-cr16.c
index 862d9ff..e53064e 100644
--- a/bfd/elf32-cr16.c
+++ b/bfd/elf32-cr16.c
@@ -673,7 +673,13 @@ elf_cr16_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
 {
   unsigned int r_type = ELF32_R_TYPE (dst->r_info);
 
-  BFD_ASSERT (r_type < (unsigned int) R_CR16_MAX);
+  if (r_type >= R_CR16_MAX)
+    {
+      (*_bfd_error_handler) (_("%B: unrecognised CR16 reloc number: %d"),
+			     abfd, r_type);
+      bfd_set_error (bfd_error_bad_value);
+      r_type = R_CR16_NONE;
+    }
   cache_ptr->howto = cr16_elf_howto_table + r_type;
 }
 
diff --git a/bfd/elf32-cr16c.c b/bfd/elf32-cr16c.c
index cf4503c..0980111 100644
--- a/bfd/elf32-cr16c.c
+++ b/bfd/elf32-cr16c.c
@@ -180,7 +180,11 @@ elf_cr16c_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
 {
   unsigned int r_type = ELF32_R_TYPE (dst->r_info);
 
-  BFD_ASSERT (r_type < (unsigned int) RINDEX_16C_MAX);
+  if (r_type >= RINDEX_16C_MAX)
+    {
+      _bfd_error_handler (_("%B: invalid CR16C reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = &elf_howto_table[r_type];
 }
 
diff --git a/bfd/elf32-cris.c b/bfd/elf32-cris.c
index ce1cbfe..c297339 100644
--- a/bfd/elf32-cris.c
+++ b/bfd/elf32-cris.c
@@ -461,7 +461,11 @@ cris_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
   enum elf_cris_reloc_type r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_CRIS_max);
+  if (r_type >= R_CRIS_max)
+    {
+      _bfd_error_handler (_("%B: invalid CRIS reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = & cris_elf_howto_table [r_type];
 }
 
diff --git a/bfd/elf32-crx.c b/bfd/elf32-crx.c
index 607ad9c..9be3161 100644
--- a/bfd/elf32-crx.c
+++ b/bfd/elf32-crx.c
@@ -423,7 +423,13 @@ elf_crx_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
 		       Elf_Internal_Rela *dst)
 {
   unsigned int r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_CRX_MAX);
+  if (r_type >= R_CRX_MAX)
+    {
+      (*_bfd_error_handler) (_("%B: unrecognised CRX reloc number: %d"),
+			     abfd, r_type);
+      bfd_set_error (bfd_error_bad_value);
+      r_type = R_CRX_NONE;
+    }
   cache_ptr->howto = &crx_elf_howto_table[r_type];
 }
 
diff --git a/bfd/elf32-d10v.c b/bfd/elf32-d10v.c
index 6680864..3e906ae 100644
--- a/bfd/elf32-d10v.c
+++ b/bfd/elf32-d10v.c
@@ -228,7 +228,11 @@ d10v_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_D10V_max);
+  if (r_type >= (unsigned int) R_D10V_max)
+    {
+      _bfd_error_handler (_("%B: invalid D10V reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = &elf_d10v_howto_table[r_type];
 }
 
diff --git a/bfd/elf32-d30v.c b/bfd/elf32-d30v.c
index e39cdff..479f6e1 100644
--- a/bfd/elf32-d30v.c
+++ b/bfd/elf32-d30v.c
@@ -516,7 +516,11 @@ d30v_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_D30V_max);
+  if (r_type >= (unsigned int) R_D30V_max)
+    {
+      _bfd_error_handler (_("%B: invalid D30V reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = &elf_d30v_howto_table[r_type];
 }
 
@@ -530,7 +534,11 @@ d30v_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_D30V_max);
+  if (r_type >= (unsigned int) R_D30V_max)
+    {
+      _bfd_error_handler (_("%B: invalid D30V reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = &elf_d30v_howto_table[r_type];
 }
 
diff --git a/bfd/elf32-dlx.c b/bfd/elf32-dlx.c
index 978befd..1ffbc3e 100644
--- a/bfd/elf32-dlx.c
+++ b/bfd/elf32-dlx.c
@@ -546,7 +546,11 @@ dlx_rtype_to_howto (unsigned int r_type)
     case R_DLX_RELOC_16_LO:
       return & elf_dlx_reloc_16_lo;
     default:
-      BFD_ASSERT (r_type < (unsigned int) R_DLX_max);
+      if (r_type >= (unsigned int) R_DLX_max)
+	{
+	  _bfd_error_handler (_("Invalid DLX reloc number: %d"), r_type);
+	  r_type = 0;
+	}
       return & dlx_elf_howto_table[r_type];
     }
 }
diff --git a/bfd/elf32-epiphany.c b/bfd/elf32-epiphany.c
index 133521f..addd467 100644
--- a/bfd/elf32-epiphany.c
+++ b/bfd/elf32-epiphany.c
@@ -370,6 +370,11 @@ epiphany_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
+  if (r_type >= (unsigned int) R_EPIPHANY_max)
+    {
+      _bfd_error_handler (_("%B: invalid Epiphany reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = & epiphany_elf_howto_table [r_type];
 }
 
diff --git a/bfd/elf32-fr30.c b/bfd/elf32-fr30.c
index 3cc31b7..0715d97 100644
--- a/bfd/elf32-fr30.c
+++ b/bfd/elf32-fr30.c
@@ -343,7 +343,7 @@ fr30_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned int i;
 
   for (i = sizeof (fr30_reloc_map) / sizeof (fr30_reloc_map[0]);
-       --i;)
+       i--;)
     if (fr30_reloc_map [i].bfd_reloc_val == code)
       return & fr30_elf_howto_table [fr30_reloc_map[i].fr30_reloc_val];
 
@@ -375,7 +375,11 @@ fr30_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_FR30_max);
+  if (r_type >= (unsigned int) R_FR30_max)
+    {
+      _bfd_error_handler (_("%B: invalid FR30 reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = & fr30_elf_howto_table [r_type];
 }
 
diff --git a/bfd/elf32-frv.c b/bfd/elf32-frv.c
index 714399a..5c291c5 100644
--- a/bfd/elf32-frv.c
+++ b/bfd/elf32-frv.c
@@ -2557,6 +2557,11 @@ frv_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
       break;
 
     default:
+      if (r_type >= (unsigned int) R_FRV_max)
+	{
+	  _bfd_error_handler (_("%B: invalid FRV reloc number: %d"), abfd, r_type);
+	  r_type = 0;
+	}
       cache_ptr->howto = & elf32_frv_howto_table [r_type];
       break;
     }
diff --git a/bfd/elf32-i370.c b/bfd/elf32-i370.c
index 3c32190..d7c3885 100644
--- a/bfd/elf32-i370.c
+++ b/bfd/elf32-i370.c
@@ -294,12 +294,21 @@ i370_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
 			arelent *cache_ptr,
 			Elf_Internal_Rela *dst)
 {
+  unsigned int r_type;
+
   if (!i370_elf_howto_table[ R_I370_ADDR31 ])
     /* Initialize howto table.  */
     i370_elf_howto_init ();
 
-  BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_I370_max);
-  cache_ptr->howto = i370_elf_howto_table[ELF32_R_TYPE (dst->r_info)];
+  r_type = ELF32_R_TYPE (dst->r_info);
+  if (r_type >= R_I370_max)
+    {
+      (*_bfd_error_handler) (_("%B: unrecognised I370 reloc number: %d"),
+			     abfd, r_type);
+      bfd_set_error (bfd_error_bad_value);
+      r_type = R_I370_NONE;
+    }
+  cache_ptr->howto = i370_elf_howto_table[r_type];
 }
 
 /* Hack alert --  the following several routines look generic to me ...
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 1d463e5..c71ef04 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -379,7 +379,9 @@ elf_i386_rtype_to_howto (bfd *abfd, unsigned r_type)
 			     abfd, (int) r_type);
       indx = R_386_NONE;
     }
-  BFD_ASSERT (elf_howto_table [indx].type == r_type);
+  /* PR 17512: file: 0f67f69d.  */
+  if (elf_howto_table [indx].type != r_type)
+    return NULL;
   return &elf_howto_table[indx];
 }
 
@@ -5015,7 +5017,7 @@ bad_return:
   if (plt_sym_val == NULL)
     goto bad_return;
 
-  for (i = 0; i < count; i++, p++)
+  for (i = 0; i < count; i++)
     plt_sym_val[i] = -1;
 
   plt_offset = bed->plt->plt_entry_size;
@@ -5024,6 +5026,10 @@ bad_return:
     {
       long reloc_index;
 
+      /* Skip unknown relocation.  PR 17512: file: bc9d6cf5.  */
+      if (p->howto == NULL)
+	continue;
+
       if (p->howto->type != R_386_JUMP_SLOT
 	  && p->howto->type != R_386_IRELATIVE)
 	continue;
diff --git a/bfd/elf32-i960.c b/bfd/elf32-i960.c
index 5030347..78a7ae9 100644
--- a/bfd/elf32-i960.c
+++ b/bfd/elf32-i960.c
@@ -132,7 +132,12 @@ elf32_i960_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
   enum elf_i960_reloc_type type;
 
   type = (enum elf_i960_reloc_type) ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (type < R_960_max);
+  /* PR 17521: file: 9609b8d6.  */
+  if (type >= R_960_max)
+    {
+      _bfd_error_handler (_("%B: invalid i960 reloc number: %d"), abfd, type);
+      type = 0;
+    }
 
   cache_ptr->howto = &elf_howto_table[(int) type];
 }
diff --git a/bfd/elf32-ip2k.c b/bfd/elf32-ip2k.c
index df12490..b2bf343 100644
--- a/bfd/elf32-ip2k.c
+++ b/bfd/elf32-ip2k.c
@@ -1239,6 +1239,11 @@ ip2k_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
+  if (r_type >= (unsigned int) R_IP2K_max)
+    {
+      _bfd_error_handler (_("%B: invalid IP2K reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = & ip2k_elf_howto_table [r_type];
 }
 
diff --git a/bfd/elf32-iq2000.c b/bfd/elf32-iq2000.c
index fc87891..7282651 100644
--- a/bfd/elf32-iq2000.c
+++ b/bfd/elf32-iq2000.c
@@ -435,6 +435,11 @@ iq2000_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
       break;
 
     default:
+      if (r_type >= (unsigned int) R_IQ2000_max)
+	{
+	  _bfd_error_handler (_("%B: invalid IQ2000 reloc number: %d"), abfd, r_type);
+	  r_type = 0;
+	}
       cache_ptr->howto = & iq2000_elf_howto_table [r_type];
       break;
     }
diff --git a/bfd/elf32-lm32.c b/bfd/elf32-lm32.c
index 0ff5929..cb834d2 100644
--- a/bfd/elf32-lm32.c
+++ b/bfd/elf32-lm32.c
@@ -588,7 +588,11 @@ lm32_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_LM32_max);
+  if (r_type >= (unsigned int) R_LM32_max)
+    {
+      _bfd_error_handler (_("%B: invalid LM32 reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = &lm32_elf_howto_table[r_type];
 }
 
diff --git a/bfd/elf32-m32c.c b/bfd/elf32-m32c.c
index be88738..7370103 100644
--- a/bfd/elf32-m32c.c
+++ b/bfd/elf32-m32c.c
@@ -266,7 +266,7 @@ m32c_reloc_type_lookup
 {
   unsigned int i;
 
-  for (i = ARRAY_SIZE (m32c_reloc_map); --i;)
+  for (i = ARRAY_SIZE (m32c_reloc_map); i--;)
     if (m32c_reloc_map [i].bfd_reloc_val == code)
       return & m32c_elf_howto_table [m32c_reloc_map[i].m32c_reloc_val];
 
@@ -299,7 +299,11 @@ m32c_info_to_howto_rela
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_M32C_max);
+  if (r_type >= (unsigned int) R_M32C_max)
+    {
+      _bfd_error_handler (_("%B: invalid M32C reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = & m32c_elf_howto_table [r_type];
 }
 
diff --git a/bfd/elf32-m32r.c b/bfd/elf32-m32r.c
index 951d43e..30d3a45 100644
--- a/bfd/elf32-m32r.c
+++ b/bfd/elf32-m32r.c
@@ -1280,7 +1280,11 @@ m32r_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (ELF32_R_TYPE(dst->r_info) <= (unsigned int) R_M32R_GNU_VTENTRY);
+  if (r_type > (unsigned int) R_M32R_GNU_VTENTRY)
+    {
+      _bfd_error_handler (_("%B: invalid M32R reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = &m32r_elf_howto_table[r_type];
 }
 
@@ -4079,4 +4083,3 @@ m32r_elf_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
 #define elf32_bed               elf32_m32r_lin_bed
 
 #include "elf32-target.h"
-
diff --git a/bfd/elf32-m68hc11.c b/bfd/elf32-m68hc11.c
index 00a77d0..f0a7e7e 100644
--- a/bfd/elf32-m68hc11.c
+++ b/bfd/elf32-m68hc11.c
@@ -384,7 +384,11 @@ m68hc11_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_M68HC11_max);
+  if (r_type >= (unsigned int) R_M68HC11_max)
+    {
+      _bfd_error_handler (_("%B: invalid M68HC11 reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
 }
 
diff --git a/bfd/elf32-m68hc12.c b/bfd/elf32-m68hc12.c
index fd13354..488e338 100644
--- a/bfd/elf32-m68hc12.c
+++ b/bfd/elf32-m68hc12.c
@@ -504,7 +504,11 @@ m68hc11_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_M68HC11_max);
+  if (r_type >= (unsigned int) R_M68HC11_max)
+    {
+      _bfd_error_handler (_("%B: invalid M68HC12 reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
 }
 
diff --git a/bfd/elf32-mcore.c b/bfd/elf32-mcore.c
index 3d37530..839812e 100644
--- a/bfd/elf32-mcore.c
+++ b/bfd/elf32-mcore.c
@@ -340,13 +340,22 @@ mcore_elf_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED,
 			 arelent * cache_ptr,
 			 Elf_Internal_Rela * dst)
 {
+  unsigned int r_type;
+
   if (! mcore_elf_howto_table [R_MCORE_PCRELIMM8BY4])
     /* Initialize howto table if needed.  */
     mcore_elf_howto_init ();
 
-  BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_MCORE_max);
+  r_type = ELF32_R_TYPE (dst->r_info);
+  if (r_type >= R_MCORE_max)
+    {
+      (*_bfd_error_handler) (_("%B: unrecognised MCore reloc number: %d"),
+			     abfd, r_type);
+      bfd_set_error (bfd_error_bad_value);
+      r_type = R_MCORE_NONE;
+    }
 
-  cache_ptr->howto = mcore_elf_howto_table [ELF32_R_TYPE (dst->r_info)];
+  cache_ptr->howto = mcore_elf_howto_table [r_type];
 }
 
 /* The RELOCATE_SECTION function is called by the ELF backend linker
diff --git a/bfd/elf32-mep.c b/bfd/elf32-mep.c
index ac51df4..4aee881 100644
--- a/bfd/elf32-mep.c
+++ b/bfd/elf32-mep.c
@@ -400,6 +400,11 @@ mep_info_to_howto_rela
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
+  if (r_type >= R_MEP_max)
+    {
+      _bfd_error_handler (_("%B: invalid MEP reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = & mep_elf_howto_table [r_type];
 }
 
diff --git a/bfd/elf32-metag.c b/bfd/elf32-metag.c
index 209baed..9c14880 100644
--- a/bfd/elf32-metag.c
+++ b/bfd/elf32-metag.c
@@ -896,7 +896,11 @@ metag_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_METAG_MAX);
+  if (r_type >= (unsigned int) R_METAG_MAX)
+    {
+      _bfd_error_handler (_("%B: invalid METAG reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = & elf_metag_howto_table [r_type];
 }
 
diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c
index 64487af..2fb1b68 100644
--- a/bfd/elf32-microblaze.c
+++ b/bfd/elf32-microblaze.c
@@ -643,13 +643,22 @@ microblaze_elf_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED,
 			      arelent * cache_ptr,
 			      Elf_Internal_Rela * dst)
 {
+  unsigned int r_type;
+
   if (!microblaze_elf_howto_table [R_MICROBLAZE_32])
     /* Initialize howto table if needed.  */
     microblaze_elf_howto_init ();
 
-  BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_MICROBLAZE_max);
+  r_type = ELF32_R_TYPE (dst->r_info);
+  if (r_type >= R_MICROBLAZE_max)
+    {
+      (*_bfd_error_handler) (_("%B: unrecognised MicroBlaze reloc number: %d"),
+			     abfd, r_type);
+      bfd_set_error (bfd_error_bad_value);
+      r_type = R_MICROBLAZE_NONE;
+    }
 
-  cache_ptr->howto = microblaze_elf_howto_table [ELF32_R_TYPE (dst->r_info)];
+  cache_ptr->howto = microblaze_elf_howto_table [r_type];
 }
 
 /* Microblaze ELF local labels start with 'L.' or '$L', not '.L'.  */
diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c
index af661c4..390fd9b 100644
--- a/bfd/elf32-mips.c
+++ b/bfd/elf32-mips.c
@@ -2204,7 +2204,12 @@ mips_elf32_rtype_to_howto (unsigned int r_type,
 	return &elf_micromips_howto_table_rel[r_type - R_MICROMIPS_min];
       if (r_type >= R_MIPS16_min && r_type < R_MIPS16_max)
         return &elf_mips16_howto_table_rel[r_type - R_MIPS16_min];
-      BFD_ASSERT (r_type < (unsigned int) R_MIPS_max);
+      if (r_type >= (unsigned int) R_MIPS_max)
+	{
+	  (*_bfd_error_handler) (_("Unrecognised MIPS reloc number: %d"), r_type);
+	  bfd_set_error (bfd_error_bad_value);
+	  r_type = R_MIPS_NONE;
+	}
       return &elf_mips_howto_table_rel[r_type];
     }
 }
diff --git a/bfd/elf32-moxie.c b/bfd/elf32-moxie.c
index fab19d8..85952d1 100644
--- a/bfd/elf32-moxie.c
+++ b/bfd/elf32-moxie.c
@@ -99,7 +99,7 @@ moxie_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned int i;
 
   for (i = sizeof (moxie_reloc_map) / sizeof (moxie_reloc_map[0]);
-       --i;)
+       i--;)
     if (moxie_reloc_map [i].bfd_reloc_val == code)
       return & moxie_elf_howto_table [moxie_reloc_map[i].moxie_reloc_val];
 
@@ -131,7 +131,11 @@ moxie_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_MOXIE_max);
+  if (r_type >= (unsigned int) R_MOXIE_max)
+    {
+      _bfd_error_handler (_("%B: invalid Moxie reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = & moxie_elf_howto_table [r_type];
 }
 
diff --git a/bfd/elf32-msp430.c b/bfd/elf32-msp430.c
index 593cd81..667ebd4 100644
--- a/bfd/elf32-msp430.c
+++ b/bfd/elf32-msp430.c
@@ -617,12 +617,20 @@ msp430_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
 
   if (uses_msp430x_relocs (abfd))
     {
-      BFD_ASSERT (r_type < (unsigned int) R_MSP430x_max);
+      if (r_type >= (unsigned int) R_MSP430x_max)
+	{
+	  _bfd_error_handler (_("%B: invalid MSP430X reloc number: %d"), abfd, r_type);
+	  r_type = 0;
+	}
       cache_ptr->howto = elf_msp430x_howto_table + r_type;
       return;
     }
 
-  BFD_ASSERT (r_type < (unsigned int) R_MSP430_max);
+  if (r_type >= (unsigned int) R_MSP430_max)
+    {
+      _bfd_error_handler (_("%B: invalid MSP430 reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = &elf_msp430_howto_table[r_type];
 }
 
diff --git a/bfd/elf32-mt.c b/bfd/elf32-mt.c
index 5ae4e19..db11cf8 100644
--- a/bfd/elf32-mt.c
+++ b/bfd/elf32-mt.c
@@ -236,6 +236,11 @@ mt_info_to_howto_rela
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
+  if (r_type >= (unsigned int) R_MT_max)
+    {
+      _bfd_error_handler (_("%B: invalid MT reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = & mt_elf_howto_table [r_type];
 }
 
diff --git a/bfd/elf32-nds32.c b/bfd/elf32-nds32.c
index dbfa85e..f073621 100644
--- a/bfd/elf32-nds32.c
+++ b/bfd/elf32-nds32.c
@@ -2965,7 +2965,11 @@ nds32_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
   enum elf_nds32_reloc_type r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (ELF32_R_TYPE (dst->r_info) <= R_NDS32_GNU_VTENTRY);
+  if (r_type > R_NDS32_GNU_VTENTRY)
+    {
+      _bfd_error_handler (_("%B: invalid NDS32 reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = bfd_elf32_bfd_reloc_type_table_lookup (r_type);
 }
 
diff --git a/bfd/elf32-or1k.c b/bfd/elf32-or1k.c
index fd8fb83..91d62d3 100644
--- a/bfd/elf32-or1k.c
+++ b/bfd/elf32-or1k.c
@@ -704,7 +704,7 @@ or1k_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
 {
   unsigned int i;
 
-  for (i = ARRAY_SIZE (or1k_reloc_map); --i;)
+  for (i = ARRAY_SIZE (or1k_reloc_map); i--;)
     if (or1k_reloc_map[i].bfd_reloc_val == code)
       return & or1k_elf_howto_table[or1k_reloc_map[i].or1k_reloc_val];
 
@@ -738,7 +738,11 @@ or1k_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_OR1K_max);
+  if (r_type >= (unsigned int) R_OR1K_max)
+    {
+      _bfd_error_handler (_("%B: invalid OR1K reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = & or1k_elf_howto_table[r_type];
 }
 
diff --git a/bfd/elf32-pj.c b/bfd/elf32-pj.c
index 4a1655e..caca721 100644
--- a/bfd/elf32-pj.c
+++ b/bfd/elf32-pj.c
@@ -319,7 +319,13 @@ pj_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
 
   r = ELF32_R_TYPE (dst->r_info);
 
-  BFD_ASSERT (r < (unsigned int) R_PJ_max);
+  if (r >= R_PJ_max)
+    {
+      (*_bfd_error_handler) (_("%B: unrecognised PicoJava reloc number: %d"),
+			     abfd, r);
+      bfd_set_error (bfd_error_bad_value);
+      r = R_PJ_NONE;
+    }
 
   cache_ptr->howto = &pj_elf_howto_table[r];
 }
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index af3c10c..5a37fdb 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -2019,19 +2019,28 @@ ppc_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
 		       arelent *cache_ptr,
 		       Elf_Internal_Rela *dst)
 {
+  unsigned int r_type;
+
   /* Initialize howto table if not already done.  */
   if (!ppc_elf_howto_table[R_PPC_ADDR32])
     ppc_elf_howto_init ();
 
-  BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_PPC_max);
-  cache_ptr->howto = ppc_elf_howto_table[ELF32_R_TYPE (dst->r_info)];
+  r_type = ELF32_R_TYPE (dst->r_info);
+  if (r_type >= R_PPC_max)
+    {
+      (*_bfd_error_handler) (_("%B: unrecognised PPC reloc number: %d"),
+			     abfd, r_type);
+      bfd_set_error (bfd_error_bad_value);
+      r_type = R_PPC_NONE;
+    }
+  cache_ptr->howto = ppc_elf_howto_table[r_type];
 
   /* Just because the above assert didn't trigger doesn't mean that
      ELF32_R_TYPE (dst->r_info) is necessarily a valid relocation.  */
   if (!cache_ptr->howto)
     {
       (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
-                             abfd, ELF32_R_TYPE (dst->r_info));
+                             abfd, r_type);
       bfd_set_error (bfd_error_bad_value);
 
       cache_ptr->howto = ppc_elf_howto_table[R_PPC_NONE];
diff --git a/bfd/elf32-rl78.c b/bfd/elf32-rl78.c
index 3574ed3..c07b237 100644
--- a/bfd/elf32-rl78.c
+++ b/bfd/elf32-rl78.c
@@ -246,7 +246,7 @@ rl78_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
   if (code == BFD_RELOC_RL78_32_OP)
     return rl78_elf_howto_table + R_RL78_DIR32;
 
-  for (i = ARRAY_SIZE (rl78_reloc_map); --i;)
+  for (i = ARRAY_SIZE (rl78_reloc_map); i--;)
     if (rl78_reloc_map [i].bfd_reloc_val == code)
       return rl78_elf_howto_table + rl78_reloc_map[i].rl78_reloc_val;
 
@@ -276,7 +276,11 @@ rl78_info_to_howto_rela (bfd *               abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_RL78_max);
+  if (r_type >= (unsigned int) R_RL78_max)
+    {
+      _bfd_error_handler (_("%B: invalid RL78 reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = rl78_elf_howto_table + r_type;
 }
 
diff --git a/bfd/elf32-rx.c b/bfd/elf32-rx.c
index 3073b32..9f78a19 100644
--- a/bfd/elf32-rx.c
+++ b/bfd/elf32-rx.c
@@ -277,7 +277,7 @@ rx_reloc_type_lookup (bfd *                    abfd ATTRIBUTE_UNUSED,
   if (code == BFD_RELOC_RX_32_OP)
     return rx_elf_howto_table + R_RX_DIR32;
 
-  for (i = ARRAY_SIZE (rx_reloc_map); --i;)
+  for (i = ARRAY_SIZE (rx_reloc_map); i--;)
     if (rx_reloc_map [i].bfd_reloc_val == code)
       return rx_elf_howto_table + rx_reloc_map[i].rx_reloc_val;
 
@@ -307,7 +307,11 @@ rx_info_to_howto_rela (bfd *               abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_RX_max);
+  if (r_type >= (unsigned int) R_RX_max)
+    {
+      _bfd_error_handler (_("%B: invalid RX reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = rx_elf_howto_table + r_type;
 }
 
diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c
index ecb8c17..7027bdf 100644
--- a/bfd/elf32-sh.c
+++ b/bfd/elf32-sh.c
@@ -479,13 +479,19 @@ sh_elf_info_to_howto (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst)
 
   r = ELF32_R_TYPE (dst->r_info);
 
-  BFD_ASSERT (r < (unsigned int) R_SH_max);
-  BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC || r > R_SH_LAST_INVALID_RELOC);
-  BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC_2 || r > R_SH_LAST_INVALID_RELOC_2);
-  BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC_3 || r > R_SH_LAST_INVALID_RELOC_3);
-  BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC_4 || r > R_SH_LAST_INVALID_RELOC_4);
-  BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC_5 || r > R_SH_LAST_INVALID_RELOC_5);
-  BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC_6 || r > R_SH_LAST_INVALID_RELOC_6);
+  if (r >= R_SH_max
+      || (r >= R_SH_FIRST_INVALID_RELOC   && r <= R_SH_LAST_INVALID_RELOC)
+      || (r >= R_SH_FIRST_INVALID_RELOC_2 && r <= R_SH_LAST_INVALID_RELOC_2)
+      || (r >= R_SH_FIRST_INVALID_RELOC_3 && r <= R_SH_LAST_INVALID_RELOC_3)
+      || (r >= R_SH_FIRST_INVALID_RELOC_4 && r <= R_SH_LAST_INVALID_RELOC_4)
+      || (r >= R_SH_FIRST_INVALID_RELOC_5 && r <= R_SH_LAST_INVALID_RELOC_5)
+      || (r >= R_SH_FIRST_INVALID_RELOC_6 && r <= R_SH_LAST_INVALID_RELOC_6))
+    {
+      (*_bfd_error_handler) (_("%B: unrecognised SH reloc number: %d"),
+			     abfd, r);
+      bfd_set_error (bfd_error_bad_value);
+      r = R_SH_NONE;
+    }
 
   cache_ptr->howto = get_howto_table (abfd) + r;
 }
diff --git a/bfd/elf32-spu.c b/bfd/elf32-spu.c
index ce7001d..10c683f 100644
--- a/bfd/elf32-spu.c
+++ b/bfd/elf32-spu.c
@@ -153,7 +153,14 @@ spu_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
   enum elf_spu_reloc_type r_type;
 
   r_type = (enum elf_spu_reloc_type) ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < R_SPU_max);
+  /* PR 17512: file: 90c2a92e.  */
+  if (r_type >= R_SPU_max)
+    {
+      (*_bfd_error_handler) (_("%B: unrecognised SPU reloc number: %d"),
+			     abfd, r_type);
+      bfd_set_error (bfd_error_bad_value);
+      r_type = R_SPU_NONE;
+    }
   cache_ptr->howto = &elf_howto_table[(int) r_type];
 }
 
@@ -163,7 +170,7 @@ spu_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 {
   enum elf_spu_reloc_type r_type = spu_elf_bfd_to_reloc_type (code);
 
-  if (r_type == R_SPU_NONE)
+  if (r_type == (enum elf_spu_reloc_type) -1)
     return NULL;
 
   return elf_howto_table + r_type;
diff --git a/bfd/elf32-v850.c b/bfd/elf32-v850.c
index 7f69acb..c6fa72e 100644
--- a/bfd/elf32-v850.c
+++ b/bfd/elf32-v850.c
@@ -494,7 +494,7 @@ v850_elf_perform_relocation (bfd *abfd,
     {
     default:
 #ifdef DEBUG
-      fprintf (stderr, "reloc number %d not recognised\n", r_type);
+      fprintf (stderr, "%B: reloc number %d not recognised\n", abfd, r_type);
 #endif
       return bfd_reloc_notsupported;
 
@@ -1896,7 +1896,11 @@ v850_elf_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_V850_max);
+  if (r_type >= (unsigned int) R_V850_max)
+    {
+      _bfd_error_handler (_("%B: invalid V850 reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = &v850_elf_howto_table[r_type];
 }
 
@@ -1910,7 +1914,11 @@ v850_elf_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_V850_max);
+  if (r_type >= (unsigned int) R_V850_max)
+    {
+      _bfd_error_handler (_("%B: invalid V850 reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = &v850_elf_howto_table[r_type];
 }
 
@@ -2139,7 +2147,7 @@ v850_elf_final_link_relocate (reloc_howto_type *howto,
 
     default:
 #ifdef DEBUG
-      fprintf (stderr, "reloc number %d not recognised\n", r_type);
+      fprintf (stderr, "%B: reloc number %d not recognised\n", input_bfd, r_type);
 #endif
       return bfd_reloc_notsupported;
     }
diff --git a/bfd/elf32-vax.c b/bfd/elf32-vax.c
index 943b230..df73ef5 100644
--- a/bfd/elf32-vax.c
+++ b/bfd/elf32-vax.c
@@ -280,11 +280,19 @@ static reloc_howto_type howto_table[] = {
 };
 
 static void
-rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
-		Elf_Internal_Rela *dst)
+rtype_to_howto (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst)
 {
-  BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_VAX_max);
-  cache_ptr->howto = &howto_table[ELF32_R_TYPE(dst->r_info)];
+  unsigned int r_type;
+
+  r_type = ELF32_R_TYPE (dst->r_info);
+  if (r_type >= R_VAX_max)
+    {
+      (*_bfd_error_handler) (_("%B: unrecognised VAX reloc number: %d"),
+			     abfd, r_type);
+      bfd_set_error (bfd_error_bad_value);
+      r_type = R_VAX_NONE;
+    }
+  cache_ptr->howto = &howto_table[r_type];
 }
 
 #define elf_info_to_howto rtype_to_howto
diff --git a/bfd/elf32-xgate.c b/bfd/elf32-xgate.c
index 1ee0ce4..e2294ef 100644
--- a/bfd/elf32-xgate.c
+++ b/bfd/elf32-xgate.c
@@ -422,7 +422,11 @@ xgate_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT(r_type < (unsigned int) R_XGATE_max);
+  if (r_type >= (unsigned int) R_XGATE_max)
+    {
+      _bfd_error_handler (_("%B: invalid XGate reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = &elf_xgate_howto_table[r_type];
 }
 
diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
index 09476f2..50d0fc4 100644
--- a/bfd/elf32-xtensa.c
+++ b/bfd/elf32-xtensa.c
@@ -479,7 +479,11 @@ elf_xtensa_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
 {
   unsigned int r_type = ELF32_R_TYPE (dst->r_info);
 
-  BFD_ASSERT (r_type < (unsigned int) R_XTENSA_max);
+  if (r_type >= (unsigned int) R_XTENSA_max)
+    {
+      _bfd_error_handler (_("%B: invalid XTENSA reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = &elf_howto_table[r_type];
 }
 
diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c
index 042dae3..8f8cf7b 100644
--- a/bfd/elf64-alpha.c
+++ b/bfd/elf64-alpha.c
@@ -1105,7 +1105,14 @@ elf64_alpha_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
 			   Elf_Internal_Rela *dst)
 {
   unsigned r_type = ELF64_R_TYPE(dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_ALPHA_max);
+
+  if (r_type >= R_ALPHA_max)
+    {
+      (*_bfd_error_handler) (_("%B: unrecognised Alpha reloc number: %d"),
+			     abfd, r_type);
+      bfd_set_error (bfd_error_bad_value);
+      r_type = R_ALPHA_NONE;
+    }
   cache_ptr->howto = &elf64_alpha_howto_table[r_type];
 }
 
diff --git a/bfd/elf64-mmix.c b/bfd/elf64-mmix.c
index 585dad9..b6f4232 100644
--- a/bfd/elf64-mmix.c
+++ b/bfd/elf64-mmix.c
@@ -1259,7 +1259,11 @@ mmix_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned int r_type;
 
   r_type = ELF64_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_MMIX_max);
+  if (r_type >= (unsigned int) R_MMIX_max)
+    {
+      _bfd_error_handler (_("%B: invalid MMIX reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = &elf_mmix_howto_table[r_type];
 }
 
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 327004c..fde5215 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -3289,6 +3289,8 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
 	    }
 	}
 
+      if (size == 0)
+	goto done;
       s = *ret = bfd_malloc (size);
       if (s == NULL)
 	{
@@ -3460,6 +3462,8 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
 	    }
 	}
 
+      if (size == 0)
+	goto free_contents_and_exit;
       s = *ret = bfd_malloc (size);
       if (s == NULL)
 	goto free_contents_and_exit;
@@ -5943,6 +5947,10 @@ opd_entry_value (asection *opd_sec,
 	  ppc64_elf_tdata (opd_bfd)->opd.contents = contents;
 	}
 
+      /* PR 17512: file: 64b9dfbb.  */
+      if (offset + 7 >= opd_sec->size || offset + 7 < offset)
+	return (bfd_vma) -1;
+
       val = bfd_get_64 (opd_bfd, contents + offset);
       if (code_sec != NULL)
 	{
@@ -5978,10 +5986,12 @@ opd_entry_value (asection *opd_sec,
   relocs = ppc64_elf_tdata (opd_bfd)->opd.relocs;
   if (relocs == NULL)
     relocs = _bfd_elf_link_read_relocs (opd_bfd, opd_sec, NULL, NULL, TRUE);
+  /* PR 17512: file: df8e1fd6.  */
+  if (relocs == NULL)
+    return (bfd_vma) -1;
 
   /* Go find the opd reloc at the sym address.  */
   lo = relocs;
-  BFD_ASSERT (lo != NULL);
   hi = lo + opd_sec->reloc_count - 1; /* ignore last reloc */
   val = (bfd_vma) -1;
   while (lo < hi)
@@ -15305,4 +15315,3 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
 #define elf64_bed	elf64_powerpc_fbsd_bed
 
 #include "elf64-target.h"
-
diff --git a/bfd/elf64-sparc.c b/bfd/elf64-sparc.c
index eeb94a9..0dcd14a 100644
--- a/bfd/elf64-sparc.c
+++ b/bfd/elf64-sparc.c
@@ -97,7 +97,9 @@ elf64_sparc_slurp_one_reloc_table (bfd *abfd, asection *asect,
       else
 	relent->address = rela.r_offset - asect->vma;
 
-      if (ELF64_R_SYM (rela.r_info) == STN_UNDEF)
+      if (ELF64_R_SYM (rela.r_info) == STN_UNDEF
+	  /* PR 17512: file: 996185f8.  */
+	  || ELF64_R_SYM (rela.r_info) > bfd_get_symcount (abfd))
 	relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
       else
 	{
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 08585de..e8305f8 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -302,7 +302,7 @@ elf_x86_64_reloc_type_lookup (bfd *abfd,
 	return elf_x86_64_rtype_to_howto (abfd,
 					  x86_64_reloc_map[i].elf_reloc_val);
     }
-  return 0;
+  return NULL;
 }
 
 static reloc_howto_type *
@@ -5410,7 +5410,7 @@ bad_return:
   if (plt_sym_val == NULL)
     goto bad_return;
 
-  for (i = 0; i < count; i++, p++)
+  for (i = 0; i < count; i++)
     plt_sym_val[i] = -1;
 
   plt_offset = bed->plt_entry_size;
@@ -5419,6 +5419,10 @@ bad_return:
     {
       long reloc_index;
 
+      /* Skip unknown relocation.  */
+      if (p->howto == NULL)
+	continue;
+
       if (p->howto->type != R_X86_64_JUMP_SLOT
 	  && p->howto->type != R_X86_64_IRELATIVE)
 	continue;
diff --git a/bfd/elfcode.h b/bfd/elfcode.h
index ec53c3b..d34e18e 100644
--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -1501,7 +1501,9 @@ elf_slurp_reloc_table (bfd *abfd,
       rel_hdr2 = d->rela.hdr;
       reloc_count2 = rel_hdr2 ? NUM_SHDR_ENTRIES (rel_hdr2) : 0;
 
-      BFD_ASSERT (asect->reloc_count == reloc_count + reloc_count2);
+      /* PR 17512: file: 0b4f81b7.  */
+      if (asect->reloc_count != reloc_count + reloc_count2)
+	return FALSE;
       BFD_ASSERT ((rel_hdr && asect->rel_filepos == rel_hdr->sh_offset)
 		  || (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset));
 
diff --git a/bfd/elfn32-mips.c b/bfd/elfn32-mips.c
index d65e11b..cbf0eb7 100644
--- a/bfd/elfn32-mips.c
+++ b/bfd/elfn32-mips.c
@@ -3403,7 +3403,12 @@ mips_elf_n32_rtype_to_howto (unsigned int r_type, bfd_boolean rela_p)
 	  else
 	    return &elf_mips16_howto_table_rel[r_type - R_MIPS16_min];
 	}
-      BFD_ASSERT (r_type < (unsigned int) R_MIPS_max);
+      if (r_type >= R_MIPS_max)
+	{
+	  (*_bfd_error_handler) (_("unrecognised MIPS reloc number: %d"), r_type);
+	  bfd_set_error (bfd_error_bad_value);
+	  r_type = R_MIPS_NONE;
+	}
       if (rela_p)
 	return &elf_mips_howto_table_rela[r_type];
       else
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index a00e228..302e8cb 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -1377,7 +1377,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
 static reloc_howto_type elfNN_aarch64_howto_none =
   HOWTO (R_AARCH64_NONE,	/* type */
 	 0,			/* rightshift */
-	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 3,			/* size (0 = byte, 1 = short, 2 = long) */
 	 0,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
@@ -1431,6 +1431,14 @@ elfNN_aarch64_bfd_reloc_from_type (unsigned int r_type)
   if (r_type == R_AARCH64_NONE || r_type == R_AARCH64_NULL)
     return BFD_RELOC_AARCH64_NONE;
 
+  /* PR 17512: file: b371e70a.  */
+  if (r_type >= R_AARCH64_end)
+    {
+      _bfd_error_handler (_("Invalid AArch64 reloc number: %d"), r_type);
+      bfd_set_error (bfd_error_bad_value);
+      return BFD_RELOC_AARCH64_NONE;
+    }
+
   return BFD_RELOC_AARCH64_RELOC_START + offsets[r_type];
 }
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]