Hi, hackers
I noticed an inconsistency in how optind is handled when a required argument
is missing.
For short options, the current code handles the BADARG case as follows:
else if (argc <= ++optind)
{ /* no arg */
place = EMSG;
if (*optstring == ':')
return BADARG;
if (opterr)
fprintf(stderr,
"%s: option requires an argument -- %c\n",
argv[0], optopt);
return BADCH;
}
Here, place is set to EMSG and optind is incremented before returning BADARG.
However, for long options, the same logic currently sets place = EMSG and
increments optind after returning BADARG.
else
{
if (optstring[0] == ':')
return BADARG; <-- here, return before increasing optind
if (opterr && has_arg == required_argument)
fprintf(stderr,
"%s: option requires an argument -- %s\n",
argv[0], place);
place = EMSG;
optind++;
if (has_arg == required_argument)
return BADCH;
optarg = NULL;
}
The attached patch moves the place = EMSG and optind++ assignments to the
beginning of the long‑option error block, aligning the behavior with that of
short options.
Any thought?
--
Regards,
Japin Li
ChengDu WenWu Information Technology Co., Ltd.
>From 22914a78ccdfb1d05a907ef43474cb6253f62293 Mon Sep 17 00:00:00 2001
From: Japin Li <[email protected]>
Date: Tue, 21 Jul 2026 17:49:02 +0800
Subject: [PATCH v1] Fix optind handling inconsistency in getopt_long() for
missing argument
Move optind++ and place = EMSG before the BADARG return in the long option
path to match short option behavior and ensure consistent state.
---
src/port/getopt_long.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/port/getopt_long.c b/src/port/getopt_long.c
index 20953db9db1..a488a647889 100644
--- a/src/port/getopt_long.c
+++ b/src/port/getopt_long.c
@@ -145,6 +145,9 @@ retry:
}
else
{
+ place = EMSG;
+ optind++;
+
if (optstring[0] == ':')
return BADARG;
@@ -153,9 +156,6 @@ retry:
"%s: option requires an argument -- %s\n",
argv[0], place);
- place = EMSG;
- optind++;
-
if (has_arg == required_argument)
return BADCH;
optarg = NULL;
--
2.53.0