PR29653, objcopy/strip: fuzzed small input file induces large output file

_bfd_check_format functions should not print errors or warnings if
they return NULL.  A NULL return means the particular target under
test does not match, so there isn't any reason to make a complaint
about the target.  In fact there isn't a good reason to warn even if
the target matches, except via the _bfd_per_xvec_warn mechanism; Some
other target might be a better match.

This patch tidies pe_bfd_object_p with the above in mind, and
restricts the PE optional header SectionAlignment and FileAlignment
fields somewhat.  I chose to warn on nonsense values rather than
refusing to match.  Refusing to match would be OK too.

	PR 29653
	* peXXigen.c (_bfd_XXi_swap_aouthdr_in): Don't emit error about
	invalid NumberOfRvaAndSizes here.  Limit loop copying data
	directory to IMAGE_NUMBEROF_DIRECTORY_ENTRIES.
	* peicode.h (pe_bfd_object_p): Don't clear and test bfd_error
	around bfd_coff_swap_aouthdr_in.  Warn on invalid SectionAlignment,
	FileAlignment and NumberOfRvaAndSizes.  Don't return NULL on
	invalid NumberOfRvaAndSizes.
This commit is contained in:
Alan Modra
2022-10-07 10:23:05 +10:30
parent fea044ba7b
commit ea4e4a19b7
2 changed files with 46 additions and 43 deletions

View File

@ -517,45 +517,26 @@ _bfd_XXi_swap_aouthdr_in (bfd * abfd,
a->LoaderFlags = H_GET_32 (abfd, src->LoaderFlags);
a->NumberOfRvaAndSizes = H_GET_32 (abfd, src->NumberOfRvaAndSizes);
{
unsigned idx;
/* PR 17512: Don't blindly trust NumberOfRvaAndSizes. */
unsigned idx;
for (idx = 0;
idx < a->NumberOfRvaAndSizes && idx < IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
idx++)
{
/* If data directory is empty, rva also should be 0. */
int size = H_GET_32 (abfd, src->DataDirectory[idx][1]);
int vma = size ? H_GET_32 (abfd, src->DataDirectory[idx][0]) : 0;
/* PR 17512: Corrupt PE binaries can cause seg-faults. */
if (a->NumberOfRvaAndSizes > IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
{
/* xgettext:c-format */
_bfd_error_handler
(_("%pB: aout header specifies an invalid number of"
" data-directory entries: %u"), abfd, a->NumberOfRvaAndSizes);
bfd_set_error (bfd_error_bad_value);
a->DataDirectory[idx].Size = size;
a->DataDirectory[idx].VirtualAddress = vma;
}
/* Paranoia: If the number is corrupt, then assume that the
actual entries themselves might be corrupt as well. */
a->NumberOfRvaAndSizes = 0;
}
for (idx = 0; idx < a->NumberOfRvaAndSizes; idx++)
{
/* If data directory is empty, rva also should be 0. */
int size =
H_GET_32 (abfd, src->DataDirectory[idx][1]);
a->DataDirectory[idx].Size = size;
if (size)
a->DataDirectory[idx].VirtualAddress =
H_GET_32 (abfd, src->DataDirectory[idx][0]);
else
a->DataDirectory[idx].VirtualAddress = 0;
}
while (idx < IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
{
a->DataDirectory[idx].Size = 0;
a->DataDirectory[idx].VirtualAddress = 0;
idx ++;
}
}
while (idx < IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
{
a->DataDirectory[idx].Size = 0;
a->DataDirectory[idx].VirtualAddress = 0;
idx++;
}
if (aouthdr_int->entry)
{

View File

@ -1519,19 +1519,41 @@ pe_bfd_object_p (bfd * abfd)
if (amt > opt_hdr_size)
memset (opthdr + opt_hdr_size, 0, amt - opt_hdr_size);
bfd_set_error (bfd_error_no_error);
bfd_coff_swap_aouthdr_in (abfd, opthdr, & internal_a);
if (bfd_get_error () != bfd_error_no_error)
return NULL;
}
bfd_coff_swap_aouthdr_in (abfd, opthdr, &internal_a);
struct internal_extra_pe_aouthdr *a = &internal_a.pe;
if ((a->SectionAlignment & -a->SectionAlignment) != a->SectionAlignment
|| a->SectionAlignment >= 0x80000000)
{
const char **warn = _bfd_per_xvec_warn (abfd->xvec);
*warn = _("%pB: adjusting invalid SectionAlignment");
a->SectionAlignment &= -a->SectionAlignment;
if (a->SectionAlignment >= 0x80000000)
a->SectionAlignment = 0x40000000;
}
if ((a->FileAlignment & -a->FileAlignment) != a->FileAlignment
|| a->FileAlignment > a->SectionAlignment)
{
const char **warn = _bfd_per_xvec_warn (abfd->xvec);
*warn = _("%pB: adjusting invalid FileAlignment");
a->FileAlignment &= -a->FileAlignment;
if (a->FileAlignment > a->SectionAlignment)
a->FileAlignment = a->SectionAlignment;
}
if (a->NumberOfRvaAndSizes > IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
{
const char **warn = _bfd_per_xvec_warn (abfd->xvec);
*warn = _("%pB: invalid NumberOfRvaAndSizes");
}
}
result = coff_real_object_p (abfd, internal_f.f_nscns, &internal_f,
(opt_hdr_size != 0
? &internal_a
: (struct internal_aouthdr *) NULL));
if (result)
{
/* Now the whole header has been processed, see if there is a build-id */