aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2017-06-19 13:01:57 +0100
committerNick Clifton <nickc@redhat.com>2017-06-19 13:01:57 +0100
commit80053e466b3a8055334b9be9bac7d99e0d617cbe (patch)
tree08f6c962fca058105b37806d90a399c81452a3a8
parent16b7a7199881fa26fc863279bbf08741e5674b5d (diff)
Fix access violation disassembling a corrupt VMS binary.
PR binutils/21611 * vms-alpha.c (_bfd_vms_slurp_eihs): Check for invalid offset before reading the EIHS structure entries.
-rw-r--r--bfd/ChangeLog8
-rw-r--r--bfd/vms-alpha.c27
2 files changed, 28 insertions, 7 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index a900e1ac16..6aa4c9099f 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,6 +1,12 @@
2017-06-19 Nick Clifton <nickc@redhat.com>
- PR 21615
+ PR binutils/21611
+ * vms-alpha.c (_bfd_vms_slurp_eihs): Check for invalid offset
+ before reading the EIHS structure entries.
+
+2017-06-19 Nick Clifton <nickc@redhat.com>
+
+ PR binutils/21615
* vms-alpha.c (_bfd_vms_slurp_egsd): Use unsigned int for
gsd_size. Check that there are enough bytes remaining to read the
type and size of the next egsd. Check that the size of the egsd
diff --git a/bfd/vms-alpha.c b/bfd/vms-alpha.c
index be5c06f648..73f6976325 100644
--- a/bfd/vms-alpha.c
+++ b/bfd/vms-alpha.c
@@ -622,14 +622,29 @@ static bfd_boolean
_bfd_vms_slurp_eihs (bfd *abfd, unsigned int offset)
{
unsigned char *p = PRIV (recrd.rec) + offset;
- unsigned int gstvbn = bfd_getl32 (p + EIHS__L_GSTVBN);
- unsigned int gstsize ATTRIBUTE_UNUSED = bfd_getl32 (p + EIHS__L_GSTSIZE);
- unsigned int dstvbn = bfd_getl32 (p + EIHS__L_DSTVBN);
- unsigned int dstsize = bfd_getl32 (p + EIHS__L_DSTSIZE);
- unsigned int dmtvbn = bfd_getl32 (p + EIHS__L_DMTVBN);
- unsigned int dmtbytes = bfd_getl32 (p + EIHS__L_DMTBYTES);
+ unsigned int gstvbn;
+ unsigned int gstsize ATTRIBUTE_UNUSED;
+ unsigned int dstvbn;
+ unsigned int dstsize;
+ unsigned int dmtvbn;
+ unsigned int dmtbytes;
asection *section;
+ /* PR 21611: Check that offset is valid. */
+ if (offset > PRIV (recrd.rec_size) - (EIHS__L_DMTBYTES + 4))
+ {
+ _bfd_error_handler (_("Unable to read EIHS record at offset %#x"), offset);
+ bfd_set_error (bfd_error_file_truncated);
+ return FALSE;
+ }
+
+ gstvbn = bfd_getl32 (p + EIHS__L_GSTVBN);
+ gstsize = bfd_getl32 (p + EIHS__L_GSTSIZE);
+ dstvbn = bfd_getl32 (p + EIHS__L_DSTVBN);
+ dstsize = bfd_getl32 (p + EIHS__L_DSTSIZE);
+ dmtvbn = bfd_getl32 (p + EIHS__L_DMTVBN);
+ dmtbytes = bfd_getl32 (p + EIHS__L_DMTBYTES);
+
#if VMS_DEBUG
vms_debug (8, "_bfd_vms_slurp_ihs\n");
vms_debug (4, "EIHS record gstvbn %d gstsize %d dstvbn %d dstsize %d dmtvbn %d dmtbytes %d\n",