Skip to content

Commit 6cb109a

Browse files
committed
Fix assorted issues in pg_ctl's pgwin32_CommandLine().
Ensure that the invocation command for postgres or pg_ctl runservice double-quotes the executable's pathname; failure to do this leads to trouble when the path contains spaces. Also, ensure that the path ends in ".exe" in both cases and uses backslashes rather than slashes as directory separators. The latter issue is reported to confuse some third-party tools such as Symantec Backup Exec. Also, rewrite the function to avoid buffer overrun issues by using a PQExpBuffer instead of a fixed-size static buffer. Combinations of very long executable pathnames and very long data directory pathnames could have caused trouble before, for example. Back-patch to all active branches, since this code has been like this for a long while. Naoya Anzai and Tom Lane, reviewed by Rajeev Rastogi
1 parent 8a7f446 commit 6cb109a

File tree

1 file changed

+41
-35
lines changed

1 file changed

+41
-35
lines changed

src/bin/pg_ctl/pg_ctl.c

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
#endif
1919

2020
#include "postgres_fe.h"
21+
2122
#include "libpq-fe.h"
23+
#include "pqexpbuffer.h"
2224

2325
#include <fcntl.h>
2426
#include <locale.h>
@@ -1038,16 +1040,13 @@ pgwin32_IsInstalled(SC_HANDLE hSCM)
10381040
static char *
10391041
pgwin32_CommandLine(bool registration)
10401042
{
1041-
static char cmdLine[MAXPGPATH];
1043+
PQExpBuffer cmdLine = createPQExpBuffer();
1044+
char cmdPath[MAXPGPATH];
10421045
int ret;
10431046

1044-
#ifdef __CYGWIN__
1045-
char buf[MAXPGPATH];
1046-
#endif
1047-
10481047
if (registration)
10491048
{
1050-
ret = find_my_exec(argv0, cmdLine);
1049+
ret = find_my_exec(argv0, cmdPath);
10511050
if (ret != 0)
10521051
{
10531052
write_stderr(_("%s: could not find own program executable\n"), progname);
@@ -1057,7 +1056,7 @@ pgwin32_CommandLine(bool registration)
10571056
else
10581057
{
10591058
ret = find_other_exec(argv0, "postgres", PG_BACKEND_VERSIONSTR,
1060-
cmdLine);
1059+
cmdPath);
10611060
if (ret != 0)
10621061
{
10631062
write_stderr(_("%s: could not find postgres program executable\n"), progname);
@@ -1067,50 +1066,57 @@ pgwin32_CommandLine(bool registration)
10671066

10681067
#ifdef __CYGWIN__
10691068
/* need to convert to windows path */
1070-
cygwin_conv_to_full_win32_path(cmdLine, buf);
1071-
strcpy(cmdLine, buf);
1069+
{
1070+
char buf[MAXPGPATH];
1071+
1072+
#if CYGWIN_VERSION_DLL_MAJOR >= 1007
1073+
cygwin_conv_path(CCP_POSIX_TO_WIN_A, cmdPath, buf, sizeof(buf));
1074+
#else
1075+
cygwin_conv_to_full_win32_path(cmdPath, buf);
1076+
#endif
1077+
strcpy(cmdPath, buf);
1078+
}
10721079
#endif
10731080

1081+
/* if path does not end in .exe, append it */
1082+
if (strlen(cmdPath) < 4 ||
1083+
pg_strcasecmp(cmdPath + strlen(cmdPath) - 4, ".exe") != 0)
1084+
snprintf(cmdPath + strlen(cmdPath), sizeof(cmdPath) - strlen(cmdPath),
1085+
".exe");
1086+
1087+
/* use backslashes in path to avoid problems with some third-party tools */
1088+
make_native_path(cmdPath);
1089+
1090+
/* be sure to double-quote the executable's name in the command */
1091+
appendPQExpBuffer(cmdLine, "\"%s\"", cmdPath);
1092+
1093+
/* append assorted switches to the command line, as needed */
1094+
10741095
if (registration)
1075-
{
1076-
if (pg_strcasecmp(cmdLine + strlen(cmdLine) - 4, ".exe"))
1077-
{
1078-
/* If commandline does not end in .exe, append it */
1079-
strcat(cmdLine, ".exe");
1080-
}
1081-
strcat(cmdLine, " runservice -N \"");
1082-
strcat(cmdLine, register_servicename);
1083-
strcat(cmdLine, "\"");
1084-
}
1096+
appendPQExpBuffer(cmdLine, " runservice -N \"%s\"",
1097+
register_servicename);
10851098

10861099
if (pg_data)
1087-
{
1088-
strcat(cmdLine, " -D \"");
1089-
strcat(cmdLine, pg_data);
1090-
strcat(cmdLine, "\"");
1091-
}
1100+
appendPQExpBuffer(cmdLine, " -D \"%s\"", pg_data);
10921101

10931102
if (registration && do_wait)
1094-
strcat(cmdLine, " -w");
1103+
appendPQExpBuffer(cmdLine, " -w");
10951104

10961105
if (registration && wait_seconds != DEFAULT_WAIT)
1097-
/* concatenate */
1098-
sprintf(cmdLine + strlen(cmdLine), " -t %d", wait_seconds);
1106+
appendPQExpBuffer(cmdLine, " -t %d", wait_seconds);
10991107

11001108
if (registration && silent_mode)
1101-
strcat(cmdLine, " -s");
1109+
appendPQExpBuffer(cmdLine, " -s");
11021110

11031111
if (post_opts)
11041112
{
1105-
strcat(cmdLine, " ");
1106-
if (registration)
1107-
strcat(cmdLine, " -o \"");
1108-
strcat(cmdLine, post_opts);
11091113
if (registration)
1110-
strcat(cmdLine, "\"");
1114+
appendPQExpBuffer(cmdLine, " -o \"%s\"", post_opts);
1115+
else
1116+
appendPQExpBuffer(cmdLine, " %s", post_opts);
11111117
}
11121118

1113-
return cmdLine;
1119+
return cmdLine->data;
11141120
}
11151121

11161122
static void
@@ -1546,7 +1552,7 @@ CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo, bool as_ser
15461552
*/
15471553
return r;
15481554
}
1549-
#endif
1555+
#endif /* defined(WIN32) || defined(__CYGWIN__) */
15501556

15511557
static void
15521558
do_advice(void)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy