aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2023-02-17 12:26:13 +1030
committerAlan Modra <amodra@gmail.com>2023-02-17 12:39:10 +1030
commit75092c693dc1325d222d25e0eb3ac7e24b2f16ad (patch)
tree6a705787116ea51c222d191bee0aeb7c28245863
parent999835294779e92ffb1511c20ac37cea4f3a1b4e (diff)
downloadbinutils-75092c693dc1325d222d25e0eb3ac7e24b2f16ad.zip
binutils-75092c693dc1325d222d25e0eb3ac7e24b2f16ad.tar.gz
binutils-75092c693dc1325d222d25e0eb3ac7e24b2f16ad.tar.bz2
Wild pointer reads in _bfd_ecoff_locate_line
* ecofflink.c (mk_fdrtab): Sanity check fdr procedure descriptor pointer and isymBase. Set fdrtab_len after possible discards. Use size_t vars and catch possible size overflows.
-rw-r--r--bfd/ecofflink.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/bfd/ecofflink.c b/bfd/ecofflink.c
index 3521dc8..e902bd5 100644
--- a/bfd/ecofflink.c
+++ b/bfd/ecofflink.c
@@ -1730,8 +1730,8 @@ mk_fdrtab (bfd *abfd,
FDR *fdr_start;
FDR *fdr_end;
bool stabs;
- long len;
- bfd_size_type amt;
+ size_t len;
+ size_t amt;
fdr_start = debug_info->fdr;
fdr_end = fdr_start + debug_info->symbolic_header.ifdMax;
@@ -1739,17 +1739,26 @@ mk_fdrtab (bfd *abfd,
/* First, let's see how long the table needs to be. */
for (len = 0, fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++)
{
- if (fdr_ptr->cpd == 0) /* Skip FDRs that have no PDRs. */
+ /* Sanity check fdr procedure descriptor pointer. */
+ long ipdMax = debug_info->symbolic_header.ipdMax;
+ if (fdr_ptr->ipdFirst >= ipdMax
+ || fdr_ptr->cpd > ipdMax - fdr_ptr->ipdFirst)
+ fdr_ptr->cpd = 0;
+ /* Skip FDRs that have no PDRs. */
+ if (fdr_ptr->cpd == 0)
continue;
++len;
}
/* Now, create and fill in the table. */
- amt = (bfd_size_type) len * sizeof (struct ecoff_fdrtab_entry);
+ if (_bfd_mul_overflow (len, sizeof (struct ecoff_fdrtab_entry), &amt))
+ {
+ bfd_set_error (bfd_error_file_too_big);
+ return false;
+ }
line_info->fdrtab = (struct ecoff_fdrtab_entry*) bfd_zalloc (abfd, amt);
if (line_info->fdrtab == NULL)
return false;
- line_info->fdrtab_len = len;
tab = line_info->fdrtab;
for (fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++)
@@ -1766,6 +1775,10 @@ mk_fdrtab (bfd *abfd,
char *sym_ptr;
SYMR sym;
+ if ((long) ((unsigned long) fdr_ptr->isymBase + 1) <= 0
+ || fdr_ptr->isymBase + 1 >= debug_info->symbolic_header.isymMax)
+ continue;
+
sym_ptr = ((char *) debug_info->external_sym
+ (fdr_ptr->isymBase + 1) * debug_swap->external_sym_size);
(*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym);
@@ -1797,12 +1810,14 @@ mk_fdrtab (bfd *abfd,
tab->fdr = fdr_ptr;
++tab;
}
+ len = tab - line_info->fdrtab;
+ line_info->fdrtab_len = len;
/* Finally, the table is sorted in increasing memory-address order.
The table is mostly sorted already, but there are cases (e.g.,
static functions in include files), where this does not hold.
Use "odump -PFv" to verify... */
- qsort (line_info->fdrtab, (size_t) len,
+ qsort (line_info->fdrtab, len,
sizeof (struct ecoff_fdrtab_entry), cmp_fdrtab_entry);
return true;