aboutsummaryrefslogtreecommitdiff
path: root/bfd/vms-alpha.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/vms-alpha.c')
-rw-r--r--bfd/vms-alpha.c161
1 files changed, 85 insertions, 76 deletions
diff --git a/bfd/vms-alpha.c b/bfd/vms-alpha.c
index c4b2484..36cdac6 100644
--- a/bfd/vms-alpha.c
+++ b/bfd/vms-alpha.c
@@ -467,21 +467,12 @@ static bool
_bfd_vms_slurp_eihd (bfd *abfd, unsigned int *eisd_offset,
unsigned int *eihs_offset)
{
- unsigned int imgtype, size;
+ unsigned int imgtype;
bfd_vma symvva;
struct vms_eihd *eihd = (struct vms_eihd *)PRIV (recrd.rec);
vms_debug2 ((8, "_bfd_vms_slurp_eihd\n"));
- /* PR 21813: Check for an undersized record. */
- if (PRIV (recrd.buf_size) < sizeof (* eihd))
- {
- _bfd_error_handler (_("corrupt EIHD record - size is too small"));
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
-
- size = bfd_getl32 (eihd->size);
imgtype = bfd_getl32 (eihd->imgtype);
if (imgtype == EIHD__K_EXE || imgtype == EIHD__K_LIM)
@@ -501,10 +492,8 @@ _bfd_vms_slurp_eihd (bfd *abfd, unsigned int *eisd_offset,
*eihs_offset = bfd_getl32 (eihd->symdbgoff);
vms_debug2 ((4, "EIHD size %d imgtype %d symvva 0x%lx eisd %d eihs %d\n",
- size, imgtype, (unsigned long)symvva,
+ PRIV (recrd.rec_size), imgtype, (unsigned long) symvva,
*eisd_offset, *eihs_offset));
- (void) size;
-
return true;
}
@@ -903,65 +892,64 @@ static bool
_bfd_vms_slurp_ehdr (bfd *abfd)
{
unsigned char *ptr;
- unsigned char *vms_rec;
- unsigned char *end;
+ unsigned int len, slen;
int subtype;
- vms_rec = PRIV (recrd.rec);
- /* PR 17512: file: 62736583. */
- end = PRIV (recrd.buf) + PRIV (recrd.buf_size);
-
vms_debug2 ((2, "HDR/EMH\n"));
- subtype = bfd_getl16 (vms_rec + 4);
+ ptr = PRIV (recrd.rec);
+ len = PRIV (recrd.rec_size);
+ if (len < 6)
+ goto fail;
+
+ subtype = bfd_getl16 (ptr + 4);
vms_debug2 ((3, "subtype %d\n", subtype));
+ ptr += 6;
+ len -= 6;
switch (subtype)
{
case EMH__C_MHD:
/* Module header. */
- if (vms_rec + 21 >= end)
- goto fail;
- PRIV (hdr_data).hdr_b_strlvl = vms_rec[6];
- PRIV (hdr_data).hdr_l_arch1 = bfd_getl32 (vms_rec + 8);
- PRIV (hdr_data).hdr_l_arch2 = bfd_getl32 (vms_rec + 12);
- PRIV (hdr_data).hdr_l_recsiz = bfd_getl32 (vms_rec + 16);
- if ((vms_rec + 20 + vms_rec[20] + 1) >= end)
+ if (len < 15)
goto fail;
+ PRIV (hdr_data).hdr_b_strlvl = *ptr;
+ PRIV (hdr_data).hdr_l_arch1 = bfd_getl32 (ptr + 2);
+ PRIV (hdr_data).hdr_l_arch2 = bfd_getl32 (ptr + 6);
+ PRIV (hdr_data).hdr_l_recsiz = bfd_getl32 (ptr + 10);
+ ptr += 14;
+ len -= 14;
PRIV (hdr_data).hdr_t_name
- = _bfd_vms_save_counted_string (abfd, vms_rec + 20, vms_rec[20]);
- ptr = vms_rec + 20 + vms_rec[20] + 1;
- if ((ptr + *ptr + 1) >= end)
+ = _bfd_vms_save_counted_string (abfd, ptr, len);
+ slen = *ptr + 1;
+ if (len <= slen)
goto fail;
+ ptr += slen;
+ len -= slen;
PRIV (hdr_data).hdr_t_version
- = _bfd_vms_save_counted_string (abfd, ptr, *ptr);
- ptr += *ptr + 1;
- if (ptr + 17 >= end)
+ = _bfd_vms_save_counted_string (abfd, ptr, len);
+ slen = *ptr + 1;
+ if (len < slen + 17)
goto fail;
+ ptr += slen;
PRIV (hdr_data).hdr_t_date
= _bfd_vms_save_sized_string (abfd, ptr, 17);
break;
case EMH__C_LNM:
- if (vms_rec + PRIV (recrd.rec_size - 6) > end)
- goto fail;
PRIV (hdr_data).hdr_c_lnm
- = _bfd_vms_save_sized_string (abfd, vms_rec, PRIV (recrd.rec_size - 6));
+ = _bfd_vms_save_sized_string (abfd, ptr, len);
break;
case EMH__C_SRC:
- if (vms_rec + PRIV (recrd.rec_size - 6) > end)
- goto fail;
PRIV (hdr_data).hdr_c_src
- = _bfd_vms_save_sized_string (abfd, vms_rec, PRIV (recrd.rec_size - 6));
+ = _bfd_vms_save_sized_string (abfd, ptr, len);
break;
case EMH__C_TTL:
- if (vms_rec + PRIV (recrd.rec_size - 6) > end)
- goto fail;
PRIV (hdr_data).hdr_c_ttl
- = _bfd_vms_save_sized_string (abfd, vms_rec, PRIV (recrd.rec_size - 6));
+ = _bfd_vms_save_sized_string (abfd, ptr, len);
break;
case EMH__C_CPR:
@@ -1616,37 +1604,43 @@ static bool
image_write (bfd *abfd, unsigned char *ptr, unsigned int size)
{
asection *sec = PRIV (image_section);
- size_t off = PRIV (image_offset);
- /* Check bounds. */
- if (off > sec->size
- || size > sec->size - off)
+ if ((sec->flags & SEC_IN_MEMORY) != 0
+ && sec->contents == NULL)
+ /* Not yet allocated. Just increment size. */
+ ;
+ else
{
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
+ size_t off = PRIV (image_offset);
+ /* Check bounds. */
+ if (off > sec->size
+ || size > sec->size - off)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
#if VMS_DEBUG
- _bfd_vms_debug (8, "image_write from (%p, %d) to (%ld)\n", ptr, size,
- (long) off);
+ _bfd_vms_debug (8, "image_write from (%p, %d) to (%ld)\n", ptr, size,
+ (long) off);
#endif
- if (PRIV (image_section)->contents != NULL)
- memcpy (sec->contents + off, ptr, size);
- else
- {
- unsigned int i;
- for (i = 0; i < size; i++)
- if (ptr[i] != 0)
- {
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- }
-
+ if (sec->contents != NULL)
+ memcpy (sec->contents + off, ptr, size);
+ else
+ {
+ unsigned int i;
+ for (i = 0; i < size; i++)
+ if (ptr[i] != 0)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ }
#if VMS_DEBUG
- _bfd_hexdump (9, ptr, size, 0);
+ _bfd_hexdump (9, ptr, size, 0);
#endif
+ }
PRIV (image_offset) += size;
return true;
@@ -1869,11 +1863,16 @@ alpha_vms_fix_sec_rel (bfd *abfd, struct bfd_link_info *info,
unsigned int rel, bfd_vma vma)
{
asection *sec;
+ unsigned int sec_indx;
if (PRIV (sections) == NULL)
return 0;
- sec = PRIV (sections)[rel & RELC_MASK];
+ sec_indx = rel & RELC_MASK;
+ if (sec_indx >= PRIV (section_count))
+ return 0;
+
+ sec = PRIV (sections)[sec_indx];
if (info)
{
@@ -2660,7 +2659,7 @@ _bfd_vms_slurp_eeom (bfd *abfd)
vms_debug2 ((2, "EEOM\n"));
/* PR 21813: Check for an undersized record. */
- if (PRIV (recrd.buf_size) < sizeof (* eeom))
+ if (PRIV (recrd.rec_size) < 10)
{
_bfd_error_handler (_("corrupt EEOM record - size is too small"));
bfd_set_error (bfd_error_bad_value);
@@ -2677,7 +2676,7 @@ _bfd_vms_slurp_eeom (bfd *abfd)
}
PRIV (eom_data).eom_has_transfer = false;
- if (PRIV (recrd.rec_size) > 10)
+ if (PRIV (recrd.rec_size) >= sizeof (*eeom))
{
PRIV (eom_data).eom_has_transfer = true;
PRIV (eom_data).eom_b_tfrflg = eeom->tfrflg;
@@ -2841,7 +2840,7 @@ alpha_vms_object_p (bfd *abfd)
/* PR 21813: Check for a truncated record. */
/* PR 17512: file: 7d7c57c2. */
- if (PRIV (recrd.rec_size) < sizeof (struct vms_eihd))
+ if (PRIV (recrd.rec_size) < EIHD__C_LENGTH)
goto err_wrong_format;
if (bfd_seek (abfd, 0, SEEK_SET))
@@ -7504,6 +7503,8 @@ evax_bfd_print_dst (struct bfd *abfd, unsigned int dst_size, FILE *file)
/* xgettext:c-format */
fprintf (file, _(" type: %3u, len: %3u (at 0x%08x): "),
type, len, off);
+ /* !!! The length is short by one! */
+ len++;
if (len > dst_size)
len = dst_size;
if (len < sizeof (dsth))
@@ -8043,6 +8044,7 @@ static void
evax_bfd_print_image (bfd *abfd, FILE *file)
{
struct vms_eihd eihd;
+ unsigned int rec_size, size;
const char *name;
unsigned int val;
unsigned int eiha_off;
@@ -8062,15 +8064,17 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
unsigned int eihvn_off;
if (bfd_seek (abfd, 0, SEEK_SET)
- || bfd_read (&eihd, sizeof (eihd), abfd) != sizeof (eihd))
+ || (rec_size = bfd_read (&eihd, sizeof (eihd), abfd)) < EIHD__C_LENGTH)
{
fprintf (file, _("cannot read EIHD\n"));
return;
}
+ size = bfd_getl32 (eihd.size);
/* xgettext:c-format */
fprintf (file, _("EIHD: (size: %u, nbr blocks: %u)\n"),
- (unsigned)bfd_getl32 (eihd.size),
- (unsigned)bfd_getl32 (eihd.hdrblkcnt));
+ size, (unsigned) bfd_getl32 (eihd.hdrblkcnt));
+ if (size > rec_size)
+ size = rec_size;
/* xgettext:c-format */
fprintf (file, _(" majorid: %u, minorid: %u\n"),
(unsigned)bfd_getl32 (eihd.majorid),
@@ -8172,7 +8176,9 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
(unsigned)bfd_getl32 (eihd.symvect_size));
fprintf (file, _(" BPAGE: %u"),
(unsigned)bfd_getl32 (eihd.virt_mem_block_size));
- if (val & (EIHD__M_OMV_READY | EIHD__M_EXT_BIND_SECT))
+ if (size >= (offsetof (struct vms_eihd, noopt_psect_off)
+ + sizeof (eihd.noopt_psect_off))
+ && (val & (EIHD__M_OMV_READY | EIHD__M_EXT_BIND_SECT)))
{
eihef_off = bfd_getl32 (eihd.ext_fixup_off);
eihnp_off = bfd_getl32 (eihd.noopt_psect_off);
@@ -8180,7 +8186,9 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
fprintf (file, _(", ext fixup offset: %u, no_opt psect off: %u"),
eihef_off, eihnp_off);
}
- fprintf (file, _(", alias: %u\n"), (unsigned)bfd_getl16 (eihd.alias));
+ if (size >= offsetof (struct vms_eihd, alias) + sizeof (eihd.alias))
+ fprintf (file, _(", alias: %u"), (unsigned) bfd_getl16 (eihd.alias));
+ fprintf (file, "\n");
if (eihvn_off != 0)
{
@@ -8935,13 +8943,13 @@ alpha_vms_add_fixup_lr (struct bfd_link_info *info ATTRIBUTE_UNUSED,
static bool
alpha_vms_add_lw_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED)
{
- return false;
+ return true;
}
static bool
alpha_vms_add_qw_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED)
{
- return false;
+ return true;
}
static struct bfd_hash_entry *
@@ -9652,6 +9660,7 @@ alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
bfd_vma tfradr = PRIV2 (startbfd, eom_data).eom_l_tfradr;
asection *sec;
+ BFD_ASSERT (ps_idx < PRIV2 (startbfd, section_count));
sec = PRIV2 (startbfd, sections)[ps_idx];
bfd_set_start_address