public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* A ld.so bug
@ 2001-05-04 16:36 H . J . Lu
  2001-05-04 22:45 ` H . J . Lu
  0 siblings, 1 reply; 3+ messages in thread
From: H . J . Lu @ 2001-05-04 16:36 UTC (permalink / raw)
  To: GNU C Library

# gcc d.c -ldl -D_GNU_SOURCE
# a.out
zsh: 5484 segmentation fault  ./a.out

The problem is _dl_signal_error is called with (xxx, NULL, xxx) in
quite a few places. But _dl_signal_error does strlen (objname) without
checking if objname is NULL.

BTW, there is anther problem. I don't think _dlerror_run can use
calloc for error reporting. I got a testcase with

void*
calloc(size_t n, size_t len)
{
        if (callocp == NULL) 
                callocp = (void *(*) (size_t, size_t)) dlsym (RTLD_NEXT,
"calloc
");

        printf("CALLOC %d %d --> %p\n", n, len, callocp);
        return (*callocp)(n, len);
}

void *
malloc(size_t len)
{
        if (mallocp == NULL)
                mallocp = (void *(*) (size_t)) dlsym (RTLD_NEXT, "malloc");

        printf("MALLOC %d (--> %p)\n", len, mallocp);
        return (*mallocp)(len);
}

void *
realloc(void* ptr, size_t len)
{
        if (reallocp == NULL)
                reallocp = (void *(*) (void*, size_t)) dlsym (RTLD_NEXT,
"reallo
c");

        printf("REALLOC %p %d (--> %p)\n", ptr, len, reallocp);
        return (*reallocp)(ptr, len);
}

ld.so went to an endless recursive call while trying to tell me

RTLD_NEXT used in code not dynamically loade



H.J.
----
#include <stdio.h>
#include <dlfcn.h>

int
main(void)
{
   void *p;

   p = (void *(*) (size_t)) dlsym (RTLD_NEXT, "foo");

   if (p == NULL)
     printf("%s\n", dlerror ());

  return 0;
}

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: A ld.so bug
  2001-05-04 16:36 A ld.so bug H . J . Lu
@ 2001-05-04 22:45 ` H . J . Lu
  2001-05-04 23:46   ` A new patch for ld.so (Re: A ld.so bug) H . J . Lu
  0 siblings, 1 reply; 3+ messages in thread
From: H . J . Lu @ 2001-05-04 22:45 UTC (permalink / raw)
  To: GNU C Library

On Fri, May 04, 2001 at 04:36:30PM -0700, H . J . Lu wrote:
> # gcc d.c -ldl -D_GNU_SOURCE
> # a.out
> zsh: 5484 segmentation fault  ./a.out
> 
> The problem is _dl_signal_error is called with (xxx, NULL, xxx) in
> quite a few places. But _dl_signal_error does strlen (objname) without
> checking if objname is NULL.
> 
> BTW, there is anther problem. I don't think _dlerror_run can use
> calloc for error reporting. I got a testcase with
> 

# cc -o d d.c -ldl
# ./d
zsh: 5238 segmentation fault  ./d

Here is a patch and a testcase.


H.J.
-----
2001-05-04  H.J. Lu  <hjl@gnu.org>

	* elf/dl-error.c (catch): Add 2 new fields, fatal and errcode.
	(_dl_signal_error): Check if objname is NULL and prepare for
	malloc failure.
	(_dl_catch_error): Copy the "fatal" field from the old catch to
	the new one.

--- libc/elf/dl-error.c.fatal	Tue Feb 27 22:22:09 2001
+++ libc/elf/dl-error.c	Fri May  4 22:26:59 2001
@@ -31,6 +31,8 @@ struct catch
   {
     const char *objname;	/* Object/File name.  */
     const char *errstring;	/* Error detail filled in here.  */
+    int fatal;			/* If any error is fatal.  */
+    int errcode;		/* The old error code.  */
     jmp_buf env;		/* longjmp here on error.  */
   };
 
@@ -71,29 +73,55 @@ _dl_signal_error (int errcode, const cha
     errstring = N_("DYNAMIC LINKER BUG!!!");
 
   lcatch = tsd_getspecific ();
-  if (lcatch != NULL)
+  if (lcatch != NULL && lcatch->fatal == 0)
     {
       /* We are inside _dl_catch_error.  Return to it.  We have to
 	 duplicate the error string since it might be allocated on the
 	 stack.  The object name is always a string constant.  */
-      size_t len_objname = strlen (objname) + 1;
-      size_t len_errstring = strlen (errstring) + 1;
+      size_t len_objname;
+      size_t len_errstring;
+      struct catch new_catch;
+
+      if (objname == NULL)
+	objname = _dl_argv[0] ?: "<main program>";
+
+      len_objname = strlen (objname) + 1;
+      len_errstring = strlen (errstring) + 1;
+
+      /* We have to prepare for any possible errors. */
+      new_catch.errstring = errstring;
+      new_catch.objname = objname;
+      new_catch.errcode = errcode;
+      new_catch.fatal = 1;
 
-      lcatch->errstring = (char *) malloc (len_objname + len_errstring);
-      if (lcatch->errstring != NULL)
-	/* Make a copy of the object file name and the error string.  */
-	lcatch->objname = memcpy (__mempcpy ((char *) lcatch->errstring,
-					     errstring, len_errstring),
-				  objname, len_objname);
-      else
+      errcode = setjmp (new_catch.env);
+      if (__builtin_expect (errcode, 0) == 0)
 	{
-	  /* This is better than nothing.  */
-	  lcatch->objname = "";
-	  lcatch->errstring = _dl_out_of_memory;
+	  tsd_setspecific (&new_catch);
+	  lcatch->errstring = (char *) malloc (len_objname
+					       + len_errstring);
+	  if (lcatch->errstring != NULL)
+	    /* Make a copy of the object file name and the error
+	       string.  */
+	    lcatch->objname = memcpy (__mempcpy ((char *) lcatch->errstring,
+						 errstring,
+						 len_errstring),
+				      objname, len_objname);
+	  else
+	    {
+	      /* This is better than nothing.  */
+	      lcatch->objname = "";
+	      lcatch->errstring = _dl_out_of_memory;
+	    }
+	  tsd_setspecific (lcatch);
+	  longjmp (lcatch->env, errcode ?: -1);
 	}
-      longjmp (lcatch->env, errcode ?: -1);
+      /* When we get here via longjmp, something must be worng.  */
+      tsd_setspecific (lcatch);
+      objname = new_catch.objname;
+      errstring = new_catch.errstring;
+      errcode = new_catch.errcode;
     }
-  else
     {
       /* Lossage while resolving the program's own symbols is always fatal.  */
       char buffer[1024];
@@ -143,6 +171,8 @@ _dl_catch_error (const char **objname, c
   c.errstring = NULL;
 
   old = tsd_getspecific ();
+  c.fatal = old ? old->fatal : 0;
+
   errcode = setjmp (c.env);
   if (__builtin_expect (errcode, 0) == 0)
     {
------
#undef _GNU_SOURCE
#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>

void *
malloc(size_t len)
{
  void *(*mallocp) (size_t);

  mallocp = (void *(*) (size_t)) dlsym (RTLD_NEXT, "malloc");
  if (mallocp == NULL)
    {
      printf ("%s\n", dlerror ());
      exit (1);
    }

   return (*mallocp)(len);
}

int
main(void)
{
  void* ptr;

  ptr = malloc(10);
  free(ptr);
  return 0;
}

^ permalink raw reply	[flat|nested] 3+ messages in thread

* A new patch for ld.so (Re: A ld.so bug)
  2001-05-04 22:45 ` H . J . Lu
@ 2001-05-04 23:46   ` H . J . Lu
  0 siblings, 0 replies; 3+ messages in thread
From: H . J . Lu @ 2001-05-04 23:46 UTC (permalink / raw)
  To: GNU C Library

On Fri, May 04, 2001 at 10:45:29PM -0700, H . J . Lu wrote:
> On Fri, May 04, 2001 at 04:36:30PM -0700, H . J . Lu wrote:
> > # gcc d.c -ldl -D_GNU_SOURCE
> > # a.out
> > zsh: 5484 segmentation fault  ./a.out
> > 
> > The problem is _dl_signal_error is called with (xxx, NULL, xxx) in
> > quite a few places. But _dl_signal_error does strlen (objname) without
> > checking if objname is NULL.
> > 
> > BTW, there is anther problem. I don't think _dlerror_run can use
> > calloc for error reporting. I got a testcase with
> > 
> 
> # cc -o d d.c -ldl
> # ./d
> zsh: 5238 segmentation fault  ./d
> 
> Here is a patch and a testcase.
> 
> 

My last patch has a bug. I think this one is ok.


H.J.
----
2001-05-04  H.J. Lu  <hjl@gnu.org>

	* elf/dl-error.c (catch): Add a new field, fatal.
	(_dl_signal_error): Check if objname is NULL and prepare for
	malloc failure.
	(_dl_catch_error): Copy the "fatal" field from the old catch to
	the new one.

--- libc/elf/dl-error.c.fatal	Tue Feb 27 22:22:09 2001
+++ libc/elf/dl-error.c	Fri May  4 22:26:59 2001
@@ -31,6 +31,7 @@ struct catch
   {
     const char *objname;	/* Object/File name.  */
     const char *errstring;	/* Error detail filled in here.  */
+    int fatal;			/* If any error is fatal.  */
     jmp_buf env;		/* longjmp here on error.  */
   };
 
@@ -71,29 +72,50 @@ _dl_signal_error (int errcode, const cha
     errstring = N_("DYNAMIC LINKER BUG!!!");
 
   lcatch = tsd_getspecific ();
-  if (lcatch != NULL)
+  if (lcatch != NULL && lcatch->fatal == 0)
     {
       /* We are inside _dl_catch_error.  Return to it.  We have to
 	 duplicate the error string since it might be allocated on the
 	 stack.  The object name is always a string constant.  */
-      size_t len_objname = strlen (objname) + 1;
-      size_t len_errstring = strlen (errstring) + 1;
+      size_t len_objname;
+      size_t len_errstring;
+      struct catch new_catch;
+      int result;
+
+      if (objname == NULL)
+	objname = _dl_argv[0] ?: "<main program>";
 
-      lcatch->errstring = (char *) malloc (len_objname + len_errstring);
-      if (lcatch->errstring != NULL)
-	/* Make a copy of the object file name and the error string.  */
-	lcatch->objname = memcpy (__mempcpy ((char *) lcatch->errstring,
-					     errstring, len_errstring),
-				  objname, len_objname);
-      else
+      len_objname = strlen (objname) + 1;
+      len_errstring = strlen (errstring) + 1;
+
+      /* We have to prepare for any possible errors. */
+      new_catch.fatal = 1;
+
+      result = setjmp (new_catch.env);
+      if (__builtin_expect (result, 0) == 0)
 	{
-	  /* This is better than nothing.  */
-	  lcatch->objname = "";
-	  lcatch->errstring = _dl_out_of_memory;
+	  tsd_setspecific (&new_catch);
+	  lcatch->errstring = (char *) malloc (len_objname
+					       + len_errstring);
+	  if (lcatch->errstring != NULL)
+	    /* Make a copy of the object file name and the error
+	       string.  */
+	    lcatch->objname = memcpy (__mempcpy ((char *) lcatch->errstring,
+						 errstring,
+						 len_errstring),
+				      objname, len_objname);
+	  else
+	    {
+	      /* This is better than nothing.  */
+	      lcatch->objname = "";
+	      lcatch->errstring = _dl_out_of_memory;
+	    }
+	  tsd_setspecific (lcatch);
+	  longjmp (lcatch->env, errcode ?: -1);
 	}
-      longjmp (lcatch->env, errcode ?: -1);
+      /* When we get here via longjmp, something must be worng.  */
+      tsd_setspecific (lcatch);
     }
-  else
     {
       /* Lossage while resolving the program's own symbols is always fatal.  */
       char buffer[1024];
@@ -143,6 +165,8 @@ _dl_catch_error (const char **objname, c
   c.errstring = NULL;
 
   old = tsd_getspecific ();
+  c.fatal = old ? old->fatal : 0;
+
   errcode = setjmp (c.env);
   if (__builtin_expect (errcode, 0) == 0)
     {

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2001-05-04 23:46 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-05-04 16:36 A ld.so bug H . J . Lu
2001-05-04 22:45 ` H . J . Lu
2001-05-04 23:46   ` A new patch for ld.so (Re: A ld.so bug) H . J . Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).