According to [1], windows does not support setenv, so for the patch to work 
[3],  would need to add it.
With the possibility of setenv going further [2], I am submitting in this 
thread, the patch to add setenv support on the windows side, avoiding starting 
a new trhead.
It is based on pre-existing functions, and seeks to correctly emulate the 
functioning of the POSIX setenv, but has not yet been tested.

If this work is not acceptable then it is finished. And two memory leaks and a 
possible access beyond heap bounds, reported and not fixed.

regards,
Ranier Vilela

[1] https://www.postgresql.org/message-id/29478.1576537771%40sss.pgh.pa.us
[2] https://www.postgresql.org/message-id/30119.1576538578%40sss.pgh.pa.us
[3] 
https://www.postgresql.org/message-id/SN2PR05MB264066382E2CC75E734492C8E3510%40SN2PR05MB2640.namprd05.prod.outlook.com
diff --git a/src/common/exec.c b/src/common/exec.c
index 92dc3134a1..82e94b4df1 100644
--- a/src/common/exec.c
+++ b/src/common/exec.c
@@ -72,14 +72,15 @@ validate_exec(const char *path)
 	int			is_x;
 
 #ifdef WIN32
-	char		path_exe[MAXPGPATH + sizeof(".exe") - 1];
+	char		path_exe[MAXPGPATH + sizeof(".exe")];
+	int             path_len;
 
 	/* Win32 requires a .exe suffix for stat() */
-	if (strlen(path) >= strlen(".exe") &&
-		pg_strcasecmp(path + strlen(path) - strlen(".exe"), ".exe") != 0)
+	path_len = strlen(path);
+	if (path_len >= (sizeof(".exe") - 1) &&
+		pg_strcasecmp(path + path_len - (sizeof(".exe") - 1), ".exe") != 0)
 	{
-		strlcpy(path_exe, path, sizeof(path_exe) - 4);
-		strcat(path_exe, ".exe");
+		snprintf(path_exe, sizeof(path_exe) - 5, "%s.exe", path);
 		path = path_exe;
 	}
 #endif
@@ -566,11 +567,8 @@ set_pglocale_pgservice(const char *argv0, const char *app)
 {
 	char		path[MAXPGPATH];
 	char		my_exec_path[MAXPGPATH];
-	char		env_path[MAXPGPATH + sizeof("PGSYSCONFDIR=")];	/* longer than
-																 * PGLOCALEDIR */
-	char	   *dup_path;
 
-	/* don't set LC_ALL in the backend */
+        /* don't set LC_ALL in the backend */
 	if (strcmp(app, PG_TEXTDOMAIN("postgres")) != 0)
 	{
 		setlocale(LC_ALL, "");
@@ -596,25 +594,19 @@ set_pglocale_pgservice(const char *argv0, const char *app)
 
 	if (getenv("PGLOCALEDIR") == NULL)
 	{
-		/* set for libpq to use */
-		snprintf(env_path, sizeof(env_path), "PGLOCALEDIR=%s", path);
-		canonicalize_path(env_path + 12);
-		dup_path = strdup(env_path);
-		if (dup_path)
-			putenv(dup_path);
+	    /* set for libpq to use */
+	    canonicalize_path(path);
+            setenv("PGLOCALEDIR", path, 1);
 	}
 #endif
 
 	if (getenv("PGSYSCONFDIR") == NULL)
 	{
-		get_etc_path(my_exec_path, path);
-
-		/* set for libpq to use */
-		snprintf(env_path, sizeof(env_path), "PGSYSCONFDIR=%s", path);
-		canonicalize_path(env_path + 13);
-		dup_path = strdup(env_path);
-		if (dup_path)
-			putenv(dup_path);
+	    get_etc_path(my_exec_path, path);
+
+	    /* set for libpq to use */
+	    canonicalize_path(path);
+            setenv("PGSYSCONFDIR", path, 1);
 	}
 }
 

diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index 275f3bb699..33dc9bf5ad 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -65,7 +65,7 @@ my @frontend_uselibpgcommon = (
 my $frontend_extralibs = {
 	'initdb'     => ['ws2_32.lib'],
 	'pg_restore' => ['ws2_32.lib'],
-	'pgbench'    => ['ws2_32.lib'],
+	'pgbench'    => ['ws2_32.lib', 'bcrypt.lib'],
 	'psql'       => ['ws2_32.lib']
 };
 my $frontend_extraincludes = {
@@ -184,6 +184,7 @@ sub mkvcbuild
 	$postgres->AddFiles('src/backend/utils/adt', 'jsonpath_scan.l',
 		'jsonpath_gram.y');
 	$postgres->AddDefine('BUILDING_DLL');
+	$postgres->AddLibrary('bcrypt.lib') if ($vsVersion > '12.00');
 	$postgres->AddLibrary('secur32.lib');
 	$postgres->AddLibrary('ws2_32.lib');
 	$postgres->AddLibrary('wldap32.lib') if ($solution->{options}->{ldap});
@@ -246,6 +247,7 @@ sub mkvcbuild
 	$libpq->AddDefine('FRONTEND');
 	$libpq->AddDefine('UNSAFE_STAT_OK');
 	$libpq->AddIncludeDir('src/port');
+	$libpq->AddLibrary('bcrypt.lib')  if ($vsVersion > '12.00');
 	$libpq->AddLibrary('secur32.lib');
 	$libpq->AddLibrary('ws2_32.lib');
 	$libpq->AddLibrary('wldap32.lib') if ($solution->{options}->{ldap});
diff --git a/src/include/port/win32_port.h b/src/include/port/win32_port.h
index c459a2417d..1ffddcceee 100644
--- a/src/include/port/win32_port.h
+++ b/src/include/port/win32_port.h
@@ -463,6 +463,7 @@ extern void _dosmaperr(unsigned long);
 /* in port/win32env.c */
 extern int	pgwin32_putenv(const char *);
 extern void pgwin32_unsetenv(const char *);
+extern int	pgwin32_setenv(const char *name, const char *envval, int overwrite);
 
 /* in port/win32security.c */
 extern int	pgwin32_is_service(void);
@@ -473,6 +474,7 @@ extern BOOL AddUserToTokenDacl(HANDLE hToken);
 
 #define putenv(x) pgwin32_putenv(x)
 #define unsetenv(x) pgwin32_unsetenv(x)
+#define setenv(n,v,o) pgwin32_setenv(n, v, o)
 
 /* Things that exist in MinGW headers, but need to be added to MSVC */
 #ifdef _MSC_VER
diff --git a/src/port/win32env.c b/src/port/win32env.c
index 6f4994c96a..e9845a78c8 100644
--- a/src/port/win32env.c
+++ b/src/port/win32env.c
@@ -123,3 +123,35 @@ pgwin32_unsetenv(const char *name)
 	pgwin32_putenv(envbuf);
 	free(envbuf);
 }
+
+
+int
+pgwin32_setenv(const char *name, const char *envval, int overwrite)
+{
+        if (name == NULL)
+            return -1;
+
+        if (overwrite || !getenv(name)) {
+           char *envbuf;
+           int  name_len;
+
+           name_len = strlen(name);
+           if (envval != NULL) {
+               envbuf = (char *) malloc(name_len + strlen(envval) + 2);
+	       if (!envbuf)
+		   return -1;
+ 
+	       sprintf(envbuf, "%s=%s", name, envval);
+           } else {
+               envbuf = (char *) malloc(name_len + 2);
+	       if (!envbuf)
+		   return -1;
+ 
+	       sprintf(envbuf, "%s=", name);
+           }
+	   pgwin32_putenv(envbuf);
+	   free(envbuf);
+        }
+
+        return 0;
+}

Reply via email to