Re: BUG #18971: Server passes an invalid (indirect) path in PGDATA to the external program

Laurenz Albe <laurenz.albe@cybertec.at>

From: Laurenz Albe <laurenz.albe@cybertec.at>
To: "David G. Johnston" <david.g.johnston@gmail.com>, Tom Lane <tgl@sss.pgh.pa.us>
Cc: Dmitry Kovalenko <d.kovalenko@postgrespro.ru>, pgsql-bugs@lists.postgresql.org
Date: 2025-06-29T06:00:11Z
Lists: pgsql-bugs
On Sat, 2025-06-28 at 14:12 -0700, David G. Johnston wrote:
> On Sat, Jun 28, 2025 at 1:19 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
> > I'm not sure which part of "don't rely on PGDATA" you didn't get.
> > Under normal circumstances, Postgres itself doesn't set that at all.
> 
> If we have to tell someone to not rely on a value that we've set we've
> done something wrong.

I am not sure that that is an accurate description.  Look at the code
in pg_ctl.c:

    /* process command-line options */
    while ((c = getopt_long(argc, argv, "cD:e:l:m:N:o:p:P:sS:t:U:wW",
                            long_options, &option_index)) != -1)
    {
        switch (c)
        {
            case 'D':
                {
                    char       *pgdata_D;

                    pgdata_D = pg_strdup(optarg);
                    canonicalize_path(pgdata_D);
                    setenv("PGDATA", pgdata_D, 1);

                    /*
                     * We could pass PGDATA just in an environment variable
                     * but we do -D too for clearer postmaster 'ps' display
                     */
                    pgdata_opt = psprintf("-D \"%s\" ", pgdata_D);
                    free(pgdata_D);
                    break;
                }

So we take the value specified with the -D option, canonicalize_path() it
and set it in the environment.  canonicalize_path() does the following:

/*
 * canonicalize_path()
 *
 *  Clean up path by:
 *      o  make Win32 path use Unix slashes
 *      o  remove trailing quote on Win32
 *      o  remove trailing slash
 *      o  remove duplicate (adjacent) separators
 *      o  remove '.' (unless path reduces to only '.')
 *      o  process '..' ourselves, removing it if possible
 *  Modifies path in-place.

So, essentially, Dmitry feeds a weird path to the -D option and then
complains that PGDATA is set to a weird value.

Yours,
Laurenz Albe