This is the mail archive of the cygwin mailing list for the Cygwin 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]

Re: mdemo ltdl failure


[cross-posted to cygwin]

Ralf Wildenhues wrote:
A (very small) progress report.
On Tue, Feb 27, 2007 at 11:02:01PM +0100, Ralf Wildenhues wrote:
* Charles Wilson wrote on Tue, Feb 27, 2007 at 05:42:50AM CET:
> Ralf Wildenhues wrote:
> >The only thing that's then still worrying me is that on Cygwin, the
> >mdemo and mdemo_static programs sometimes throw segmentation faults
> >on my system. Not all the time though.
> > Well, it's failing all the time for me, but I'm not sure it's a > segfault. What does "Hangup" mean, when reported by the shell after > executing the app:
Good question, I don't know. I suppose there is memory corruption
earlier, and due to it anything weird can happen later, so the exit
status is not really reliable.

When I compiled with -O0, the error message changed to 'Aborted (core dumped)'. It was indeed a segfault, and occurred at line 1582 in ltdl.c: 'FREE(buf)' within lt_argz_insertdir.


It's exposed by try_iterate which calls lt_dlforeachfile.  I think it's
somewhere in dirent code.  I have a feeling that it's not caused by
anything in Libtool, but am not sure.  (Only noting this because it may
ring a bell, not because I have any evidence.)

I've (almost) tracked down the error: it is caused by yet another bug in newlib's argz_insert() (or possibly realloc()! ), as called by lt_argz_insert:


1473	static int
1474	lt_argz_insert (char **pargz, size_t *pargz_len, char *before,
1475			const char *entry)
1476	{
1477	  error_t error;
1478
1479	  /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
1480	     pargz_len, NULL, entry) failed with EINVAL.  */
1481	  if (before)
1482	    error = argz_insert (pargz, pargz_len, before, entry);
1483	  else
1484	    error = argz_append (pargz, pargz_len, entry, 1 + strlen (entry));
1485
1486	  if (error)

The very first time argz_insert() is called -- rather than argz_append() -- the memory pointed to by pargz and entry gets corrupted (entry is known as 'buf' back in the caller lt_argz_insertdir.)

The value of 'entry' and 'before' during each successive call to lt_arg_insert() was:

"tests/mdemo/config", NULL
"tests/mdemo/foo1", NULL
"tests/mdemo/foo2", NULL
"tests/mdemo/libfoo2", NULL
"tests/mdemo/libmlib", NULL
"tests/mdemo/libsub", NULL
"tests/mdemo/libtool", NULL
"tests/mdemo/main", NULL
"tests/mdemo/Makefile", == *pargz

Note that dirent is returning filenames in case-insensitive alphabetical order -- but lt_argz_insertinorder() is using case-sensitive comparison, so Makefile gets inserted at the front of the list, while all the others were successively appended to the pargz list.

What's odd is that this bug in argz_insert() is very ticklish: it triggers on "tests/mdemo/Makefile", but not when argz_insert is called with "./tests/mdemo/Makefile". See the attached gdb screenshots from just before the buggy call and just after. I've highlighted in red the location to which *pargz points, and in blue the location to which entry (ne' buf) points.

The "after" shot indicates that the original contents of entry got copied to some 11 bytes prior to the beginning of the *pargz buffer, overlapping the beginning of the newly realloc'ed *pargz. Furthermore, after the call, the *pargz buffer -- if the value of of *pargz and *pargz_len are to be believed -- extends across where entry (e.g. buf) points -- so the malloc subsytem obviously no longer thinks *buf is an allocated block (otherwise, it wouldn't have included that chunk in the memory assigned to *pargz by the realloc). So, naturally, FREE(buf) fails.

I need to verify this using a debug-built cygwin kernel, but it looks like within newlib's argz_insert(), the call to realloc() is not operating correctly in this instance.

Note that using libltdl's own argz routines "fixes" this problem, perhaps because libltdl's argz_insert does not use realloc, but rather explicitly mallocs the new memory, does the copy, explicitly frees the old memory, and then does the *pargz pointer reassignment.

export ac_cv_func_argz_append=no;
export ac_cv_func_argz_create_sep=no;
export ac_cv_func_argz_insert=no;
export ac_cv_func_argz_next=no;
export ac_cv_func_argz_stringify=no;
export ac_cv_header_argz_h=no
../libtool-HEAD/configure FC=no CFLAGS="-ggdb -O0"
make
make -k check-TESTS TESTS='tests/mdemo-conf.test tests/mdemo-make.test tests/mdemo-exec.test' VERBOSE=t CFLAGS="-ggdb -O0"


works just fine (and I've verified that in this case, _lt__argz_insert() is being used, not cygwin's argz_insert()).

--
Chuck

P.S. all this was done using libtool-HEAD from yesterday, most recent changelog entry:

2007-03-09 Gary V. Vaughan <...>

        * libtoolize.m4sh: Replace literal tab chars in help comment
        with spaces to align columns in --help output.

which unfortunately exhibited new testsuite failures in Subproject Libltdl...

 33: compiling softlinked libltdl FAILED (subproject.at:59)
 34: compiling copied libltdl     FAILED (subproject.at:75)
 35: installable libltdl          FAILED (subproject.at:95)

Haven't even tried to track these down.

PNG image

PNG image

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

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