* Reimplemented getopt_long. We use our replacement even if simple getopt
is available on the operating system.
This commit is contained in:
+7
-2
@@ -57,11 +57,16 @@ AC_TRY_COMPILE([#include <sys/types.h>
|
||||
AC_MSG_RESULT($ac_v_recv_t)
|
||||
AC_DEFINE_UNQUOTED(RECV_T, $ac_v_recv_t, [Define to the recv() return type])
|
||||
|
||||
ac_cv_have_getopt_long="no"
|
||||
AC_CHECK_FUNCS(getopt_long,
|
||||
[AC_DEFINE(HAVE_GETOPT_LONG, 1, Define to 1 if you have the `getopt_long' function.)],
|
||||
[ac_cv_have_getopt_long="yes"],
|
||||
[AC_CHECK_LIB(gnugetopt, getopt_long,
|
||||
[AC_DEFINE(HAVE_GETOPT_LONG, 1, Define to 1 if you have the `getopt_long' function.)
|
||||
[ac_cv_have_getopt_long="yes"
|
||||
GETOPT_LIBS="${GETOPT_LIBS} -lgnugetopt"])])
|
||||
if test "$ac_cv_have_getopt_long" != "no"; then
|
||||
AC_DEFINE(HAVE_GETOPT_LONG, 1, Define to 1 if you have the `getopt_long' function.)
|
||||
fi
|
||||
AM_CONDITIONAL(NEED_GETOPT_LONG, test "$ac_cv_have_getopt_long" = "no")
|
||||
AC_SUBST(GETOPT_LIBS)
|
||||
|
||||
AC_CHECK_LIB(m, log, [MATH_LIBS="-lm"])
|
||||
|
||||
+5
-1
@@ -1,9 +1,13 @@
|
||||
# $Id$
|
||||
|
||||
COMMON = random.c random.h fd.c fd.h fuzz.c fuzz.h
|
||||
if NEED_GETOPT_LONG
|
||||
GETOPT = mygetopt.c mygetopt.h
|
||||
endif
|
||||
|
||||
bin_PROGRAMS = zzuf
|
||||
zzuf_SOURCES = zzuf.c $(COMMON) opts.c opts.h md5.c md5.h timer.c timer.h
|
||||
zzuf_SOURCES = zzuf.c $(COMMON) $(GETOPT) \
|
||||
opts.c opts.h md5.c md5.h timer.c timer.h
|
||||
zzuf_CFLAGS = -DLIBDIR=\"$(libdir)/zzuf\"
|
||||
zzuf_LDFLAGS = $(MATH_LIBS) $(WINSOCK2_LIBS)
|
||||
|
||||
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* zzuf - general purpose fuzzer
|
||||
* Copyright (c) 2002, 2007 Sam Hocevar <sam@zoy.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
*/
|
||||
|
||||
/*
|
||||
* mygetopt.c: getopt_long reimplementation
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
#elif defined HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mygetopt.h"
|
||||
|
||||
int myoptind = 1;
|
||||
char *myoptarg = NULL;
|
||||
|
||||
/* XXX: this getopt_long implementation should not be trusted for other
|
||||
* applications without any serious peer reviewing. It “just works” with
|
||||
* zzuf but may fail miserably in other programs. */
|
||||
int mygetopt(int argc, char * const _argv[], const char *optstring,
|
||||
const struct myoption *longopts, int *longindex)
|
||||
{
|
||||
char **argv = (char **)(uintptr_t)_argv;
|
||||
char *flag;
|
||||
int i;
|
||||
|
||||
if(myoptind >= argc)
|
||||
return -1;
|
||||
|
||||
flag = argv[myoptind];
|
||||
|
||||
if(flag[0] == '-' && flag[1] != '-')
|
||||
{
|
||||
char *tmp;
|
||||
int ret = flag[1];
|
||||
|
||||
if(ret == '\0')
|
||||
return -1;
|
||||
|
||||
tmp = strchr(optstring, ret);
|
||||
if(!tmp || ret == ':')
|
||||
return '?';
|
||||
|
||||
myoptind++;
|
||||
if(tmp[1] == ':')
|
||||
{
|
||||
if(flag[2] != '\0')
|
||||
myoptarg = tmp + 2;
|
||||
else
|
||||
myoptarg = argv[myoptind++];
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(flag[2] != '\0')
|
||||
{
|
||||
flag[1] = '-';
|
||||
myoptind--;
|
||||
argv[myoptind]++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(flag[0] == '-' && flag[1] == '-')
|
||||
{
|
||||
if(flag[2] == '\0')
|
||||
return -1;
|
||||
|
||||
for(i = 0; longopts[i].name; i++)
|
||||
{
|
||||
int l = strlen(longopts[i].name);
|
||||
|
||||
if(strncmp(flag + 2, longopts[i].name, l))
|
||||
continue;
|
||||
|
||||
switch(flag[2 + l])
|
||||
{
|
||||
case '=':
|
||||
if(!longopts[i].has_arg)
|
||||
goto bad_opt;
|
||||
if(longindex)
|
||||
*longindex = i;
|
||||
myoptind++;
|
||||
myoptarg = flag + 2 + l + 1;
|
||||
return longopts[i].val;
|
||||
case '\0':
|
||||
if(longindex)
|
||||
*longindex = i;
|
||||
myoptind++;
|
||||
if(longopts[i].has_arg)
|
||||
myoptarg = argv[myoptind++];
|
||||
return longopts[i].val;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
bad_opt:
|
||||
fprintf(stderr, "%s: unrecognized option `%s'\n", argv[0], flag);
|
||||
return '?';
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* zzuf - general purpose fuzzer
|
||||
* Copyright (c) 2002, 2007 Sam Hocevar <sam@zoy.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
*/
|
||||
|
||||
/*
|
||||
* mygetopt.h: getopt_long reimplementation
|
||||
*/
|
||||
|
||||
struct myoption
|
||||
{
|
||||
const char *name;
|
||||
int has_arg;
|
||||
int *flag;
|
||||
int val;
|
||||
};
|
||||
|
||||
extern int myoptind;
|
||||
extern char *myoptarg;
|
||||
|
||||
int mygetopt(int, char * const[], const char *, const struct myoption *, int *);
|
||||
|
||||
+47
-94
@@ -23,7 +23,9 @@
|
||||
#elif defined HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
#if defined HAVE_GETOPT_H
|
||||
#if !defined HAVE_GETOPT_LONG
|
||||
# include "mygetopt.h"
|
||||
#elif defined HAVE_GETOPT_H
|
||||
# include <getopt.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
@@ -62,6 +64,13 @@
|
||||
#include "md5.h"
|
||||
#include "timer.h"
|
||||
|
||||
#if defined HAVE_GETOPT_LONG
|
||||
# define mygetopt getopt_long
|
||||
# define myoptind optind
|
||||
# define myoptarg optarg
|
||||
# define myoption option
|
||||
#endif
|
||||
|
||||
#if !defined SIGKILL
|
||||
# define SIGKILL 9
|
||||
#endif
|
||||
@@ -93,9 +102,7 @@ static char *merge_regex(char *, char *);
|
||||
static char *merge_file(char *, char *);
|
||||
#endif
|
||||
static void version(void);
|
||||
#if defined HAVE_GETOPT_H
|
||||
static void usage(void);
|
||||
#endif
|
||||
|
||||
#if defined HAVE_WINDOWS_H
|
||||
static inline void addcpy(void *buf, void *x)
|
||||
@@ -124,25 +131,19 @@ int main(int argc, char *argv[])
|
||||
int cmdline = 0;
|
||||
#endif
|
||||
int i;
|
||||
#if !defined HAVE_GETOPT_H
|
||||
# define MOREINFO "Usage: %s message...\n"
|
||||
int optind = 1;
|
||||
#endif
|
||||
|
||||
_zz_opts_init(opts);
|
||||
|
||||
#if defined HAVE_GETOPT_H
|
||||
for(;;)
|
||||
{
|
||||
# if defined HAVE_REGEX_H
|
||||
# define OPTSTR "Ab:B:cC:dD:E:f:F:iI:mM:nP:qr:R:s:ST:vxhV"
|
||||
# else
|
||||
# define OPTSTR "Ab:B:C:dD:f:F:imM:nP:qr:R:s:ST:vxhV"
|
||||
# endif
|
||||
# if defined HAVE_GETOPT_LONG
|
||||
# define MOREINFO "Try `%s --help' for more information.\n"
|
||||
#if defined HAVE_REGEX_H
|
||||
# define OPTSTR "Ab:B:cC:dD:E:f:F:iI:mM:nP:qr:R:s:ST:vxhV"
|
||||
#else
|
||||
# define OPTSTR "Ab:B:C:dD:f:F:imM:nP:qr:R:s:ST:vxhV"
|
||||
#endif
|
||||
#define MOREINFO "Try `%s --help' for more information.\n"
|
||||
int option_index = 0;
|
||||
static struct option long_options[] =
|
||||
static struct myoption long_options[] =
|
||||
{
|
||||
/* Long option, needs arg, flag, short option */
|
||||
{ "autoinc", 0, NULL, 'A' },
|
||||
@@ -179,11 +180,8 @@ int main(int argc, char *argv[])
|
||||
{ "version", 0, NULL, 'V' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
int c = getopt_long(argc, argv, OPTSTR, long_options, &option_index);
|
||||
# else
|
||||
# define MOREINFO "Try `%s -h' for more information.\n"
|
||||
int c = getopt(argc, argv, OPTSTR);
|
||||
# endif
|
||||
int c = mygetopt(argc, argv, OPTSTR, long_options, &option_index);
|
||||
|
||||
if(c == -1)
|
||||
break;
|
||||
|
||||
@@ -193,10 +191,10 @@ int main(int argc, char *argv[])
|
||||
setenv("ZZUF_AUTOINC", "1", 1);
|
||||
break;
|
||||
case 'b': /* --bytes */
|
||||
opts->bytes = optarg;
|
||||
opts->bytes = myoptarg;
|
||||
break;
|
||||
case 'B': /* --max-bytes */
|
||||
opts->maxbytes = atoi(optarg);
|
||||
opts->maxbytes = atoi(myoptarg);
|
||||
break;
|
||||
#if defined HAVE_REGEX_H
|
||||
case 'c': /* --cmdline */
|
||||
@@ -204,7 +202,7 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
#endif
|
||||
case 'C': /* --max-crashes */
|
||||
opts->maxcrashes = atoi(optarg);
|
||||
opts->maxcrashes = atoi(myoptarg);
|
||||
if(opts->maxcrashes <= 0)
|
||||
opts->maxcrashes = 0;
|
||||
break;
|
||||
@@ -212,34 +210,36 @@ int main(int argc, char *argv[])
|
||||
setenv("ZZUF_DEBUG", DEBUG_FILENO_STR, 1);
|
||||
break;
|
||||
case 'D': /* --delay */
|
||||
opts->delay = (int64_t)(atof(optarg) * 1000000.0);
|
||||
opts->delay = (int64_t)(atof(myoptarg) * 1000000.0);
|
||||
break;
|
||||
#if defined HAVE_REGEX_H
|
||||
case 'E': /* --exclude */
|
||||
exclude = merge_regex(exclude, optarg);
|
||||
exclude = merge_regex(exclude, myoptarg);
|
||||
if(!exclude)
|
||||
{
|
||||
printf("%s: invalid regex -- `%s'\n", argv[0], optarg);
|
||||
fprintf(stderr, "%s: invalid regex -- `%s'\n",
|
||||
argv[0], myoptarg);
|
||||
_zz_opts_fini(opts);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 'f': /* --fuzzing */
|
||||
opts->fuzzing = optarg;
|
||||
opts->fuzzing = myoptarg;
|
||||
break;
|
||||
case 'F': /* --max-forks */
|
||||
opts->maxchild = atoi(optarg) > 1 ? atoi(optarg) : 1;
|
||||
opts->maxchild = atoi(myoptarg) > 1 ? atoi(myoptarg) : 1;
|
||||
break;
|
||||
case 'i': /* --stdin */
|
||||
setenv("ZZUF_STDIN", "1", 1);
|
||||
break;
|
||||
#if defined HAVE_REGEX_H
|
||||
case 'I': /* --include */
|
||||
include = merge_regex(include, optarg);
|
||||
include = merge_regex(include, myoptarg);
|
||||
if(!include)
|
||||
{
|
||||
printf("%s: invalid regex -- `%s'\n", argv[0], optarg);
|
||||
fprintf(stderr, "%s: invalid regex -- `%s'\n",
|
||||
argv[0], myoptarg);
|
||||
_zz_opts_fini(opts);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -251,36 +251,36 @@ int main(int argc, char *argv[])
|
||||
#if defined HAVE_SETRLIMIT
|
||||
case 'M': /* --max-memory */
|
||||
setenv("ZZUF_MEMORY", "1", 1);
|
||||
opts->maxmem = atoi(optarg);
|
||||
opts->maxmem = atoi(myoptarg);
|
||||
break;
|
||||
#endif
|
||||
case 'n': /* --network */
|
||||
setenv("ZZUF_NETWORK", "1", 1);
|
||||
break;
|
||||
case 'P': /* --protect */
|
||||
opts->protect = optarg;
|
||||
opts->protect = myoptarg;
|
||||
break;
|
||||
case 'q': /* --quiet */
|
||||
opts->quiet = 1;
|
||||
break;
|
||||
case 'r': /* --ratio */
|
||||
tmp = strchr(optarg, ':');
|
||||
opts->minratio = atof(optarg);
|
||||
tmp = strchr(myoptarg, ':');
|
||||
opts->minratio = atof(myoptarg);
|
||||
opts->maxratio = tmp ? atof(tmp + 1) : opts->minratio;
|
||||
break;
|
||||
case 'R': /* --refuse */
|
||||
opts->refuse = optarg;
|
||||
opts->refuse = myoptarg;
|
||||
break;
|
||||
case 's': /* --seed */
|
||||
tmp = strchr(optarg, ':');
|
||||
opts->seed = atol(optarg);
|
||||
tmp = strchr(myoptarg, ':');
|
||||
opts->seed = atol(myoptarg);
|
||||
opts->endseed = tmp ? (uint32_t)atoi(tmp + 1) : opts->seed + 1;
|
||||
break;
|
||||
case 'S': /* --signal */
|
||||
setenv("ZZUF_SIGNAL", "1", 1);
|
||||
break;
|
||||
case 'T': /* --max-time */
|
||||
opts->maxtime = (int64_t)(atof(optarg) * 1000000.0);
|
||||
opts->maxtime = (int64_t)(atof(myoptarg) * 1000000.0);
|
||||
break;
|
||||
case 'x': /* --check-exit */
|
||||
opts->checkexit = 1;
|
||||
@@ -297,24 +297,23 @@ int main(int argc, char *argv[])
|
||||
_zz_opts_fini(opts);
|
||||
return 0;
|
||||
default:
|
||||
printf("%s: invalid option -- %c\n", argv[0], c);
|
||||
fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c);
|
||||
printf(MOREINFO, argv[0]);
|
||||
_zz_opts_fini(opts);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
_zz_setratio(opts->minratio, opts->maxratio);
|
||||
_zz_setseed(opts->seed);
|
||||
|
||||
/* If asked to read from the standard input */
|
||||
if(optind >= argc)
|
||||
if(myoptind >= argc)
|
||||
{
|
||||
if(opts->endseed != opts->seed + 1)
|
||||
{
|
||||
printf("%s: seed ranges are incompatible with stdin fuzzing\n",
|
||||
argv[0]);
|
||||
fprintf(stderr, "%s: seed ranges are incompatible with "
|
||||
"stdin fuzzing\n", argv[0]);
|
||||
printf(MOREINFO, argv[0]);
|
||||
_zz_opts_fini(opts);
|
||||
return EXIT_FAILURE;
|
||||
@@ -332,7 +331,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
int dashdash = 0;
|
||||
|
||||
for(i = optind + 1; i < argc; i++)
|
||||
for(i = myoptind + 1; i < argc; i++)
|
||||
{
|
||||
if(dashdash)
|
||||
include = merge_file(include, argv[i]);
|
||||
@@ -366,9 +365,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* Create new argv */
|
||||
opts->oldargv = argv;
|
||||
opts->newargv = malloc((argc - optind + 1) * sizeof(char *));
|
||||
memcpy(opts->newargv, argv + optind, (argc - optind) * sizeof(char *));
|
||||
opts->newargv[argc - optind] = (char *)NULL;
|
||||
opts->newargv = malloc((argc - myoptind + 1) * sizeof(char *));
|
||||
memcpy(opts->newargv, argv + myoptind, (argc - myoptind) * sizeof(char *));
|
||||
opts->newargv[argc - myoptind] = (char *)NULL;
|
||||
|
||||
/* Main loop */
|
||||
while(opts->nchild || opts->seed < opts->endseed)
|
||||
@@ -1050,7 +1049,6 @@ static void version(void)
|
||||
printf("Written by Sam Hocevar. Report bugs to <sam@zoy.org>.\n");
|
||||
}
|
||||
|
||||
#if defined HAVE_GETOPT_H
|
||||
static void usage(void)
|
||||
{
|
||||
#if defined HAVE_REGEX_H
|
||||
@@ -1065,17 +1063,11 @@ static void usage(void)
|
||||
#else
|
||||
printf(" [PROGRAM [--] [ARGS]...]\n");
|
||||
#endif
|
||||
# if defined HAVE_GETOPT_LONG
|
||||
printf(" zzuf -h | --help\n");
|
||||
printf(" zzuf -V | --version\n");
|
||||
# else
|
||||
printf(" zzuf -h\n");
|
||||
printf(" zzuf -V\n");
|
||||
# endif
|
||||
printf("Run PROGRAM with optional arguments ARGS and fuzz its input.\n");
|
||||
printf("\n");
|
||||
printf("Mandatory arguments to long options are mandatory for short options too.\n");
|
||||
# if defined HAVE_GETOPT_LONG
|
||||
printf(" -A, --autoinc increment seed each time a new file is opened\n");
|
||||
printf(" -b, --bytes <ranges> only fuzz bytes at offsets within <ranges>\n");
|
||||
printf(" -B, --max-bytes <n> kill children that output more than <n> bytes\n");
|
||||
@@ -1112,46 +1104,7 @@ static void usage(void)
|
||||
printf(" -x, --check-exit report processes that exit with a non-zero status\n");
|
||||
printf(" -h, --help display this help and exit\n");
|
||||
printf(" -V, --version output version information and exit\n");
|
||||
# else
|
||||
printf(" -A increment seed each time a new file is opened\n");
|
||||
printf(" -b <ranges> only fuzz bytes at offsets within <ranges>\n");
|
||||
printf(" -B <n> kill children that output more than <n> bytes\n");
|
||||
#if defined HAVE_REGEX_H
|
||||
printf(" -c only fuzz files specified in the command line\n");
|
||||
#endif
|
||||
printf(" -C <n> stop after <n> children have crashed (default 1)\n");
|
||||
printf(" -d print debug messages\n");
|
||||
printf(" -D delay between forks\n");
|
||||
#if defined HAVE_REGEX_H
|
||||
printf(" -E <regex> do not fuzz files matching <regex>\n");
|
||||
#endif
|
||||
printf(" -f <mode> use fuzzing mode <mode>\n");
|
||||
printf(" -F <n> number of concurrent forks (default 1)\n");
|
||||
printf(" -i fuzz standard input\n");
|
||||
#if defined HAVE_REGEX_H
|
||||
printf(" -I <regex> only fuzz files matching <regex>\n");
|
||||
#endif
|
||||
printf(" -m compute the output's MD5 hash\n");
|
||||
#if defined HAVE_SETRLIMIT
|
||||
printf(" -M maximum child virtual memory size in MB\n");
|
||||
#endif
|
||||
printf(" -n fuzz network input\n");
|
||||
printf(" -P <list> protect bytes and characters in <list>\n");
|
||||
printf(" -q do not print the fuzzed application's messages\n");
|
||||
printf(" -r <ratio> bit fuzzing ratio (default %g)\n", DEFAULT_RATIO);
|
||||
printf(" <start:stop> specify a ratio range\n");
|
||||
printf(" -R <list> refuse bytes and characters in <list>\n");
|
||||
printf(" -s <seed> random seed (default %i)\n", DEFAULT_SEED);
|
||||
printf(" <start:stop> specify a seed range\n");
|
||||
printf(" -S prevent children from diverting crashing signals\n");
|
||||
printf(" -T <n> kill children that run for more than <n> seconds\n");
|
||||
printf(" -v print information during the run\n");
|
||||
printf(" -x report processes that exit with a non-zero status\n");
|
||||
printf(" -h display this help and exit\n");
|
||||
printf(" -V output version information and exit\n");
|
||||
# endif
|
||||
printf("\n");
|
||||
printf("Written by Sam Hocevar. Report bugs to <sam@zoy.org>.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user