Fix internal error when core file section is too big

As reported in PR 17808, a test case with a forged (invalid) core file
can crash GDB with an assertion failure.  In that particular case the
prstatus of an i386 core file looks like that from an AMD64 core file.
Consequently the respective regset supply function i386_supply_gregset
is invoked with a larger buffer than usual.  But i386_supply_gregset
asserts a specific buffer size, and this assertion fails.

The patch relaxes all buffer size assertions in regset supply
functions such that they merely check for a sufficiently large buffer.
For consistency the regset collect functions are adjusted as well.

gdb/ChangeLog:

	PR corefiles/17808:
	* gdbarch.sh (iterate_over_regset_sections_cb): Document this
	function type, particularly its SIZE parameter.
	* gdbarch.h: Regenerate.
	* amd64-tdep.c (amd64_supply_fpregset): In gdb_assert, compare
	actual against required size using ">=" instead of "==".
	(amd64_collect_fpregset): Likewise.
	* i386-tdep.c (i386_supply_gregset): Likewise.
	(i386_collect_gregset): Likewise.
	(i386_supply_fpregset): Likewise.
	(i386_collect_fpregset): Likewise.
	* mips-linux-tdep.c (mips_supply_gregset_wrapper): Likewise.
	(mips_fill_gregset_wrapper): Likewise.
	(mips_supply_fpregset_wrapper): Likewise.
	(mips_fill_fpregset_wrapper): Likewise.
	(mips64_supply_gregset_wrapper): Likewise.
	(mips64_fill_gregset_wrapper): Likewise.
	(mips64_supply_fpregset_wrapper): Likewise.
	(mips64_fill_fpregset_wrapper): Likewise.
	* mn10300-linux-tdep.c (am33_supply_gregset_method): Likewise.
	(am33_supply_fpregset_method): Likewise.
	(am33_collect_gregset_method): Likewise.
	(am33_collect_fpregset_method): Likewise.
This commit is contained in:
Andreas Arnez 2015-01-14 12:01:38 +00:00 committed by Ulrich Weigand
parent 8962a307ae
commit 1528345d6c
7 changed files with 56 additions and 18 deletions

View File

@ -1,3 +1,29 @@
2015-02-04 Andreas Arnez <arnez@linux.vnet.ibm.com>
PR corefiles/17808:
* gdbarch.sh (iterate_over_regset_sections_cb): Document this
function type, particularly its SIZE parameter.
* gdbarch.h: Regenerate.
* amd64-tdep.c (amd64_supply_fpregset): In gdb_assert, compare
actual against required size using ">=" instead of "==".
(amd64_collect_fpregset): Likewise.
* i386-tdep.c (i386_supply_gregset): Likewise.
(i386_collect_gregset): Likewise.
(i386_supply_fpregset): Likewise.
(i386_collect_fpregset): Likewise.
* mips-linux-tdep.c (mips_supply_gregset_wrapper): Likewise.
(mips_fill_gregset_wrapper): Likewise.
(mips_supply_fpregset_wrapper): Likewise.
(mips_fill_fpregset_wrapper): Likewise.
(mips64_supply_gregset_wrapper): Likewise.
(mips64_fill_gregset_wrapper): Likewise.
(mips64_supply_fpregset_wrapper): Likewise.
(mips64_fill_fpregset_wrapper): Likewise.
* mn10300-linux-tdep.c (am33_supply_gregset_method): Likewise.
(am33_supply_fpregset_method): Likewise.
(am33_collect_gregset_method): Likewise.
(am33_collect_fpregset_method): Likewise.
2015-02-04 Doug Evans <dje@google.com>
Pedro Alves <palves@redhat.com>
Eli Zaretskii <eliz@gnu.org>

View File

@ -2854,7 +2854,7 @@ amd64_supply_fpregset (const struct regset *regset, struct regcache *regcache,
struct gdbarch *gdbarch = get_regcache_arch (regcache);
const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
gdb_assert (len == tdep->sizeof_fpregset);
gdb_assert (len >= tdep->sizeof_fpregset);
amd64_supply_fxsave (regcache, regnum, fpregs);
}
@ -2871,7 +2871,7 @@ amd64_collect_fpregset (const struct regset *regset,
struct gdbarch *gdbarch = get_regcache_arch (regcache);
const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
gdb_assert (len == tdep->sizeof_fpregset);
gdb_assert (len >= tdep->sizeof_fpregset);
amd64_collect_fxsave (regcache, regnum, fpregs);
}

View File

@ -85,6 +85,12 @@ extern struct gdbarch *target_gdbarch (void);
typedef int (iterate_over_objfiles_in_search_order_cb_ftype)
(struct objfile *objfile, void *cb_data);
/* Callback type for regset section iterators. The callback usually
invokes the REGSET's supply or collect method, to which it must
pass a buffer with at least the given SIZE. SECT_NAME is a BFD
section name, and HUMAN_NAME is used for diagnostic messages.
CB_DATA should have been passed unchanged through the iterator. */
typedef void (iterate_over_regset_sections_cb)
(const char *sect_name, int size, const struct regset *regset,
const char *human_name, void *cb_data);

View File

@ -1239,6 +1239,12 @@ extern struct gdbarch *target_gdbarch (void);
typedef int (iterate_over_objfiles_in_search_order_cb_ftype)
(struct objfile *objfile, void *cb_data);
/* Callback type for regset section iterators. The callback usually
invokes the REGSET's supply or collect method, to which it must
pass a buffer with at least the given SIZE. SECT_NAME is a BFD
section name, and HUMAN_NAME is used for diagnostic messages.
CB_DATA should have been passed unchanged through the iterator. */
typedef void (iterate_over_regset_sections_cb)
(const char *sect_name, int size, const struct regset *regset,
const char *human_name, void *cb_data);

View File

@ -3727,7 +3727,7 @@ i386_supply_gregset (const struct regset *regset, struct regcache *regcache,
const gdb_byte *regs = gregs;
int i;
gdb_assert (len == tdep->sizeof_gregset);
gdb_assert (len >= tdep->sizeof_gregset);
for (i = 0; i < tdep->gregset_num_regs; i++)
{
@ -3752,7 +3752,7 @@ i386_collect_gregset (const struct regset *regset,
gdb_byte *regs = gregs;
int i;
gdb_assert (len == tdep->sizeof_gregset);
gdb_assert (len >= tdep->sizeof_gregset);
for (i = 0; i < tdep->gregset_num_regs; i++)
{
@ -3779,7 +3779,7 @@ i386_supply_fpregset (const struct regset *regset, struct regcache *regcache,
return;
}
gdb_assert (len == tdep->sizeof_fpregset);
gdb_assert (len >= tdep->sizeof_fpregset);
i387_supply_fsave (regcache, regnum, fpregs);
}
@ -3802,7 +3802,7 @@ i386_collect_fpregset (const struct regset *regset,
return;
}
gdb_assert (len == tdep->sizeof_fpregset);
gdb_assert (len >= tdep->sizeof_fpregset);
i387_collect_fsave (regcache, regnum, fpregs);
}

View File

@ -163,7 +163,7 @@ mips_supply_gregset_wrapper (const struct regset *regset,
struct regcache *regcache,
int regnum, const void *gregs, size_t len)
{
gdb_assert (len == sizeof (mips_elf_gregset_t));
gdb_assert (len >= sizeof (mips_elf_gregset_t));
mips_supply_gregset (regcache, (const mips_elf_gregset_t *)gregs);
}
@ -231,7 +231,7 @@ mips_fill_gregset_wrapper (const struct regset *regset,
const struct regcache *regcache,
int regnum, void *gregs, size_t len)
{
gdb_assert (len == sizeof (mips_elf_gregset_t));
gdb_assert (len >= sizeof (mips_elf_gregset_t));
mips_fill_gregset (regcache, (mips_elf_gregset_t *)gregs, regnum);
}
@ -268,7 +268,7 @@ mips_supply_fpregset_wrapper (const struct regset *regset,
struct regcache *regcache,
int regnum, const void *gregs, size_t len)
{
gdb_assert (len == sizeof (mips_elf_fpregset_t));
gdb_assert (len >= sizeof (mips_elf_fpregset_t));
mips_supply_fpregset (regcache, (const mips_elf_fpregset_t *)gregs);
}
@ -311,7 +311,7 @@ mips_fill_fpregset_wrapper (const struct regset *regset,
const struct regcache *regcache,
int regnum, void *gregs, size_t len)
{
gdb_assert (len == sizeof (mips_elf_fpregset_t));
gdb_assert (len >= sizeof (mips_elf_fpregset_t));
mips_fill_fpregset (regcache, (mips_elf_fpregset_t *)gregs, regnum);
}
@ -413,7 +413,7 @@ mips64_supply_gregset_wrapper (const struct regset *regset,
struct regcache *regcache,
int regnum, const void *gregs, size_t len)
{
gdb_assert (len == sizeof (mips64_elf_gregset_t));
gdb_assert (len >= sizeof (mips64_elf_gregset_t));
mips64_supply_gregset (regcache, (const mips64_elf_gregset_t *)gregs);
}
@ -484,7 +484,7 @@ mips64_fill_gregset_wrapper (const struct regset *regset,
const struct regcache *regcache,
int regnum, void *gregs, size_t len)
{
gdb_assert (len == sizeof (mips64_elf_gregset_t));
gdb_assert (len >= sizeof (mips64_elf_gregset_t));
mips64_fill_gregset (regcache, (mips64_elf_gregset_t *)gregs, regnum);
}
@ -533,7 +533,7 @@ mips64_supply_fpregset_wrapper (const struct regset *regset,
struct regcache *regcache,
int regnum, const void *gregs, size_t len)
{
gdb_assert (len == sizeof (mips64_elf_fpregset_t));
gdb_assert (len >= sizeof (mips64_elf_fpregset_t));
mips64_supply_fpregset (regcache, (const mips64_elf_fpregset_t *)gregs);
}
@ -611,7 +611,7 @@ mips64_fill_fpregset_wrapper (const struct regset *regset,
const struct regcache *regcache,
int regnum, void *gregs, size_t len)
{
gdb_assert (len == sizeof (mips64_elf_fpregset_t));
gdb_assert (len >= sizeof (mips64_elf_fpregset_t));
mips64_fill_fpregset (regcache, (mips64_elf_fpregset_t *)gregs, regnum);
}

View File

@ -90,7 +90,7 @@ am33_supply_gregset_method (const struct regset *regset,
const mn10300_elf_greg_t *regp = (const mn10300_elf_greg_t *) gregs;
int i;
gdb_assert (len == sizeof (mn10300_elf_gregset_t));
gdb_assert (len >= sizeof (mn10300_elf_gregset_t));
switch (regnum) {
case E_D0_REGNUM:
@ -245,7 +245,7 @@ am33_supply_fpregset_method (const struct regset *regset,
{
const mn10300_elf_fpregset_t *fpregset = fpregs;
gdb_assert (len == sizeof (mn10300_elf_fpregset_t));
gdb_assert (len >= sizeof (mn10300_elf_fpregset_t));
if (regnum == -1)
{
@ -278,7 +278,7 @@ am33_collect_gregset_method (const struct regset *regset,
mn10300_elf_gregset_t *regp = gregs;
int i;
gdb_assert (len == sizeof (mn10300_elf_gregset_t));
gdb_assert (len >= sizeof (mn10300_elf_gregset_t));
switch (regnum) {
case E_D0_REGNUM:
@ -425,7 +425,7 @@ am33_collect_fpregset_method (const struct regset *regset,
{
mn10300_elf_fpregset_t *fpregset = fpregs;
gdb_assert (len == sizeof (mn10300_elf_fpregset_t));
gdb_assert (len >= sizeof (mn10300_elf_fpregset_t));
if (regnum == -1)
{