mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-23 19:50:13 +08:00
ECOFF archive uninitialised read
* ecoff.c (_bfd_ecoff_slurp_armap): Sanity check parsed_size and symbol count. Allocate an extra byte to ensure name strings are terminated. Sanity check name offsets. Release memory on error return.
This commit is contained in:
@ -1,3 +1,10 @@
|
|||||||
|
2020-03-23 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* ecoff.c (_bfd_ecoff_slurp_armap): Sanity check parsed_size and
|
||||||
|
symbol count. Allocate an extra byte to ensure name strings
|
||||||
|
are terminated. Sanity check name offsets. Release memory on
|
||||||
|
error return.
|
||||||
|
|
||||||
2020-03-23 Alan Modra <amodra@gmail.com>
|
2020-03-23 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* i386msdos.c (msdos_object_p): Don't access e_lfanew when that
|
* i386msdos.c (msdos_object_p): Don't access e_lfanew when that
|
||||||
|
35
bfd/ecoff.c
35
bfd/ecoff.c
@ -2883,7 +2883,7 @@ _bfd_ecoff_slurp_armap (bfd *abfd)
|
|||||||
char nextname[17];
|
char nextname[17];
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
struct areltdata *mapdata;
|
struct areltdata *mapdata;
|
||||||
bfd_size_type parsed_size;
|
bfd_size_type parsed_size, stringsize;
|
||||||
char *raw_armap;
|
char *raw_armap;
|
||||||
struct artdata *ardata;
|
struct artdata *ardata;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
@ -2895,9 +2895,9 @@ _bfd_ecoff_slurp_armap (bfd *abfd)
|
|||||||
/* Get the name of the first element. */
|
/* Get the name of the first element. */
|
||||||
i = bfd_bread ((void *) nextname, (bfd_size_type) 16, abfd);
|
i = bfd_bread ((void *) nextname, (bfd_size_type) 16, abfd);
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
if (i != 16)
|
if (i != 16)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
|
if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -2942,17 +2942,22 @@ _bfd_ecoff_slurp_armap (bfd *abfd)
|
|||||||
parsed_size = mapdata->parsed_size;
|
parsed_size = mapdata->parsed_size;
|
||||||
free (mapdata);
|
free (mapdata);
|
||||||
|
|
||||||
raw_armap = (char *) _bfd_alloc_and_read (abfd, parsed_size, parsed_size);
|
if (parsed_size + 1 < 9)
|
||||||
if (raw_armap == NULL)
|
|
||||||
{
|
{
|
||||||
if (bfd_get_error () != bfd_error_system_call)
|
bfd_set_error (bfd_error_malformed_archive);
|
||||||
bfd_set_error (bfd_error_malformed_archive);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
raw_armap = (char *) _bfd_alloc_and_read (abfd, parsed_size + 1, parsed_size);
|
||||||
|
if (raw_armap == NULL)
|
||||||
|
return FALSE;
|
||||||
|
raw_armap[parsed_size] = 0;
|
||||||
|
|
||||||
ardata->tdata = (void *) raw_armap;
|
ardata->tdata = (void *) raw_armap;
|
||||||
|
|
||||||
count = H_GET_32 (abfd, raw_armap);
|
count = H_GET_32 (abfd, raw_armap);
|
||||||
|
if ((parsed_size - 8) / 8 < count)
|
||||||
|
goto error_malformed;
|
||||||
|
|
||||||
ardata->symdef_count = 0;
|
ardata->symdef_count = 0;
|
||||||
ardata->cache = NULL;
|
ardata->cache = NULL;
|
||||||
@ -2960,6 +2965,7 @@ _bfd_ecoff_slurp_armap (bfd *abfd)
|
|||||||
/* This code used to overlay the symdefs over the raw archive data,
|
/* This code used to overlay the symdefs over the raw archive data,
|
||||||
but that doesn't work on a 64 bit host. */
|
but that doesn't work on a 64 bit host. */
|
||||||
stringbase = raw_armap + count * 8 + 8;
|
stringbase = raw_armap + count * 8 + 8;
|
||||||
|
stringsize = parsed_size - (count * 8 + 8);
|
||||||
|
|
||||||
#ifdef CHECK_ARMAP_HASH
|
#ifdef CHECK_ARMAP_HASH
|
||||||
{
|
{
|
||||||
@ -3007,7 +3013,7 @@ _bfd_ecoff_slurp_armap (bfd *abfd)
|
|||||||
amt *= sizeof (carsym);
|
amt *= sizeof (carsym);
|
||||||
symdef_ptr = (carsym *) bfd_alloc (abfd, amt);
|
symdef_ptr = (carsym *) bfd_alloc (abfd, amt);
|
||||||
if (!symdef_ptr)
|
if (!symdef_ptr)
|
||||||
return FALSE;
|
goto error_exit;
|
||||||
|
|
||||||
ardata->symdefs = symdef_ptr;
|
ardata->symdefs = symdef_ptr;
|
||||||
|
|
||||||
@ -3020,6 +3026,8 @@ _bfd_ecoff_slurp_armap (bfd *abfd)
|
|||||||
if (file_offset == 0)
|
if (file_offset == 0)
|
||||||
continue;
|
continue;
|
||||||
name_offset = H_GET_32 (abfd, raw_ptr);
|
name_offset = H_GET_32 (abfd, raw_ptr);
|
||||||
|
if (name_offset > stringsize)
|
||||||
|
goto error_malformed;
|
||||||
symdef_ptr->name = stringbase + name_offset;
|
symdef_ptr->name = stringbase + name_offset;
|
||||||
symdef_ptr->file_offset = file_offset;
|
symdef_ptr->file_offset = file_offset;
|
||||||
++symdef_ptr;
|
++symdef_ptr;
|
||||||
@ -3028,10 +3036,17 @@ _bfd_ecoff_slurp_armap (bfd *abfd)
|
|||||||
ardata->first_file_filepos = bfd_tell (abfd);
|
ardata->first_file_filepos = bfd_tell (abfd);
|
||||||
/* Pad to an even boundary. */
|
/* Pad to an even boundary. */
|
||||||
ardata->first_file_filepos += ardata->first_file_filepos % 2;
|
ardata->first_file_filepos += ardata->first_file_filepos % 2;
|
||||||
|
|
||||||
abfd->has_armap = TRUE;
|
abfd->has_armap = TRUE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
error_malformed:
|
||||||
|
bfd_set_error (bfd_error_malformed_archive);
|
||||||
|
error_exit:
|
||||||
|
ardata->symdef_count = 0;
|
||||||
|
ardata->symdefs = NULL;
|
||||||
|
ardata->tdata = NULL;
|
||||||
|
bfd_release (abfd, raw_armap);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write out an armap. */
|
/* Write out an armap. */
|
||||||
|
Reference in New Issue
Block a user