Remove arbitrary MAXPGPATH limit on command lengths in pg_ctl.

Replace fixed-length command buffers with psprintf() calls.  We didn't
have anything as convenient as psprintf() when this code was written,
but now that we do, there's little reason for the limitation to
stand.  Removing it eliminates some corner cases where (for example)
starting the postmaster with a whole lot of options fails.

Most individual file names that pg_ctl deals with are still restricted
to MAXPGPATH, but we've seldom had complaints about that limitation
so long as it only applies to one filename.

Back-patch to all supported branches.

Phil Krylov

Discussion: https://postgr.es/m/567e199c6b97ee19deee600311515b86@krylov.eu
This commit is contained in:
Tom Lane 2021-09-03 21:04:44 -04:00
parent 132be60006
commit 742b30caee

View File

@ -442,7 +442,7 @@ free_readfile(char **optlines)
static pgpid_t static pgpid_t
start_postmaster(void) start_postmaster(void)
{ {
char cmd[MAXPGPATH]; char *cmd;
#ifndef WIN32 #ifndef WIN32
pgpid_t pm_pid; pgpid_t pm_pid;
@ -487,11 +487,11 @@ start_postmaster(void)
* has the same PID as the current child process. * has the same PID as the current child process.
*/ */
if (log_file != NULL) if (log_file != NULL)
snprintf(cmd, MAXPGPATH, "exec \"%s\" %s%s < \"%s\" >> \"%s\" 2>&1", cmd = psprintf("exec \"%s\" %s%s < \"%s\" >> \"%s\" 2>&1",
exec_path, pgdata_opt, post_opts, exec_path, pgdata_opt, post_opts,
DEVNULL, log_file); DEVNULL, log_file);
else else
snprintf(cmd, MAXPGPATH, "exec \"%s\" %s%s < \"%s\" 2>&1", cmd = psprintf("exec \"%s\" %s%s < \"%s\" 2>&1",
exec_path, pgdata_opt, post_opts, DEVNULL); exec_path, pgdata_opt, post_opts, DEVNULL);
(void) execl("/bin/sh", "/bin/sh", "-c", cmd, (char *) NULL); (void) execl("/bin/sh", "/bin/sh", "-c", cmd, (char *) NULL);
@ -553,11 +553,11 @@ start_postmaster(void)
else else
close(fd); close(fd);
snprintf(cmd, MAXPGPATH, "\"%s\" /C \"\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1\"", cmd = psprintf("\"%s\" /C \"\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1\"",
comspec, exec_path, pgdata_opt, post_opts, DEVNULL, log_file); comspec, exec_path, pgdata_opt, post_opts, DEVNULL, log_file);
} }
else else
snprintf(cmd, MAXPGPATH, "\"%s\" /C \"\"%s\" %s%s < \"%s\" 2>&1\"", cmd = psprintf("\"%s\" /C \"\"%s\" %s%s < \"%s\" 2>&1\"",
comspec, exec_path, pgdata_opt, post_opts, DEVNULL); comspec, exec_path, pgdata_opt, post_opts, DEVNULL);
if (!CreateRestrictedProcess(cmd, &pi, false)) if (!CreateRestrictedProcess(cmd, &pi, false))
@ -828,7 +828,7 @@ find_other_exec_or_die(const char *argv0, const char *target, const char *versio
static void static void
do_init(void) do_init(void)
{ {
char cmd[MAXPGPATH]; char *cmd;
if (exec_path == NULL) if (exec_path == NULL)
exec_path = find_other_exec_or_die(argv0, "initdb", "initdb (PostgreSQL) " PG_VERSION "\n"); exec_path = find_other_exec_or_die(argv0, "initdb", "initdb (PostgreSQL) " PG_VERSION "\n");
@ -840,10 +840,10 @@ do_init(void)
post_opts = ""; post_opts = "";
if (!silent_mode) if (!silent_mode)
snprintf(cmd, MAXPGPATH, "\"%s\" %s%s", cmd = psprintf("\"%s\" %s%s",
exec_path, pgdata_opt, post_opts); exec_path, pgdata_opt, post_opts);
else else
snprintf(cmd, MAXPGPATH, "\"%s\" %s%s > \"%s\"", cmd = psprintf("\"%s\" %s%s > \"%s\"",
exec_path, pgdata_opt, post_opts, DEVNULL); exec_path, pgdata_opt, post_opts, DEVNULL);
if (system(cmd) != 0) if (system(cmd) != 0)
@ -2181,9 +2181,9 @@ set_starttype(char *starttypeopt)
static void static void
adjust_data_dir(void) adjust_data_dir(void)
{ {
char cmd[MAXPGPATH], char filename[MAXPGPATH];
filename[MAXPGPATH], char *my_exec_path,
*my_exec_path; *cmd;
FILE *fd; FILE *fd;
/* do nothing if we're working without knowledge of data dir */ /* do nothing if we're working without knowledge of data dir */
@ -2213,7 +2213,7 @@ adjust_data_dir(void)
my_exec_path = pg_strdup(exec_path); my_exec_path = pg_strdup(exec_path);
/* it's important for -C to be the first option, see main.c */ /* it's important for -C to be the first option, see main.c */
snprintf(cmd, MAXPGPATH, "\"%s\" -C data_directory %s%s", cmd = psprintf("\"%s\" -C data_directory %s%s",
my_exec_path, my_exec_path,
pgdata_opt ? pgdata_opt : "", pgdata_opt ? pgdata_opt : "",
post_opts ? post_opts : ""); post_opts ? post_opts : "");