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.
This commit is contained in:
Zack Weinberg 2017-04-01 10:01:40 -04:00
parent 7f71f9c1d6
commit 7e161bef0b
2 changed files with 3 additions and 1 deletions

View File

@ -1,5 +1,8 @@
2017-04-07 Zack Weinberg <zackw@panix.com>
* posix/getopt.c (_getopt_internal_r): Don't increment
d->optind a second time when reporting ambiguous -W options.
* posix/getopt_int.h: Include getopt.h.
Use impl-namespace names for all arguments to _getopt_internal and
_getopt_internal_r.

View File

@ -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)