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