This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
memory corruption while reading lineno entries from COFF files?
- From: Jaka Močnik <jaka at xlab dot si>
- To: binutils at sourceware dot org
- Date: Mon, 04 Aug 2008 18:15:55 +0200
- Subject: memory corruption while reading lineno entries from COFF files?
hello!
hope this is the right list to discuss a rather unexpected bug, I
suspect binutils 2.18 (as well as CVS HEAD) to have.
so ... it seems that I have stumbled upon a nasty, well hidden case of
memory corruption in the process of implementing support for a new COFF
flavour (used on NEC SX architecture) in libbfd.
namely: the function
coff_slurp_line_table()
in bfd/coffcode.h at lines ~4300 allocates both native_lineno and
lineno_cache (in that order!) using bfd_alloc(), which in turn calls
objalloc_alloc() from libiberty.
at the end of this routine, native_lineno is bfd_release()d (and in turn
objalloc_free_block()ed), while lineno_cache is not (explicitly) freed,
but assigned to the relevant section member lineno for later use.
however, as the freed native_lineno was allocated prior to lineno_cache,
and the objalloc_free_block() comment from libiberty states that what
routine does is:
"Free a block from an objalloc structure. This also frees all more
recently allocated blocks."
thus, releasing native_lineno also frees the lineno cache which should
stay allocated for later use (like when doing coff_find_nearest_line()
etc.), causing next allocations to overwrite that space. this causes all
further accesses to lineno cache via the section member to return bogus
info. in my case, reading minisyms just a bit later, overwrites the
lineno cache and finding near lines (when doing nm -l or similar) fails
miserably.
my problem is that this seems way too big a bug to have gone unnoticed,
so: can someone confirm my observation and its correctnes or tell me
that it is me doing/understanding something brutally wrong?
anyhow, if my diagnosis is correct, the fix seems fairly simple - as a
quick grep over the source shows that the lineno cache of a section
never gets freed at all, it can be simply bfd_malloc()ed and forgotten
about. patch attached.
regards,
jaKa
--
email: jaka@xlab.si
w3: http://www.gmajna.net/svojat/jaka/
diff -ur binutils-2.18/bfd/coffcode.h binutils-2.18-sx/bfd/coffcode.h
--- binutils-2.18/bfd/coffcode.h 2007-08-06 21:59:19.000000000 +0200
+++ binutils-2.18-sx/bfd/coffcode.h 2008-08-04 17:58:06.000000000 +0200
@@ -4298,7 +4298,7 @@
}
amt = ((bfd_size_type) asect->lineno_count + 1) * sizeof (alent);
- lineno_cache = bfd_alloc (abfd, amt);
+ lineno_cache = bfd_malloc (amt);
if (lineno_cache == NULL)
return FALSE;
@@ -4379,7 +4379,7 @@
qsort (func_table, nbr_func, sizeof (alent *), coff_sort_func_alent);
/* Create the new sorted table. */
- n_lineno_cache = bfd_alloc (abfd, amt);
+ n_lineno_cache = bfd_malloc (amt);
if (n_lineno_cache != NULL)
{
alent *n_cache_ptr = n_lineno_cache;
@@ -4401,7 +4401,7 @@
*n_cache_ptr++ = *old_ptr++;
}
n_cache_ptr->line_number = 0;
- bfd_release (abfd, lineno_cache);
+ free (lineno_cache);
lineno_cache = n_lineno_cache;
}
free (func_table);