From 51dd05503668d47c0f5b37a9b481d4e3d7463586 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sun, 8 Aug 2021 19:11:31 +0200
Subject: [PATCH] relocatable-lib-lgpl: Fix a memory leak related to a Windows
 DLL.

Reported by Jonathan Boeing <jonathan@claws-mail.org> in
<https://lists.gnu.org/archive/html/bug-gnulib/2021-08/msg00048.html>.

* lib/relocatable.c (DllMain): Avoid memory leak in a special case
of repeated attach/detach.
---
 ChangeLog         |  8 ++++++++
 lib/relocatable.c | 13 +++++++++++--
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index fd21a946c0..dba60b9191 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2021-08-08  Bruno Haible  <bruno@clisp.org>
+
+	relocatable-lib-lgpl: Fix a memory leak related to a Windows DLL.
+	Reported by Jonathan Boeing <jonathan@claws-mail.org> in
+	<https://lists.gnu.org/archive/html/bug-gnulib/2021-08/msg00048.html>.
+	* lib/relocatable.c (DllMain): Avoid memory leak in a special case
+	of repeated attach/detach.
+
 2021-08-08  Bruno Haible  <bruno@clisp.org>
 
 	fopen: Fix link error on native Windows.
diff --git a/lib/relocatable.c b/lib/relocatable.c
index ababc35011..a6829127b4 100644
--- a/lib/relocatable.c
+++ b/lib/relocatable.c
@@ -323,7 +323,10 @@ static char *shared_library_fullname;
    supports longer file names
    (see <https://cygwin.com/ml/cygwin/2011-01/msg00410.html>).  */
 
-/* Determine the full pathname of the shared library when it is loaded.  */
+/* Determine the full pathname of the shared library when it is loaded.
+
+   Documentation:
+   <https://docs.microsoft.com/en-us/windows/win32/dlls/dllmain>  */
 
 BOOL WINAPI
 DllMain (HINSTANCE module_handle, DWORD event, LPVOID reserved)
@@ -343,7 +346,13 @@ DllMain (HINSTANCE module_handle, DWORD event, LPVOID reserved)
         /* Shouldn't happen.  */
         return FALSE;
 
-      shared_library_fullname = strdup (location);
+      /* Avoid a memory leak when the same DLL get attached, detached,
+         attached, detached, and so on.  This happens e.g. when a spell
+         checker DLL is used repeatedly by a mail program.  */
+      if (!(shared_library_fullname != NULL
+            && strcmp (shared_library_fullname, location) == 0))
+        /* Remember the full pathname of the shared library.  */
+        shared_library_fullname = strdup (location);
     }
 
   return TRUE;
-- 
2.39.5