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


Charles Wilson wrote:
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.

Actually, I messed up the screen shots, and some of the preceeding paragraph is incorrect. See the attached two screencaps, instead.
In the para above, I said that *pargz extended across entry/buf. Not so, but still -- somebody overwrote entry with junk from the old *pargz buffer, and it happened inside cygwin's argz_insert. And also, somebody lost track of the malloc status of entry/buf, because FREE(buf) dies after this call to cygwin's argz_insert (and argz_insert is not supposed to modify its const char* 'entry' argument)


Here's the code from newlib's argz_insert:

error_t
_DEFUN (argz_insert, (argz, argz_len, before, entry),
       char **argz _AND
       size_t *argz_len _AND
       char *before _AND
       const char *entry)
{
  int len = 0;

  if (before == NULL)
    return argz_add(argz, argz_len, entry);

  if (before < *argz || before >= *argz + *argz_len)
    return EINVAL;

  /* NOTE: on the failing call, before == *argz */
  while (before != *argz && before[-1])
    before--;

len = strlen(entry) + 1;

  if(!(*argz = (char *)realloc(*argz, *argz_len + len)))
    return ENOMEM;

  memmove(before + len, before, *argz + *argz_len - before);
  memcpy(before, entry, len);

*argz_len += len;

  return 0;
}

Somehow, the contents of entry are being clobbered, AND the malloc subsystem loses track of that chunk of memory such that FREE(buf) fails. But I've got to finish building my debug kernel, first.

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.

-- Chuck

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]