about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--dlfcn/dlerror.c29
2 files changed, 29 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index cf6959d262..ea7b3d4f48 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2019-05-15  Mark Wielaard  <mark@klomp.org>
+
+	[BZ# 24476]
+	* dlfcn/dlerror.c (__dlerror_main_freeres): Guard using
+	__libc_once_get (once) and static_buf == NULL.
+	(__dlerror): Check we have a valid key, set result to static_buf
+	otherwise.
+
 2019-05-15  Andreas Schwab  <schwab@suse.de>
 
 	[BZ #20568]
diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c
index 27376582d0..ca42c126c1 100644
--- a/dlfcn/dlerror.c
+++ b/dlfcn/dlerror.c
@@ -72,9 +72,16 @@ __dlerror (void)
   __libc_once (once, init);
 
   /* Get error string.  */
-  result = (struct dl_action_result *) __libc_getspecific (key);
-  if (result == NULL)
-    result = &last_result;
+  if (static_buf != NULL)
+    result = static_buf;
+  else
+    {
+      /* init () has been run and we don't use the static buffer.
+	 So we have a valid key.  */
+      result = (struct dl_action_result *) __libc_getspecific (key);
+      if (result == NULL)
+	result = &last_result;
+    }
 
   /* Test whether we already returned the string.  */
   if (result->returned != 0)
@@ -230,13 +237,19 @@ free_key_mem (void *mem)
 void
 __dlerror_main_freeres (void)
 {
-  void *mem;
   /* Free the global memory if used.  */
   check_free (&last_result);
-  /* Free the TSD memory if used.  */
-  mem = __libc_getspecific (key);
-  if (mem != NULL)
-    free_key_mem (mem);
+
+  if (__libc_once_get (once) && static_buf == NULL)
+    {
+      /* init () has been run and we don't use the static buffer.
+	 So we have a valid key.  */
+      void *mem;
+      /* Free the TSD memory if used.  */
+      mem = __libc_getspecific (key);
+      if (mem != NULL)
+	free_key_mem (mem);
+    }
 }
 
 struct dlfcn_hook *_dlfcn_hook __attribute__((nocommon));