From 21019e77e85a65b8f362426f269a748ff21baa43 Mon Sep 17 00:00:00 2001
From: Christian Ullrich <christian.ullrich@traditionsa.lu>
Date: Wed, 30 Nov 2016 16:19:55 +0100
Subject: [PATCH 5/7] Do the process environment update first.

This closes a potential race that can happen if a new CRT is loaded while
pgwin32_putenv() is running. Per Noah Misch.
---
 src/port/win32env.c | 89 ++++++++++++++++++++++++++---------------------------
 1 file changed, 44 insertions(+), 45 deletions(-)

diff --git a/src/port/win32env.c b/src/port/win32env.c
index 7bccee6..60bf013 100644
--- a/src/port/win32env.c
+++ b/src/port/win32env.c
@@ -23,19 +23,6 @@ pgwin32_putenv(const char *envval)
 	char	   *envcpy;
 	char	   *cp;
 
-	/*
-	 * Each version of MSVCRT has its own _putenv() call in the runtime
-	 * library.
-	 *
-	 * mingw always uses MSVCRT.DLL, but if we are in a Visual C++
-	 * environment, attempt to update the environment in all MSVCRT modules
-	 * that are currently loaded, to work properly with any third party
-	 * libraries linked against a different MSVCRT but still relying on
-	 * environment variables.
-	 *
-	 * Also separately update the system environment that gets inherited by
-	 * subprocesses.
-	 */
 #ifdef _MSC_VER
 	typedef int (_cdecl * PUTENVPROC) (const char *);
 	static struct
@@ -66,7 +53,51 @@ pgwin32_putenv(const char *envval)
 		{ NULL, NULL, NULL }
 	};
 	int			i;
+#endif   /* _MSC_VER */
+
+	/*
+	 * Update the process environment - to make modifications visible to child
+	 * processes.
+	 *
+	 * Need a copy of the string so we can modify it.
+	 */
+	envcpy = strdup(envval);
+	if (!envcpy)
+		return -1;
+	cp = strchr(envcpy, '=');
+	if (cp == NULL)
+	{
+		free(envcpy);
+		return -1;
+	}
+	*cp = '\0';
+	cp++;
+	if (strlen(cp))
+	{
+		/*
+		 * Only call SetEnvironmentVariable() when we are adding a variable,
+		 * not when removing it. Calling it on both crashes on at least
+		 * certain versions of MingW.
+		 */
+		if (!SetEnvironmentVariable(envcpy, cp))
+		{
+			free(envcpy);
+			return -1;
+		}
+	}
+	free(envcpy);
 
+	/*
+	 * Each version of MSVCRT has its own _putenv() call in the runtime
+	 * library.
+	 *
+	 * mingw always uses MSVCRT.DLL, but if we are in a Visual C++
+	 * environment, attempt to update the environment in all MSVCRT modules
+	 * that are currently loaded, to work properly with any third party
+	 * libraries linked against a different MSVCRT but still relying on
+	 * environment variables.
+	 */
+#ifdef _MSC_VER
 	for (i = 0; rtmodules[i].modulename; i++)
 	{
 		if (rtmodules[i].putenvFunc == NULL)
@@ -102,38 +133,6 @@ pgwin32_putenv(const char *envval)
 	}
 #endif   /* _MSC_VER */
 
-	/*
-	 * Update the process environment - to make modifications visible to child
-	 * processes.
-	 *
-	 * Need a copy of the string so we can modify it.
-	 */
-	envcpy = strdup(envval);
-	if (!envcpy)
-		return -1;
-	cp = strchr(envcpy, '=');
-	if (cp == NULL)
-	{
-		free(envcpy);
-		return -1;
-	}
-	*cp = '\0';
-	cp++;
-	if (strlen(cp))
-	{
-		/*
-		 * Only call SetEnvironmentVariable() when we are adding a variable,
-		 * not when removing it. Calling it on both crashes on at least
-		 * certain versions of MingW.
-		 */
-		if (!SetEnvironmentVariable(envcpy, cp))
-		{
-			free(envcpy);
-			return -1;
-		}
-	}
-	free(envcpy);
-
 	/* Finally, update our "own" cache */
 	return _putenv(envval);
 }
-- 
2.10.2.windows.1

