This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]