diff --git a/bfd/versados.c b/bfd/versados.c index 42bf36c..f731c84 100644 --- a/bfd/versados.c +++ b/bfd/versados.c @@ -85,7 +85,7 @@ typedef struct versados_data_struct tdata_type; #define VDATA(abfd) (abfd->tdata.versados_data) -#define EDATA(abfd, n) (abfd->tdata.versados_data->e[n]) +#define EDATA(abfd, n) (abfd->tdata.versados_data->e[(n) < 0 ? 0 : ((n) >= 16 ? 0 : n)]) #define RDATA(abfd, n) (abfd->tdata.versados_data->rest[n]) struct ext_otr @@ -184,10 +184,17 @@ versados_new_symbol (bfd *abfd, static int get_record (bfd *abfd, union ext_any *ptr) { - if (bfd_bread (&ptr->size, (bfd_size_type) 1, abfd) != 1 - || (bfd_bread ((char *) ptr + 1, (bfd_size_type) ptr->size, abfd) - != ptr->size)) + if (bfd_bread (&ptr->size, (bfd_size_type) 1, abfd) != 1) return 0; + + /* PR 16825: Validate size before reading the record. */ + if (ptr->size >= sizeof (* ptr)) + return 0; + + if (bfd_bread ((char *) ptr + 1, (bfd_size_type) ptr->size, abfd) + != ptr->size) + return 0; + return 1; } @@ -394,7 +401,9 @@ process_otr (bfd *abfd, struct ext_otr *otr, int pass) else for (j = 0; j < sizeinwords * 2; j++) { - contents[dst_idx + (sizeinwords * 2) - j - 1] = val; + /* PR 16825: Prevent out of range writes. */ + if ((dst_idx + (sizeinwords * 2) - j - 1) < EDATA (abfd, otr->esdid - 1).section->size) + contents[dst_idx + (sizeinwords * 2) - j - 1] = val; val >>= 8; } @@ -430,7 +439,7 @@ process_otr (bfd *abfd, struct ext_otr *otr, int pass) else { need_contents = 1; - if (dst_idx < esdid->section->size) + if (dst_idx < (EDATA (abfd, otr->esdid - 1).section->size - 1)) if (pass == 2) { /* Absolute code, comes in 16 bit lumps. */