bug-gnulib
[Top][All Lists]
Advanced

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

[PATCH] Check malloc result in getopt_long


From: Tobias Stoeckmann
Subject: [PATCH] Check malloc result in getopt_long
Date: Mon, 16 Feb 2015 21:06:22 +0100

In contrast to glibc's getopt implementation, this one uses malloc instead
of alloca. While in general this is a good idea, malloc returns NULL in
case of error, therefore the return value should be checked.

The fprintf statements are copied from the same source file; I am rather
indifferent about the error message.

Using coreutils' ls (I verified that gnulib's getopt is used on my system):

tobias:~/git/coreutils$ ulimit -Sv 4226
tobias:~/git/coreutils$ ./src/ls --t
Segmentation fault

With this patch:

tobias:~/git/coreutils$ ./src/ls --t
./src/ls: out of memory, dropping option 'time' while resolving ambiguity
./src/ls: out of memory, dropping option 'time-style' while resolving ambiguity
./src/ls: option '--tabsize' requires an argument
Try './src/ls --help' for more information.

With enough memory:

tobias:~/git/coreutils$ ./src/ls --t
./src/ls: option '--t' is ambiguous; possibilities: '--tabsize' '--time-style' 
'--time'
Try './src/ls --help' for more information.
---
 lib/getopt.c | 43 ++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 40 insertions(+), 3 deletions(-)

diff --git a/lib/getopt.c b/lib/getopt.c
index 3b9c585..c3eb7ad 100644
--- a/lib/getopt.c
+++ b/lib/getopt.c
@@ -521,9 +521,46 @@ _getopt_internal_r (int argc, char **argv, const char 
*optstring,
               {
                 /* Second or later nonexact match found.  */
                 struct option_list *newp = malloc (sizeof (*newp));
-                newp->p = p;
-                newp->next = ambig_list;
-                ambig_list = newp;
+                if (newp == NULL)
+                  {
+#if defined _LIBC && defined USE_IN_LIBIO
+                    char *buf = NULL;
+                    size_t buflen = 0;
+
+                    FILE *fp = open_memstream (&buf, &buflen);
+                    if (fp != NULL)
+                      {
+                        fprintf (fp, _("\
+%s: out of memory, dropping option '%s' while resolving ambiguity\n"),
+                                 argv[0], p->name);
+
+                        if (__builtin_expect (fclose (fp) != EOF, 1))
+                          {
+                            _IO_flockfile (stderr);
+
+                            int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+                            ((_IO_FILE *) stderr)->_flags2 |= 
_IO_FLAGS2_NOTCANCEL;
+
+                            __fxprintf (NULL, "%s", buf);
+
+                            ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+                            _IO_funlockfile (stderr);
+
+                            free (buf);
+                          }
+                      }
+#else
+                    fprintf (stderr, _("\
+%s: out of memory, dropping option '%s' while resolving ambiguity\n"),
+                             argv[0], p->name);
+#endif
+                  }
+                else
+                  {
+                    newp->p = p;
+                    newp->next = ambig_list;
+                    ambig_list = newp;
+                  }
               }
           }
 
-- 
2.3.0




reply via email to

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