[patch] Fix crash in read_pe_exported_syms

Corinna Vinschen
2013-03-02T11:02:46Z

Hi,

when running GDB from current CVS on a PE/COFF target, and if this
target has no debug symbols, nor any exported symbols, then GDB crashes
with a SEGV in the first do_cleanup called from coff_symfile_read.

The reason is that read_pe_exported_syms creates two cleanup handlers,
one of them referring to a symbol on the local stack:

struct read_pe_section_data *section_data;
[...]
section_data = xzalloc (...)
make_cleanup (free_current_contents, &section_data);

but then returns from the function early in three different scenarios
without calling do_cleanup. The subsequent do_cleanup call in
coff_symfile_read now tries to dereference from an invalid stack address
and ultimately crashes.

Below is a patch. Ok to apply?

Thanks,
Corinna

* coff-pe-read.c (read_pe_exported_syms): Don't return without
calling do_cleanup.

Index: coff-pe-read.c
===================================================================
RCS file: /cvs/src/src/gdb/coff-pe-read.c,v
retrieving revision 1.23
diff -u -p -r1.23 coff-pe-read.c
--- coff-pe-read.c 1 Jan 2013 06:32:40 -0000 1.23
+++ coff-pe-read.c 2 Mar 2013 11:00:42 -0000
@@ -379,7 +379,7 @@ read_pe_exported_syms (struct objfile *o
/* This is not a recognized PE format file. Abort now, because
the code is untested on anything else. *FIXME* test on
further architectures and loosen or remove this test. */
- return;
+ goto cleanup;
}

/* Get pe_header, optional header and numbers of export entries. */
@@ -392,7 +392,7 @@ read_pe_exported_syms (struct objfile *o

if (num_entries < 1) /* No exports. */
{
- return;
+ goto cleanup;
}
if (is_pe64)
{
@@ -448,7 +448,7 @@ read_pe_exported_syms (struct objfile *o
if (export_size == 0)
{
/* Empty export table. */
- return;
+ goto cleanup;
}

/* Scan sections and store the base and size of the relevant
@@ -614,6 +614,7 @@ read_pe_exported_syms (struct objfile *o
fprintf_unfiltered (gdb_stdlog, _("Finished reading \"%s\", exports %ld,"
" forwards %ld, total %ld/%ld.\n"), dll_name, nbnormal,
nbforward, nbnormal + nbforward, nexp);
+cleanup:
/* Discard expdata and section_data. */
do_cleanups (back_to);
}

--
Corinna Vinschen
Cygwin Maintainer
Red Hat