summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2017-07-27 12:04:50 +0100
committerNick Clifton <nickc@redhat.com>2017-07-27 12:04:50 +0100
commit8bdf0be19d2777565a8b1c88347f65d6a4b8c5fc (patch)
tree3837617a722ce5ec26a0e22c0e21169f47b5af0e
parent63d4980d60dd137996fa282ae1df2e3fcb4519ee (diff)
downloadbinutils-gdb-8bdf0be19d2777565a8b1c88347f65d6a4b8c5fc.tar.gz
Fix address violation issues encountered when parsing corrupt binaries.
PR 21840 * mach-o.c (bfd_mach_o_read_symtab_strtab): Fail if the symtab size is -1. * nlmcode.h (nlm_swap_auxiliary_headers_in): Replace assertion with error return. * section.c (bfd_make_section_with_flags): Fail if the name or bfd are NULL. * vms-alpha.c (bfd_make_section_with_flags): Correct computation of end pointer. (evax_bfd_print_emh): Check for invalid string lengths.
-rw-r--r--bfd/ChangeLog13
-rw-r--r--bfd/mach-o.c3
-rw-r--r--bfd/nlmcode.h4
-rw-r--r--bfd/section.c2
-rw-r--r--bfd/vms-alpha.c91
-rw-r--r--bfd/vms-misc.c8
6 files changed, 82 insertions, 39 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index bd50ac56cff..0a4c8526c4d 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,16 @@
+2017-07-27 Nick Clifton <nickc@redhat.com>
+
+ PR 21840
+ * mach-o.c (bfd_mach_o_read_symtab_strtab): Fail if the symtab
+ size is -1.
+ * nlmcode.h (nlm_swap_auxiliary_headers_in): Replace assertion
+ with error return.
+ * section.c (bfd_make_section_with_flags): Fail if the name or bfd
+ are NULL.
+ * vms-alpha.c (bfd_make_section_with_flags): Correct computation
+ of end pointer.
+ (evax_bfd_print_emh): Check for invalid string lengths.
+
2017-07-25 Nick Clifton <nickc@redhat.com>
* po/fr.po: Updated French translation.
diff --git a/bfd/mach-o.c b/bfd/mach-o.c
index 1807391d51b..9fe6326a299 100644
--- a/bfd/mach-o.c
+++ b/bfd/mach-o.c
@@ -3749,6 +3749,9 @@ bfd_mach_o_read_symtab_strtab (bfd *abfd)
}
else
{
+ /* See PR 21840 for a reproducer. */
+ if ((sym->strsize + 1) == 0)
+ return FALSE;
sym->strtab = bfd_alloc (abfd, sym->strsize + 1);
if (sym->strtab == NULL)
return FALSE;
diff --git a/bfd/nlmcode.h b/bfd/nlmcode.h
index 6d6aed02c10..350c83e1208 100644
--- a/bfd/nlmcode.h
+++ b/bfd/nlmcode.h
@@ -351,7 +351,9 @@ nlm_swap_auxiliary_headers_in (bfd *abfd)
bfd_byte *contents;
bfd_byte *p, *pend;
- BFD_ASSERT (hdrLength == 0 && hdr == NULL);
+ /* See PR 21840 for a reproducer. */
+ if (hdrLength != 0 || hdr != NULL)
+ return FALSE;
pos = bfd_tell (abfd);
if (bfd_seek (abfd, dataOffset, SEEK_SET) != 0)
diff --git a/bfd/section.c b/bfd/section.c
index 28eee7f8b3c..811d42a0d02 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -1240,7 +1240,7 @@ bfd_make_section_with_flags (bfd *abfd, const char *name,
struct section_hash_entry *sh;
asection *newsect;
- if (abfd->output_has_begun)
+ if (abfd == NULL || name == NULL || abfd->output_has_begun)
{
bfd_set_error (bfd_error_invalid_operation);
return NULL;
diff --git a/bfd/vms-alpha.c b/bfd/vms-alpha.c
index 610b034ccd0..5595b61e0d0 100644
--- a/bfd/vms-alpha.c
+++ b/bfd/vms-alpha.c
@@ -903,7 +903,7 @@ _bfd_vms_slurp_ehdr (bfd *abfd)
vms_rec = PRIV (recrd.rec);
/* PR 17512: file: 62736583. */
- end = vms_rec + PRIV (recrd.buf_size);
+ end = PRIV (recrd.buf) + PRIV (recrd.buf_size);
vms_debug2 ((2, "HDR/EMH\n"));
@@ -5737,8 +5737,9 @@ evax_bfd_print_emh (FILE *file, unsigned char *rec, unsigned int rec_len)
{
struct vms_emh_common *emh = (struct vms_emh_common *)rec;
unsigned int subtype;
+ int extra;
- subtype = (unsigned)bfd_getl16 (emh->subtyp);
+ subtype = (unsigned) bfd_getl16 (emh->subtyp);
/* xgettext:c-format */
fprintf (file, _(" EMH %u (len=%u): "), subtype, rec_len);
@@ -5749,58 +5750,82 @@ evax_bfd_print_emh (FILE *file, unsigned char *rec, unsigned int rec_len)
fprintf (file, _(" Error: The length is less than the length of an EMH record\n"));
return;
}
-
+ extra = rec_len - sizeof (struct vms_emh_common);
+
switch (subtype)
{
case EMH__C_MHD:
{
- struct vms_emh_mhd *mhd = (struct vms_emh_mhd *)rec;
- const char *name;
+ struct vms_emh_mhd *mhd = (struct vms_emh_mhd *) rec;
+ const char * name;
+ const char * nextname;
+ const char * maxname;
+ /* PR 21840: Check for invalid lengths. */
+ if (rec_len < sizeof (* mhd))
+ {
+ fprintf (file, _(" Error: The record length is less than the size of an EMH_MHD record\n"));
+ return;
+ }
fprintf (file, _("Module header\n"));
fprintf (file, _(" structure level: %u\n"), mhd->strlvl);
fprintf (file, _(" max record size: %u\n"),
- (unsigned)bfd_getl32 (mhd->recsiz));
+ (unsigned) bfd_getl32 (mhd->recsiz));
name = (char *)(mhd + 1);
+ maxname = (char *) rec + rec_len;
+ if (name > maxname - 2)
+ {
+ fprintf (file, _(" Error: The module name is missing\n"));
+ return;
+ }
+ nextname = name + name[0] + 1;
+ if (nextname >= maxname)
+ {
+ fprintf (file, _(" Error: The module name is too long\n"));
+ return;
+ }
fprintf (file, _(" module name : %.*s\n"), name[0], name + 1);
- name += name[0] + 1;
+ name = nextname;
+ if (name > maxname - 2)
+ {
+ fprintf (file, _(" Error: The module version is missing\n"));
+ return;
+ }
+ nextname = name + name[0] + 1;
+ if (nextname >= maxname)
+ {
+ fprintf (file, _(" Error: The module version is too long\n"));
+ return;
+ }
fprintf (file, _(" module version : %.*s\n"), name[0], name + 1);
- name += name[0] + 1;
- fprintf (file, _(" compile date : %.17s\n"), name);
+ name = nextname;
+ if ((maxname - name) < 17 && maxname[-1] != 0)
+ fprintf (file, _(" Error: The compile date is truncated\n"));
+ else
+ fprintf (file, _(" compile date : %.17s\n"), name);
}
break;
+
case EMH__C_LNM:
- {
- fprintf (file, _("Language Processor Name\n"));
- fprintf (file, _(" language name: %.*s\n"),
- (int)(rec_len - sizeof (struct vms_emh_common)),
- (char *)rec + sizeof (struct vms_emh_common));
- }
+ fprintf (file, _("Language Processor Name\n"));
+ fprintf (file, _(" language name: %.*s\n"), extra, (char *)(emh + 1));
break;
+
case EMH__C_SRC:
- {
- fprintf (file, _("Source Files Header\n"));
- fprintf (file, _(" file: %.*s\n"),
- (int)(rec_len - sizeof (struct vms_emh_common)),
- (char *)rec + sizeof (struct vms_emh_common));
- }
+ fprintf (file, _("Source Files Header\n"));
+ fprintf (file, _(" file: %.*s\n"), extra, (char *)(emh + 1));
break;
+
case EMH__C_TTL:
- {
- fprintf (file, _("Title Text Header\n"));
- fprintf (file, _(" title: %.*s\n"),
- (int)(rec_len - sizeof (struct vms_emh_common)),
- (char *)rec + sizeof (struct vms_emh_common));
- }
+ fprintf (file, _("Title Text Header\n"));
+ fprintf (file, _(" title: %.*s\n"), extra, (char *)(emh + 1));
break;
+
case EMH__C_CPR:
- {
- fprintf (file, _("Copyright Header\n"));
- fprintf (file, _(" copyright: %.*s\n"),
- (int)(rec_len - sizeof (struct vms_emh_common)),
- (char *)rec + sizeof (struct vms_emh_common));
- }
+ fprintf (file, _("Copyright Header\n"));
+ fprintf (file, _(" copyright: %.*s\n"), extra, (char *)(emh + 1));
break;
+
default:
fprintf (file, _("unhandled emh subtype %u\n"), subtype);
break;
diff --git a/bfd/vms-misc.c b/bfd/vms-misc.c
index 7497f0224da..91e2ec76c22 100644
--- a/bfd/vms-misc.c
+++ b/bfd/vms-misc.c
@@ -135,8 +135,8 @@ _bfd_hexdump (int level, unsigned char *ptr, int size, int offset)
#endif
-/* Copy sized string (string with fixed size) to new allocated area
- size is string size (size of record) */
+/* Copy sized string (string with fixed size) to new allocated area.
+ Size is string size (size of record). */
char *
_bfd_vms_save_sized_string (unsigned char *str, unsigned int size)
@@ -151,8 +151,8 @@ _bfd_vms_save_sized_string (unsigned char *str, unsigned int size)
return newstr;
}
-/* Copy counted string (string with size at first byte) to new allocated area
- ptr points to size byte on entry */
+/* Copy counted string (string with size at first byte) to new allocated area.
+ PTR points to size byte on entry. */
char *
_bfd_vms_save_counted_string (unsigned char *ptr, unsigned int maxlen)