bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] getopt-gnu: avoid crash in glibc getopt


From: Eric Blake
Subject: [PATCH] getopt-gnu: avoid crash in glibc getopt
Date: Thu, 7 Jul 2011 10:57:25 -0600

Use of "W;" in an option string may be rare, but we might as well
avoid crashing on it.

* m4/getopt.m4 (gl_GETOPT_CHECK_HEADRS): Detect the problem.
* tests/test-getopt.h (test_getopt): Enhance test.
* tests/test-getopt_long.h (test_getopt_long): Likewise.
* doc/posix-functions/getopt.texi (getopt): Document it.
* doc/glibc-functions/getopt_long.texi (getopt_long): Likewise.
* doc/glibc-functions/getopt_long_only.texi (getopt_long_only):
Likewise.
---

Tested on:
Fedora 14 with glibc 2.13: the patch replaces getopt, where beforehand
it did not and would fail the new test
glibc.git: glibc getopt is used as-is, and passes the new test
Cygwin 1.7.9: system getopt is still used and passes new test
FreeBSD 8.2: system getopt was already rejected for other reasons, so
without the previous patch to getopt.c this would fail the new test

 ChangeLog                                 |   11 +++++++++++
 doc/glibc-functions/getopt_long.texi      |    4 ++++
 doc/glibc-functions/getopt_long_only.texi |    4 ++++
 doc/posix-functions/getopt.texi           |    4 ++++
 m4/getopt.m4                              |    7 +++++++
 tests/test-getopt.h                       |   23 +++++++++++++++++++++++
 tests/test-getopt_long.h                  |   19 +++++++++++++++++++
 7 files changed, 72 insertions(+), 0 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index a5d52ee..e95d288 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2011-07-07  Eric Blake  <address@hidden>
+
+       getopt-gnu: avoid crash in glibc getopt
+       * m4/getopt.m4 (gl_GETOPT_CHECK_HEADRS): Detect the problem.
+       * tests/test-getopt.h (test_getopt): Enhance test.
+       * tests/test-getopt_long.h (test_getopt_long): Likewise.
+       * doc/posix-functions/getopt.texi (getopt): Document it.
+       * doc/glibc-functions/getopt_long.texi (getopt_long): Likewise.
+       * doc/glibc-functions/getopt_long_only.texi (getopt_long_only):
+       Likewise.
+
 2011-07-07  Ulrich Drepper  <address@hidden>

        getopt: handle W; without long options in getopt [BZ #12922]
diff --git a/doc/glibc-functions/getopt_long.texi 
b/doc/glibc-functions/getopt_long.texi
index f4d3561..c5e86fe 100644
--- a/doc/glibc-functions/getopt_long.texi
+++ b/doc/glibc-functions/getopt_long.texi
@@ -37,6 +37,10 @@ getopt_long
 @item
 This function is missing on some platforms:
 AIX 5.1, HP-UX 11, IRIX 6.5, OSF/1 5.1, Interix 3.5.
address@hidden
+This function crashes if the option string includes @code{W;} but
+there are no long options, on some platforms:
+glibc 2.14.
 @end itemize

 Portability problems not fixed by Gnulib:
diff --git a/doc/glibc-functions/getopt_long_only.texi 
b/doc/glibc-functions/getopt_long_only.texi
index 1b90c41..8931670 100644
--- a/doc/glibc-functions/getopt_long_only.texi
+++ b/doc/glibc-functions/getopt_long_only.texi
@@ -38,6 +38,10 @@ getopt_long_only
 This function is missing on some platforms:
 MacOS X 10.3, FreeBSD 5.2.1, NetBSD 5.0, AIX 5.1, HP-UX 11, IRIX 6.5,
 OSF/1 5.1, mingw, Interix 3.5.
address@hidden
+This function crashes if the option string includes @code{W;} but
+there are no long options, on some platforms:
+glibc 2.14.
 @end itemize

 Portability problems not fixed by Gnulib:
diff --git a/doc/posix-functions/getopt.texi b/doc/posix-functions/getopt.texi
index bab4922..099c2e3 100644
--- a/doc/posix-functions/getopt.texi
+++ b/doc/posix-functions/getopt.texi
@@ -48,6 +48,10 @@ getopt
 The function @code{getopt_long_only} is missing on some platforms:
 MacOS X 10.3, FreeBSD 5.2.1, NetBSD 5.0, AIX 5.1, HP-UX 11, IRIX 6.5,
 OSF/1 5.1, Solaris 9, mingw, Interix 3.5.
address@hidden
+This function crashes if the option string includes @code{W;} on some
+platforms:
+glibc 2.14.
 @end itemize

 Portability problems not fixed by Gnulib:
diff --git a/m4/getopt.m4 b/m4/getopt.m4
index 4d8450f..ffb9413 100644
--- a/m4/getopt.m4
+++ b/m4/getopt.m4
@@ -281,6 +281,13 @@ dnl is ambiguous with environment values that contain 
newlines.
                else if (getopt (3, argv, "+:a:b") != ':')
                  result |= 64;
              }
+             /* This code dumps core on glibc 2.14.  */
+             {
+               char *argv[] = { "program", "-W", "dummy", NULL };
+               optind = opterr = 1;
+               if (getopt (3, argv, "W;") != 'W')
+                 result |= 128;
+             }
              return result;
            ]])],
         [gl_cv_func_getopt_gnu=yes],
diff --git a/tests/test-getopt.h b/tests/test-getopt.h
index 9c877b3..8c4383f 100644
--- a/tests/test-getopt.h
+++ b/tests/test-getopt.h
@@ -1365,5 +1365,28 @@ test_getopt (void)
       ASSERT (optind == 3);
       ASSERT (!output);
     }
+
+  /* Check that 'W' does not dump core:
+     http://sourceware.org/bugzilla/show_bug.cgi?id=12922
+     Technically, POSIX says the presence of ';' in the opt-string
+     gives unspecified behavior, so we only test this when GNU compliance
+     is desired.  */
+  for (start = OPTIND_MIN; start <= 1; start++)
+    {
+      int argc = 0;
+      const char *argv[10];
+      int c;
+      int pos = ftell (stderr);
+
+      argv[argc++] = "program";
+      argv[argc++] = "-W";
+      argv[argc++] = "dummy";
+      argv[argc] = NULL;
+      optind = start;
+      opterr = 1;
+      ASSERT (getopt (argc, (char **) argv, "W;") == 'W');
+      ASSERT (ftell (stderr) == pos);
+      ASSERT (optind == 2);
+    }
 #endif /* GNULIB_TEST_GETOPT_GNU */
 }
diff --git a/tests/test-getopt_long.h b/tests/test-getopt_long.h
index 7a74867..c1035b1 100644
--- a/tests/test-getopt_long.h
+++ b/tests/test-getopt_long.h
@@ -314,6 +314,25 @@ test_getopt_long (void)
       }
   }

+  /* Test that 'W' does not dump core:
+     http://sourceware.org/bugzilla/show_bug.cgi?id=12922  */
+  {
+    int argc = 0;
+    const char *argv[10];
+    int option_index;
+    int c;
+
+    argv[argc++] = "program";
+    argv[argc++] = "-W";
+    argv[argc++] = "dummy";
+    argv[argc] = NULL;
+    optind = 1;
+    opterr = 0;
+    c = do_getopt_long (argc, argv, "W;", NULL, &option_index);
+    ASSERT (c == 'W');
+    ASSERT (optind == 2);
+  }
+
   /* Test processing of boolean short options.  */
   for (start = 0; start <= 1; start++)
     {
-- 
1.7.4.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]