mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2026-08-27 00:26:02 -04:00
mips-coff: mips_reflo_reloc buffer overflow
Like commit c2cb1bfb90, but for mips-coff. Make the hi reloc list
per-section rather than per-file, since fuzzers can generate objects
with cross-section refs where the hi reloc section data is freed
before the lo relocs are processed.
Also properly sanity check the hi reloc offset.
* libecoff.h (struct ecoff_tdata): Move mips_refhi_list to..
(struct ecoff_section_tdata): ..here.
(ecoff_section_data): Remove unused abfd arg.
* coff-alpha.c (alpha_relocate_section): Update ecoff_section_data.
* coff-mips.c (mips_refhi_reloc): Use bfd_reloc_offset_in_range.
Allocate ecoff_section_data as necessary. Use that instead of
bfd tdata.
(mips_reflo_reloc): Adjust to suit tdata change.
* ecoff.c (_bfd_ecoff_bfd_free_cached_info): Likewise.
This commit is contained in:
parent
6c85ef111b
commit
f4441fd82f
4 changed files with 36 additions and 18 deletions
|
|
@ -1445,7 +1445,7 @@ alpha_relocate_section (bfd *output_bfd,
|
|||
|
||||
/* Make sure we have a section data structure to which we can
|
||||
hang on to the gp value we pick for the section. */
|
||||
lita_sec_data = ecoff_section_data (input_bfd, lita_sec);
|
||||
lita_sec_data = ecoff_section_data (lita_sec);
|
||||
if (lita_sec_data == NULL)
|
||||
{
|
||||
lita_sec_data = bfd_zalloc (input_bfd, sizeof (*lita_sec_data));
|
||||
|
|
|
|||
|
|
@ -460,17 +460,29 @@ mips_refhi_reloc (bfd *abfd,
|
|||
relocation += symbol->section->output_offset;
|
||||
relocation += reloc_entry->addend;
|
||||
|
||||
if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
|
||||
bfd_size_type octet = (reloc_entry->address
|
||||
* OCTETS_PER_BYTE (abfd, input_section));
|
||||
if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
|
||||
input_section, octet))
|
||||
return bfd_reloc_outofrange;
|
||||
|
||||
struct ecoff_section_tdata *sdata = ecoff_section_data (input_section);
|
||||
if (sdata == NULL)
|
||||
{
|
||||
sdata = bfd_zalloc (abfd, sizeof (*sdata));
|
||||
if (sdata == NULL)
|
||||
return bfd_reloc_outofrange;
|
||||
input_section->used_by_bfd = sdata;
|
||||
}
|
||||
|
||||
/* Save the information, and let REFLO do the actual relocation. */
|
||||
n = (struct mips_hi *) bfd_malloc ((bfd_size_type) sizeof *n);
|
||||
n = bfd_malloc (sizeof (*n));
|
||||
if (n == NULL)
|
||||
return bfd_reloc_outofrange;
|
||||
n->addr = (bfd_byte *) data + reloc_entry->address;
|
||||
n->addend = relocation;
|
||||
n->next = ecoff_data (abfd)->mips_refhi_list;
|
||||
ecoff_data (abfd)->mips_refhi_list = n;
|
||||
n->next = sdata->mips_refhi_list;
|
||||
sdata->mips_refhi_list = n;
|
||||
|
||||
if (output_bfd != (bfd *) NULL)
|
||||
reloc_entry->address += input_section->output_offset;
|
||||
|
|
@ -491,11 +503,11 @@ mips_reflo_reloc (bfd *abfd,
|
|||
bfd *output_bfd,
|
||||
char **error_message)
|
||||
{
|
||||
if (ecoff_data (abfd)->mips_refhi_list != NULL)
|
||||
struct ecoff_section_tdata *sdata = ecoff_section_data (input_section);
|
||||
if (sdata != NULL)
|
||||
{
|
||||
struct mips_hi *l;
|
||||
struct mips_hi *l = sdata->mips_refhi_list;
|
||||
|
||||
l = ecoff_data (abfd)->mips_refhi_list;
|
||||
while (l != NULL)
|
||||
{
|
||||
unsigned long insn;
|
||||
|
|
@ -537,8 +549,7 @@ mips_reflo_reloc (bfd *abfd,
|
|||
free (l);
|
||||
l = next;
|
||||
}
|
||||
|
||||
ecoff_data (abfd)->mips_refhi_list = NULL;
|
||||
sdata->mips_refhi_list = NULL;
|
||||
}
|
||||
|
||||
/* Now do the REFLO reloc in the usual way. */
|
||||
|
|
|
|||
15
bfd/ecoff.c
15
bfd/ecoff.c
|
|
@ -117,11 +117,18 @@ _bfd_ecoff_bfd_free_cached_info (bfd *abfd)
|
|||
if (bfd_get_format (abfd) == bfd_object
|
||||
&& (tdata = ecoff_data (abfd)) != NULL)
|
||||
{
|
||||
while (tdata->mips_refhi_list != NULL)
|
||||
for (asection *sec = abfd->sections; sec != NULL; sec = sec->next)
|
||||
{
|
||||
struct mips_hi *ref = tdata->mips_refhi_list;
|
||||
tdata->mips_refhi_list = ref->next;
|
||||
free (ref);
|
||||
struct ecoff_section_tdata *sdata = ecoff_section_data (sec);
|
||||
if (sdata != NULL)
|
||||
{
|
||||
while (sdata->mips_refhi_list != NULL)
|
||||
{
|
||||
struct mips_hi *ref = sdata->mips_refhi_list;
|
||||
sdata->mips_refhi_list = ref->next;
|
||||
free (ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
_bfd_ecoff_free_ecoff_debug_info (&tdata->debug_info);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -153,9 +153,6 @@ typedef struct ecoff_tdata
|
|||
particular ECOFF file. This is not valid until
|
||||
ecoff_compute_section_file_positions is called. */
|
||||
bool rdata_in_text;
|
||||
|
||||
/* Used by coff-mips.c to track REFHI relocs for pairing with REFLO. */
|
||||
struct mips_hi *mips_refhi_list;
|
||||
} ecoff_data_type;
|
||||
|
||||
/* Each canonical asymbol really looks like this. */
|
||||
|
|
@ -201,10 +198,13 @@ struct ecoff_section_tdata
|
|||
we need to keep track of the gp values that we picked for each
|
||||
input .lita section . */
|
||||
bfd_vma gp;
|
||||
|
||||
/* Used by coff-mips.c to track REFHI relocs for pairing with REFLO. */
|
||||
struct mips_hi *mips_refhi_list;
|
||||
};
|
||||
|
||||
/* An accessor macro for the ecoff_section_tdata structure. */
|
||||
#define ecoff_section_data(abfd, sec) \
|
||||
#define ecoff_section_data(sec) \
|
||||
((struct ecoff_section_tdata *) (sec)->used_by_bfd)
|
||||
|
||||
/* ECOFF linker hash table entries. */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue