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.
This commit is contained in:
Nick Clifton 2017-07-27 12:04:50 +01:00
parent 63d4980d60
commit 8bdf0be19d
6 changed files with 82 additions and 39 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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)