* 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).