Fix a possible crash in the getopt_long reimplementation.

This commit is contained in:
Sam Hocevar 2016-09-20 08:57:14 +02:00
parent 6ca3b49e69
commit 192812ef51

View File

@ -1,7 +1,7 @@
/* /*
* zzuf - general purpose fuzzer * zzuf - general purpose fuzzer
* *
* Copyright © 20022015 Sam Hocevar <sam@hocevar.net> * Copyright © 20022016 Sam Hocevar <sam@hocevar.net>
* *
* This program is free software. It comes without any warranty, to * This program is free software. It comes without any warranty, to
* the extent permitted by applicable law. You can redistribute it * the extent permitted by applicable law. You can redistribute it
@ -19,7 +19,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#if defined HAVE_GETOPT_H && defined HAVE_GETOPT_LONG #if HAVE_GETOPT_H && HAVE_GETOPT_LONG
# include <getopt.h> # include <getopt.h>
#endif #endif
#include <stdint.h> #include <stdint.h>
@ -32,7 +32,7 @@ char *zz_optarg = NULL;
int zz_getopt(int argc, char * const _argv[], char const *optstring, int zz_getopt(int argc, char * const _argv[], char const *optstring,
zzuf_option_t const *longopts, int *longindex) zzuf_option_t const *longopts, int *longindex)
{ {
#if defined HAVE_GETOPT_LONG #if HAVE_GETOPT_LONG
optind = zz_optind; optind = zz_optind;
optarg = zz_optarg; optarg = zz_optarg;
int ret = getopt_long(argc, _argv, optstring, int ret = getopt_long(argc, _argv, optstring,
@ -68,8 +68,10 @@ int zz_getopt(int argc, char * const _argv[], char const *optstring,
{ {
if (flag[2] != '\0') if (flag[2] != '\0')
zz_optarg = flag + 2; zz_optarg = flag + 2;
else else if (zz_optind < argc)
zz_optarg = argv[zz_optind++]; zz_optarg = argv[zz_optind++];
else
goto too_few;
return ret; return ret;
} }
@ -110,7 +112,12 @@ int zz_getopt(int argc, char * const _argv[], char const *optstring,
*longindex = i; *longindex = i;
zz_optind++; zz_optind++;
if (longopts[i].has_arg) if (longopts[i].has_arg)
zz_optarg = argv[zz_optind++]; {
if (zz_optind < argc)
zz_optarg = argv[zz_optind++];
else
goto too_few;
}
return longopts[i].val; return longopts[i].val;
default: default:
break; break;
@ -119,6 +126,11 @@ int zz_getopt(int argc, char * const _argv[], char const *optstring,
bad_opt: bad_opt:
fprintf(stderr, "%s: unrecognized option `%s'\n", argv[0], flag); fprintf(stderr, "%s: unrecognized option `%s'\n", argv[0], flag);
return '?'; return '?';
too_few:
fprintf(stderr, "%s: option `%s' requires an argument\n",
argv[0], flag);
return '?';
} }
return -1; return -1;