Fix an illegal memory access when dumping corrupt x86_64 PE unwind data.

PR 24922
	* pei-x86_64.c (pex64_xdata_print_uwd_codes): Add checks before
	reading data from extra records.
This commit is contained in:
Nick Clifton 2019-08-22 14:37:03 +01:00
parent 93d6a337d5
commit 03da31c676
2 changed files with 68 additions and 9 deletions

View File

@ -1,3 +1,9 @@
2019-08-22 Nick Clifton <nickc@redhat.com>
PR 24922
* pei-x86_64.c (pex64_xdata_print_uwd_codes): Add checks before
reading data from extra records.
2019-08-22 Tamar Christina <tamar.christina@arm.com>
PR ld/24601

View File

@ -228,27 +228,41 @@ pex64_xdata_print_uwd_codes (FILE *file, bfd *abfd,
int unexpected = FALSE;
fprintf (file, "\t pc+0x%02x: ", (unsigned int) dta[0]);
switch (PEX64_UNWCODE_CODE (dta[1]))
{
case UWOP_PUSH_NONVOL:
fprintf (file, "push %s", pex_regs[info]);
break;
case UWOP_ALLOC_LARGE:
if (info == 0)
{
tmp = bfd_get_16 (abfd, &dta[2]) * 8;
if (dta + 4 > ui->rawUnwindCodesEnd)
{
fprintf (file, _("warning: corrupt unwind data\n"));
return;
}
tmp = bfd_get_16 (abfd, dta + 2) * 8;
i++;
}
else
{
tmp = bfd_get_32 (abfd, &dta[2]);
if (dta + 6 > ui->rawUnwindCodesEnd)
{
fprintf (file, _("warning: corrupt unwind data\n"));
return;
}
tmp = bfd_get_32 (abfd, dta + 2);
i += 2;
}
fprintf (file, "alloc large area: rsp = rsp - 0x%x", tmp);
break;
case UWOP_ALLOC_SMALL:
fprintf (file, "alloc small area: rsp = rsp - 0x%x", (info + 1) * 8);
break;
case UWOP_SET_FPREG:
/* According to the documentation, info field is unused. */
fprintf (file, "FPReg: %s = rsp + 0x%x (info = 0x%x)",
@ -257,22 +271,40 @@ pex64_xdata_print_uwd_codes (FILE *file, bfd *abfd,
unexpected = ui->FrameRegister == 0;
save_allowed = FALSE;
break;
case UWOP_SAVE_NONVOL:
tmp = bfd_get_16 (abfd, &dta[2]) * 8;
if (dta + 4 > ui->rawUnwindCodesEnd)
{
fprintf (file, _("warning: corrupt unwind data\n"));
return;
}
tmp = bfd_get_16 (abfd, dta + 2) * 8;
i++;
fprintf (file, "save %s at rsp + 0x%x", pex_regs[info], tmp);
unexpected = !save_allowed;
break;
case UWOP_SAVE_NONVOL_FAR:
tmp = bfd_get_32 (abfd, &dta[2]);
if (dta + 6 > ui->rawUnwindCodesEnd)
{
fprintf (file, _("warning: corrupt unwind data\n"));
return;
}
tmp = bfd_get_32 (abfd, dta + 2);
i += 2;
fprintf (file, "save %s at rsp + 0x%x", pex_regs[info], tmp);
unexpected = !save_allowed;
break;
case UWOP_SAVE_XMM:
if (ui->Version == 1)
{
tmp = bfd_get_16 (abfd, &dta[2]) * 8;
if (dta + 4 > ui->rawUnwindCodesEnd)
{
fprintf (file, _("warning: corrupt unwind data\n"));
return;
}
tmp = bfd_get_16 (abfd, dta + 2) * 8;
i++;
fprintf (file, "save mm%u at rsp + 0x%x", info, tmp);
unexpected = !save_allowed;
@ -283,24 +315,43 @@ pex64_xdata_print_uwd_codes (FILE *file, bfd *abfd,
unexpected = TRUE;
}
break;
case UWOP_SAVE_XMM_FAR:
tmp = bfd_get_32 (abfd, &dta[2]) * 8;
if (dta + 6 > ui->rawUnwindCodesEnd)
{
fprintf (file, _("warning: corrupt unwind data\n"));
return;
}
tmp = bfd_get_32 (abfd, dta + 2) * 8;
i += 2;
fprintf (file, "save mm%u at rsp + 0x%x", info, tmp);
unexpected = !save_allowed;
break;
case UWOP_SAVE_XMM128:
tmp = bfd_get_16 (abfd, &dta[2]) * 16;
if (dta + 4 > ui->rawUnwindCodesEnd)
{
fprintf (file, _("warning: corrupt unwind data\n"));
return;
}
tmp = bfd_get_16 (abfd, dta + 2) * 16;
i++;
fprintf (file, "save xmm%u at rsp + 0x%x", info, tmp);
unexpected = !save_allowed;
break;
case UWOP_SAVE_XMM128_FAR:
tmp = bfd_get_32 (abfd, &dta[2]) * 16;
if (dta + 6 > ui->rawUnwindCodesEnd)
{
fprintf (file, _("warning: corrupt unwind data\n"));
return;
}
tmp = bfd_get_32 (abfd, dta + 2) * 16;
i += 2;
fprintf (file, "save xmm%u at rsp + 0x%x", info, tmp);
unexpected = !save_allowed;
break;
case UWOP_PUSH_MACHFRAME:
fprintf (file, "interrupt entry (SS, old RSP, EFLAGS, CS, RIP");
if (info == 0)
@ -310,11 +361,13 @@ pex64_xdata_print_uwd_codes (FILE *file, bfd *abfd,
else
fprintf (file, ", unknown(%u))", info);
break;
default:
/* PR 17512: file: 2245-7442-0.004. */
fprintf (file, _("Unknown: %x"), PEX64_UNWCODE_CODE (dta[1]));
break;
}
}
if (unexpected)
fprintf (file, " [Unexpected!]");
fputc ('\n', file);