]> Savannah Git Hosting - gnulib.git/commitdiff
getopt: fix fencepost error in ambiguous-W-option handling
authorZack Weinberg <zackw@panix.com>
Thu, 6 Apr 2017 18:14:13 +0000 (11:14 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Thu, 6 Apr 2017 22:42:03 +0000 (15:42 -0700)
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.

* lib/getopt.c (_getopt_internal_r): Don't increment
d->optind a second time when reporting ambiguous -W options.

ChangeLog
lib/getopt.c

index e61efb8902706131f9faacc124ef6f207270ee53..06da4900fc995f72b43927e8f03a6f5b6c0da74e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,23 @@
 2017-04-06  Zack Weinberg  <zackw@panix.com>
 
+       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.
+
+       * lib/getopt.c (_getopt_internal_r): Don't increment
+       d->optind a second time when reporting ambiguous -W options.
+
+
        getopt: clean up getopt.c and getopt1.c file headers
 
        In getopt.c, there is no need to include wchar.h at all, and it is
index 559e03bed3dc99ffe47f9e8e20639efd113c9918..757856b44698ca429dd753a62770d069ca00cfad 100644 (file)
@@ -887,7 +887,6 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
 #endif
              }
            d->__nextchar += strlen (d->__nextchar);
-           d->optind++;
            return '?';
          }
        if (pfound != NULL)