]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
PR 33385, Extended Image Header
authorAlan Modra <amodra@gmail.com>
Sun, 7 Sep 2025 22:46:21 +0000 (08:16 +0930)
committerAlan Modra <amodra@gmail.com>
Mon, 8 Sep 2025 12:47:46 +0000 (22:17 +0930)
This modifies some of the PR 21813 fixes, allowing for smaller EIHD.
Not knowing any better, I chose to use EIHD__C_LENGTH as the minimum
length.

include/
* vms/eihd.h (EIHD__C_LENGTH): Comment.
bfd/
* vms-alpha.c (_bfd_vms_slurp_eihd): Remove size check
duplicating that done by the caller of this function.
(alpha_vms_object_p): Allow smaller EIHD.
(evax_bfd_print_image): Likewise.  Don't print fields past
the record size.

bfd/vms-alpha.c
include/vms/eihd.h

index c4b248494ee624f7b1d6acbf45065469cda7c682..09d343762b0eb1db520f33a2dc260d8d5094a8da 100644 (file)
@@ -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;
 }
 
@@ -2841,7 +2830,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))
@@ -8043,6 +8032,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 +8052,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 +8164,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 +8174,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)
     {
index e655cd6dffa6ab90d9eb18869d8ff40c3d4a962d..2b8e1b1212851d7ad19598fe14e2e218c4af2bd2 100644 (file)
@@ -140,6 +140,8 @@ struct vms_eihd
 #define EIHD__Q_SYMVVA         40
 #define EIHD__L_IMGTYPE                52
 
+/* ext_fixup_off field offset.  Some headers may be missing this and
+   following fields.  */
 #define EIHD__C_LENGTH 104
 
 #endif /* _VMS_EIHD_H */