PR25197, assertion fail coffgen.c

The testcase in this PR triggered "BFD_ASSERT (p2->is_sym)" by
sneakily generating a C_FILE sym whose value pointed into auxents.
The fix then is in the last changed line of this patch, to check
p->is_sym as well as p->u.syment.n_sclass.  The other changes fix
various overflow checks that weren't as solid as they could be.

	PR 25197
	* coffgen.c (coff_find_nearest_line_with_names): Check that C_FILE
	u.syment.n_value does point at another C_FILE sym and not into
	some auxent that happens to look like a C_FILE.  Properly check
	for integer overflow and avoid possible pointer wrap-around.
	Simplify pr17512 checks.
This commit is contained in:
Alan Modra 2019-11-19 11:38:36 +10:30
parent df56ecde8a
commit f14080d440
2 changed files with 19 additions and 15 deletions

View File

@ -1,3 +1,12 @@
2019-11-19 Alan Modra <amodra@gmail.com>
PR 25197
* coffgen.c (coff_find_nearest_line_with_names): Check that C_FILE
u.syment.n_value does point at another C_FILE sym and not into
some auxent that happens to look like a C_FILE. Properly check
for integer overflow and avoid possible pointer wrap-around.
Simplify pr17512 checks.
2019-11-19 Alan Modra <amodra@gmail.com>
PR 25200

View File

@ -1814,10 +1814,11 @@ coff_get_normalized_symtab (bfd *abfd)
if (! _bfd_coff_get_external_symbols (abfd))
return NULL;
size = obj_raw_syment_count (abfd) * sizeof (combined_entry_type);
size = obj_raw_syment_count (abfd);
/* Check for integer overflow. */
if (size < obj_raw_syment_count (abfd))
if (size > (bfd_size_type) -1 / sizeof (combined_entry_type))
return NULL;
size *= sizeof (combined_entry_type);
internal = (combined_entry_type *) bfd_zalloc (abfd, size);
if (internal == NULL && size != 0)
return NULL;
@ -1844,29 +1845,20 @@ coff_get_normalized_symtab (bfd *abfd)
symbol_ptr = internal_ptr;
internal_ptr->is_sym = TRUE;
/* PR 17512: file: 1353-1166-0.004. */
if (symbol_ptr->u.syment.n_sclass == C_FILE
&& symbol_ptr->u.syment.n_numaux > 0
&& raw_src + symesz + symbol_ptr->u.syment.n_numaux
* symesz > raw_end)
{
bfd_release (abfd, internal);
return NULL;
}
for (i = 0;
i < symbol_ptr->u.syment.n_numaux;
i++)
{
internal_ptr++;
raw_src += symesz;
/* PR 17512: Prevent buffer overrun. */
if (internal_ptr >= internal_end)
if (raw_src >= raw_end || internal_ptr >= internal_end)
{
bfd_release (abfd, internal);
return NULL;
}
raw_src += symesz;
bfd_coff_swap_aux_in (abfd, (void *) raw_src,
symbol_ptr->u.syment.n_type,
symbol_ptr->u.syment.n_sclass,
@ -2408,13 +2400,16 @@ coff_find_nearest_line_with_names (bfd *abfd,
maxdiff = offset + sec_vma - p2->u.syment.n_value;
}
if (p->u.syment.n_value >= cof->raw_syment_count)
break;
/* Avoid endless loops on erroneous files by ensuring that
we always move forward in the file. */
if (p >= cof->raw_syments + p->u.syment.n_value)
break;
p = cof->raw_syments + p->u.syment.n_value;
if (p > pend || p->u.syment.n_sclass != C_FILE)
if (!p->is_sym || p->u.syment.n_sclass != C_FILE)
break;
}
}