about summary refs log tree commit diff
path: root/posix/getopt.c
diff options
context:
space:
mode:
authorZack Weinberg <zackw@panix.com>2017-04-01 10:01:40 -0400
committerZack Weinberg <zackw@panix.com>2017-04-07 07:47:58 -0400
commit7e161bef0bc9d5ea5e6f3dd490ecd5da6f642671 (patch)
tree36eed7d8575ac380c467429ef3bd76cf5e73fdae /posix/getopt.c
parent7f71f9c1d6735e713de193faf03edb37c4bcb563 (diff)
downloadglibc-7e161bef0bc9d5ea5e6f3dd490ecd5da6f642671.tar.gz
glibc-7e161bef0bc9d5ea5e6f3dd490ecd5da6f642671.tar.xz
glibc-7e161bef0bc9d5ea5e6f3dd490ecd5da6f642671.zip
getopt: fix fencepost error in ambiguous-W-option handling
getopt_long contains an undocumented (AFAICT) feature in which, if you
put "W;" in the short-options list, then '-W foo' and '-Wfoo' are
treated as equivalent to '--foo'.  This is implemented with a partial
second copy of the code for handling long options, and that code
increments optind one too many times when recovering from an ambiguous
abbreviated option, which can cause the main loop to walk past the end
of argv and crash.

I discovered this while writing a test case that tries to exercise all
of getopt's error reporting paths; I wouldn't be surprised to learn
that this feature is never used by real applications.

	* posix/getopt.c (_getopt_internal_r): Don't increment
	d->optind a second time when reporting ambiguous -W options.
Diffstat (limited to 'posix/getopt.c')
-rw-r--r--posix/getopt.c1
1 files changed, 0 insertions, 1 deletions
diff --git a/posix/getopt.c b/posix/getopt.c
index f1fa0166d8..e616aa6e4d 100644
--- a/posix/getopt.c
+++ b/posix/getopt.c
@@ -850,7 +850,6 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
 #endif
 	      }
 	    d->__nextchar += strlen (d->__nextchar);
-	    d->optind++;
 	    return '?';
 	  }
 	if (pfound != NULL)