libtool-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: mdemo ltdl failure


From: Charles Wilson
Subject: Re: mdemo ltdl failure
Date: Fri, 16 Mar 2007 10:35:01 -0500
User-agent: Thunderbird 1.5.0.10 (Windows/20070221)

[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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]