1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

Fix option argument lookup in in-tree getopt_long().

The in-tree getopt_long() moves each non-option to the end of argv,
which might put it right where an option's argument lookup expects
to find the argument.  For example, "vacuumdb postgres --jobs"
takes "postgres" as the number of jobs instead of complaining that
--jobs is missing its argument.  To fix, stop the argument lookups
at the start of the moved non-options, which we already track to
know when to stop scanning.

Oversight in commit 411b720343.

Author: Sehrope Sarkuni <sehrope@jackdb.com>
Reviewed-by: solai v <solai.cdac@gmail.com>
Discussion: https://postgr.es/m/CAH7T-arxDuVCSkorO%3Dk7%2BM-_JV0JFzMpN_EtKMyD2K0RDqZ2OA%40mail.gmail.com
Backpatch-through: 17
This commit is contained in:
Nathan Bossart
2026-09-11 15:18:40 -05:00
parent 3317dc4724
commit a11bce64a3
2 changed files with 11 additions and 7 deletions

View File

@@ -207,5 +207,9 @@ $node->command_fails_like(
[ 'vacuumdb', '-a', 'postgres' ],
qr/cannot vacuum all databases and a specific one at the same time/,
'cannot use option -a and a dbname as argument at the same time');
$node->command_fails_like(
[ 'vacuumdb', 'postgres', '--jobs' ],
qr/requires an argument/,
'option missing its argument after a non-option');
done_testing();

View File

@@ -66,6 +66,9 @@ getopt_long(int argc, char *const argv[],
static int nonopt_start = -1;
static bool force_nonopt = false;
if (nonopt_start == -1)
nonopt_start = argc;
if (!*place)
{ /* update scanning pointer */
char **args = (char **) argv;
@@ -75,7 +78,7 @@ retry:
/*
* If we are out of arguments or only non-options remain, return -1.
*/
if (optind >= argc || optind == nonopt_start)
if (optind >= nonopt_start)
{
place = EMSG;
nonopt_start = -1;
@@ -99,10 +102,7 @@ retry:
args[i] = args[i + 1];
args[argc - 1] = place;
if (nonopt_start == -1)
nonopt_start = argc - 1;
else
nonopt_start--;
nonopt_start--;
goto retry;
}
@@ -137,7 +137,7 @@ retry:
{
if (place[namelen] == '=')
optarg = place + namelen + 1;
else if (optind < argc - 1 &&
else if (optind < nonopt_start - 1 &&
has_arg == required_argument)
{
optind++;
@@ -220,7 +220,7 @@ retry:
{ /* need an argument */
if (*place) /* no white space */
optarg = place;
else if (argc <= ++optind)
else if (nonopt_start <= ++optind)
{ /* no arg */
place = EMSG;
if (*optstring == ':')