aboutsummaryrefslogtreecommitdiff
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
parent7f71f9c1d6735e713de193faf03edb37c4bcb563 (diff)
downloadglibc-7e161bef0bc9d5ea5e6f3dd490ecd5da6f642671.zip
glibc-7e161bef0bc9d5ea5e6f3dd490ecd5da6f642671.tar.gz
glibc-7e161bef0bc9d5ea5e6f3dd490ecd5da6f642671.tar.bz2
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.
-rw-r--r--ChangeLog3
-rw-r--r--posix/getopt.c1
2 files changed, 3 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index ba702c0..48e5b03 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/posix/getopt.c b/posix/getopt.c
index f1fa016..e616aa6 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)