From 0ecb606cb6cf65de1d9fc8a919bceb4be476c602 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 12 Jul 2007 18:26:36 +0000 Subject: 2.5-18.1 --- dlfcn/dlerror.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) (limited to 'dlfcn/dlerror.c') diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c index 8789f4f68b..7ea31d4392 100644 --- a/dlfcn/dlerror.c +++ b/dlfcn/dlerror.c @@ -1,5 +1,5 @@ /* Return error detail for failing functions. - Copyright (C) 1995-2000,2002,2003,2004 Free Software Foundation, Inc. + Copyright (C) 1995-2000,2002,2003,2004,2005 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -40,6 +41,7 @@ struct dl_action_result { int errcode; int returned; + bool malloced; const char *objname; const char *errstring; }; @@ -154,13 +156,13 @@ _dlerror_run (void (*operate) (void *), void *args) { /* Free the error string from the last failed command. This can happen if `dlerror' was not run after an error was found. */ - if (strcmp (result->errstring, "out of memory") != 0) + if (result->malloced) free ((char *) result->errstring); result->errstring = NULL; } result->errcode = GLRO(dl_catch_error) (&result->objname, &result->errstring, - operate, args); + &result->malloced, operate, args); /* If no error we mark that no error string is available. */ result->returned = result->errstring == NULL; @@ -180,13 +182,30 @@ init (void) static_buf = &last_result; } + +static void +check_free (struct dl_action_result *rec) +{ + if (rec->errstring != NULL + && strcmp (rec->errstring, "out of memory") != 0) + { + /* We can free the string only if the allocation happened in the + C library used by the dynamic linker. This means, it is + always the C library in the base namespave. */ + struct link_map *map = NULL; + Dl_info info; + if (_dl_addr (check_free, &info, &map, NULL) != 0 + && map != NULL && map->l_ns == 0) + free ((char *) rec->errstring); + } +} + + static void __attribute__ ((destructor)) fini (void) { - if (last_result.errstring != NULL - && strcmp (last_result.errstring, "out of memory") != 0) - free ((char *) last_result.errstring); + check_free (&last_result); } @@ -194,11 +213,7 @@ fini (void) static void free_key_mem (void *mem) { - struct dl_action_result *result = (struct dl_action_result *) mem; - - if (result->errstring != NULL - && strcmp (result->errstring, "out of memory") != 0) - free ((char *) result->errstring); + check_free ((struct dl_action_result *) mem); free (mem); __libc_setspecific (key, NULL); -- cgit v1.2.3