This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
A new patch for ld.so (Re: A ld.so bug)
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)
{