* Support ranges with the -r flag.

This commit is contained in:
Sam Hocevar
2007-01-14 23:41:03 +00:00
committed by sam
parent b1541cb9fe
commit aa1dc92193
7 changed files with 134 additions and 83 deletions
+2
View File
@@ -32,6 +32,8 @@ AC_CHECK_FUNCS(getopt_long,
GETOPT_LIBS="${GETOPT_LIBS} -lgnugetopt"])])
AC_SUBST(GETOPT_LIBS)
AC_CHECK_LIB(m, log, [MATH_LIBS="-lm"])
AC_SUBST(MATH_LIBS)
AC_CHECK_LIB(dl, dlopen, [DL_LIBS="-ldl"])
AC_SUBST(DL_LIBS)
+19 -10
View File
@@ -2,7 +2,7 @@
.SH NAME
zzuf \- multiple purpose fuzzer
.SH SYNOPSIS
\fBzzuf\fR [\fB\-AcdiMnqSvx\fR] [\fB\-r\fR \fIratio\fR] [\fB\-s\fR \fIseed\fR|\fB\-s\fR \fIstart:stop\fR]
\fBzzuf\fR [\fB\-AcdiMnqSvx\fR] [\fB\-s\fR \fIseed\fR|\fB\-s\fR \fIstart:stop\fR] [\fB\-r\fR \fIratio\fR|\fB\-r\fR \fIstart:stop\fR]
.br
[\fB\-D\fR \fIdelay\fR] [\fB\-F\fR \fIforks\fR] [\fB\-C\fR \fIcrashes\fR] [\fB\-B\fR \fIbytes\fR]
.br
@@ -40,8 +40,8 @@ if the \fBcat\fR utility had been called:
.TP
\fB\-A\fR, \fB\-\-autoinc\fR
Increment random seed each time a new file is opened. This is only required
if the same application is expected to open the same file several times and
you want to test a different seed each time.
if one instance of the application is expected to open the same file several
times and you want to test a different seed each time.
.TP
\fB\-B\fR, \fB\-\-max\-bytes\fR=\fIn\fR
Automatically terminate child processes that output more than \fIn\fR bytes
@@ -165,11 +165,19 @@ is very verbose but only its exit code or signaled status is really useful to
you.
.TP
\fB\-r\fR, \fB\-\-ratio\fR=\fIratio\fR
.PD 0
.TP
\fB\-r\fR, \fB\-\-ratio\fR=\fIstart:stop\fR
.PD
Specify the proportion of bits that will be randomly fuzzed. A value of 0
will not fuzz anything. A value of 0.05 will fuzz 5% of the open files'
bits. A value of 1.0 or more will fuzz all the bytes, theoretically making
the input files undiscernible from random data. The default fuzzing ratio
is 0.004 (fuzz 0.4% of the files' bits).
An interval can be specified. When doing so, \fBzzuf\fR will pick ratio
values from the interval. This is only meaningful if an interval is also
specified with the \fB\-s\fR flag.
.TP
\fB\-R\fR, \fB\-\-refuse\fR=\fIlist\fR
Refuse a list of characters by not fuzzing bytes that would otherwise be
@@ -258,14 +266,15 @@ can be read by \fBVLC\fR to reproduce the same behaviour without using
.br
\fB vlc fuzzy\-movie.avi\fR
.PP
Fuzz 2% of \fBMPlayer\fR's input bits (\fB\-r\ 0.02\fR) with seeds 0 to 9999
(\fB\-s\ 0:10000\fR), disabling its standard output messages (\fB\-q\fR),
launching up to five simultaneous child processes (\fB\-F\ 5\fR) but wait at
least half a second between launches (\fB\-D\ 0.5\fR), killing \fBMPlayer\fR
if it takes more than one minute to read the file (\fB\-T\ 60\fR) and
disabling its \fBSIGSEGV\fR signal handler (\fB\-S\fR):
Fuzz between 0.1% and 2% of \fBMPlayer\fR's input bits (\fB\-r\ 0.001:0.02\fR)
with seeds 0 to 9999 (\fB\-s\ 0:10000\fR), disabling its standard output
messages (\fB\-q\fR), launching up to five simultaneous child processes
(\fB\-F\ 5\fR) but wait at least half a second between launches
(\fB\-D\ 0.5\fR), killing \fBMPlayer\fR if it takes more than one minute to
read the file (\fB\-T\ 60\fR) and disabling its \fBSIGSEGV\fR signal handler
(\fB\-S\fR):
.PP
\fB zzuf \-c \-r 0.02 \-q \-s 0:10000 \-F 5 \-D 0.5 \-T 60 \-S \\\fR
\fB zzuf \-c \-r 0.001:0.02 \-q \-s 0:10000 \-F 5 \-D 0.5 \-T 60 \-S \\\fR
.br
\fB mplayer \-\- \-benchmark \-vo null \-fps 1000 movie.avi\fR
.PP
+2 -1
View File
@@ -5,10 +5,11 @@ COMMON = random.c random.h fd.c fd.h fuzz.c fuzz.h
bin_PROGRAMS = zzuf
zzuf_SOURCES = zzuf.c $(COMMON) md5.c md5.h timer.c timer.h
zzuf_CFLAGS = -DLIBDIR=\"$(libdir)/zzuf\"
zzuf_LDFLAGS = @MATH_LIBS@
pkglib_LTLIBRARIES = libzzuf.la
libzzuf_la_SOURCES = libzzuf.c libzzuf.h $(COMMON) debug.c debug.h \
load-fd.c load-mem.c load-signal.c load-stream.c load.h
libzzuf_la_LDFLAGS = -avoid-version -no-undefined
libzzuf_la_LIBADD = @GETOPT_LIBS@ @DL_LIBS@
libzzuf_la_LIBADD = @GETOPT_LIBS@ @DL_LIBS@ @MATH_LIBS@
+32 -8
View File
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include <regex.h>
#include <string.h>
#include <math.h>
#include "debug.h"
#include "libzzuf.h"
@@ -54,7 +55,8 @@ static int *fds, static_fds[STATIC_FILES];
static int maxfd, nfiles;
static int32_t seed = DEFAULT_SEED;
static double ratio = DEFAULT_RATIO;
static double minratio = DEFAULT_RATIO;
static double maxratio = DEFAULT_RATIO;
static int autoinc = 0;
void _zz_include(char const *regex)
@@ -74,13 +76,35 @@ void _zz_setseed(int32_t s)
seed = s;
}
void _zz_setratio(double r)
void _zz_setratio(double r0, double r1)
{
if(r < MIN_RATIO)
r = MIN_RATIO;
else if(r > MAX_RATIO)
r = MAX_RATIO;
ratio = r;
minratio = r0 < MIN_RATIO ? MIN_RATIO : r0 > MAX_RATIO ? MAX_RATIO : r0;
maxratio = r1 < MIN_RATIO ? MIN_RATIO : r1 > MAX_RATIO ? MAX_RATIO : r1;
if(maxratio < minratio)
maxratio = minratio;
}
double _zz_getratio(void)
{
uint8_t const shuffle[16] =
{ 0, 12, 2, 10,
14, 8, 15, 7,
9, 13, 3, 6,
4, 1, 11, 5 };
uint16_t rate;
double min, max, cur;
rate = shuffle[seed & 0xf] << 12;
rate |= (seed & 0xf0) << 4;
rate |= (seed & 0xf00) >> 4;
rate |= (seed & 0xf000) >> 12;
min = log(minratio);
max = log(maxratio);
cur = min + (max - min) * rate / 0xffff;
return exp(cur);
}
void _zz_setautoinc(void)
@@ -188,7 +212,7 @@ void _zz_register(int fd)
files[i].managed = 1;
files[i].pos = 0;
files[i].fuzz.seed = seed;
files[i].fuzz.ratio = ratio;
files[i].fuzz.ratio = _zz_getratio();
files[i].fuzz.cur = -1;
#ifdef HAVE_FGETLN
files[i].fuzz.tmp = NULL;
+2 -1
View File
@@ -19,7 +19,8 @@
extern void _zz_include(char const *);
extern void _zz_exclude(char const *);
extern void _zz_setseed(int32_t);
extern void _zz_setratio(double);
extern void _zz_setratio(double, double);
extern double _zz_getratio(void);
extern void _zz_setautoinc(void);
extern void _zz_fd_init(void);
extern void _zz_fd_fini(void);
+5 -4
View File
@@ -51,7 +51,7 @@ int _zz_network = 0;
/* Library initialisation shit */
void _zz_init(void)
{
char *tmp;
char *tmp, *tmp2;
_zz_load_mem();
_zz_load_signal();
@@ -66,9 +66,10 @@ void _zz_init(void)
if(tmp && *tmp)
_zz_setseed(atol(tmp));
tmp = getenv("ZZUF_RATIO");
if(tmp && *tmp)
_zz_setratio(atof(tmp));
tmp = getenv("ZZUF_MINRATIO");
tmp2 = getenv("ZZUF_MAXRATIO");
if(tmp && *tmp && tmp2 && *tmp2)
_zz_setratio(atof(tmp), atof(tmp2));
tmp = getenv("ZZUF_AUTOINC");
if(tmp && *tmp == '1')
+72 -59
View File
@@ -73,6 +73,7 @@ static struct child_list
pid_t pid;
int fd[3]; /* 0 is debug, 1 is stderr, 2 is stdout */
int bytes, seed;
double ratio;
int64_t date;
struct md5 *ctx;
} *child_list;
@@ -82,8 +83,8 @@ static char **newargv;
static char *protect = NULL, *refuse = NULL;
static uint32_t seed = DEFAULT_SEED;
static uint32_t endseed = DEFAULT_SEED + 1;
static double ratio = DEFAULT_RATIO;
static double endratio = DEFAULT_RATIO;
static double minratio = DEFAULT_RATIO;
static double maxratio = DEFAULT_RATIO;
static int quiet = 0;
static int maxbytes = -1;
static int md5 = 0;
@@ -217,8 +218,8 @@ int main(int argc, char *argv[])
break;
case 'r': /* --ratio */
parser = strchr(optarg, ':');
ratio = atof(optarg);
endratio = parser ? atof(parser + 1) : ratio;
minratio = atof(optarg);
maxratio = parser ? atof(parser + 1) : minratio;
break;
case 'R': /* --refuse */
refuse = optarg;
@@ -257,6 +258,9 @@ int main(int argc, char *argv[])
int optind = 1;
#endif
_zz_setratio(minratio, maxratio);
_zz_setseed(seed);
/* If asked to read from the standard input */
if(optind >= argc)
{
@@ -268,9 +272,6 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
_zz_setseed(seed);
_zz_setratio(ratio);
loop_stdin();
return EXIT_SUCCESS;
@@ -380,9 +381,9 @@ static void loop_stdin(void)
if(md5)
{
_zz_md5_fini(md5sum, ctx);
fprintf(stderr, "zzuf[seed=%i]: %.02x%.02x%.02x%.02x%.02x%.02x"
"%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x\n",
seed, md5sum[0], md5sum[1], md5sum[2], md5sum[3],
fprintf(stderr, "zzuf[s=%i,r=%g]: %.02x%.02x%.02x%.02x%.02x"
"%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x\n",
seed, minratio, md5sum[0], md5sum[1], md5sum[2], md5sum[3],
md5sum[4], md5sum[5], md5sum[6], md5sum[7],
md5sum[8], md5sum[9], md5sum[10], md5sum[11],
md5sum[12], md5sum[13], md5sum[14], md5sum[15]);
@@ -506,8 +507,10 @@ static void spawn_children(void)
/* Set environment variables */
sprintf(buf, "%i", seed);
setenv("ZZUF_SEED", buf, 1);
sprintf(buf, "%g", ratio);
setenv("ZZUF_RATIO", buf, 1);
sprintf(buf, "%g", minratio);
setenv("ZZUF_MINRATIO", buf, 1);
sprintf(buf, "%g", maxratio);
setenv("ZZUF_MAXRATIO", buf, 1);
/* Run our process */
if(execvp(newargv[0], newargv))
@@ -518,9 +521,6 @@ static void spawn_children(void)
return;
}
if(verbose)
fprintf(stderr, "zzuf[seed=%i]: launched %s\n", seed, newargv[0]);
/* Were the parent, acknowledge spawn */
child_list[i].date = now;
child_list[i].pid = pid;
@@ -531,13 +531,20 @@ static void spawn_children(void)
}
child_list[i].bytes = 0;
child_list[i].seed = seed;
child_list[i].ratio = _zz_getratio();
child_list[i].status = STATUS_RUNNING;
if(md5)
child_list[i].ctx = _zz_md5_init();
if(verbose)
fprintf(stderr, "zzuf[s=%i,r=%g]: launched %s\n",
child_list[i].seed, child_list[i].ratio, newargv[0]);
lastlaunch = now;
child_count++;
seed++;
_zz_setseed(seed);
}
static void clean_children(void)
@@ -552,8 +559,9 @@ static void clean_children(void)
&& maxbytes >= 0 && child_list[i].bytes > maxbytes)
{
if(verbose)
fprintf(stderr, "zzuf[seed=%i]: data output exceeded,"
" sending SIGTERM\n", child_list[i].seed);
fprintf(stderr, "zzuf[s=%i,r=%g]: "
"data output exceeded, sending SIGTERM\n",
child_list[i].seed, child_list[i].ratio);
kill(child_list[i].pid, SIGTERM);
child_list[i].date = now;
child_list[i].status = STATUS_SIGTERM;
@@ -564,8 +572,9 @@ static void clean_children(void)
&& now > child_list[i].date + maxtime)
{
if(verbose)
fprintf(stderr, "zzuf[seed=%i]: running time exceeded,"
" sending SIGTERM\n", child_list[i].seed);
fprintf(stderr, "zzuf[s=%i,r=%g]: "
"running time exceeded, sending SIGTERM\n",
child_list[i].seed, child_list[i].ratio);
kill(child_list[i].pid, SIGTERM);
child_list[i].date = now;
child_list[i].status = STATUS_SIGTERM;
@@ -579,8 +588,9 @@ static void clean_children(void)
&& now > child_list[i].date + 2000000)
{
if(verbose)
fprintf(stderr, "zzuf[seed=%i]: not responding,"
" sending SIGKILL\n", child_list[i].seed);
fprintf(stderr, "zzuf[s=%i,r=%g]: "
"not responding, sending SIGKILL\n",
child_list[i].seed, child_list[i].ratio);
kill(child_list[i].pid, SIGKILL);
child_list[i].status = STATUS_SIGKILL;
}
@@ -604,17 +614,18 @@ static void clean_children(void)
if(checkexit && WIFEXITED(status) && WEXITSTATUS(status))
{
fprintf(stderr, "zzuf[seed=%i]: exit %i\n",
child_list[i].seed, WEXITSTATUS(status));
fprintf(stderr, "zzuf[s=%i,r=%g]: exit %i\n",
child_list[i].seed, child_list[i].ratio,
WEXITSTATUS(status));
crashes++;
}
else if(WIFSIGNALED(status)
&& !(WTERMSIG(status) == SIGTERM
&& child_list[i].status == STATUS_SIGTERM))
{
fprintf(stderr, "zzuf[seed=%i]: signal %i%s%s\n",
child_list[i].seed, WTERMSIG(status),
sig2str(WTERMSIG(status)),
fprintf(stderr, "zzuf[s=%i,r=%g]: signal %i%s%s\n",
child_list[i].seed, child_list[i].ratio,
WTERMSIG(status), sig2str(WTERMSIG(status)),
(WTERMSIG(status) == SIGKILL && maxmem >= 0) ?
" (memory exceeded?)" : "");
crashes++;
@@ -627,12 +638,12 @@ static void clean_children(void)
if(md5)
{
_zz_md5_fini(md5sum, child_list[i].ctx);
fprintf(stderr, "zzuf[seed=%i]: %.02x%.02x%.02x%.02x%.02x%.02x"
"%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x\n",
child_list[i].seed, md5sum[0], md5sum[1], md5sum[2],
md5sum[3], md5sum[4], md5sum[5], md5sum[6], md5sum[7],
md5sum[8], md5sum[9], md5sum[10], md5sum[11], md5sum[12],
md5sum[13], md5sum[14], md5sum[15]);
fprintf(stderr, "zzuf[s=%i,r=%g]: %.02x%.02x%.02x%.02x%.02x"
"%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x\n",
child_list[i].seed, child_list[i].ratio, md5sum[0],
md5sum[1], md5sum[2], md5sum[3], md5sum[4], md5sum[5],
md5sum[6], md5sum[7], md5sum[8], md5sum[9], md5sum[10],
md5sum[11], md5sum[12], md5sum[13], md5sum[14], md5sum[15]);
}
child_list[i].status = STATUS_FREE;
child_count--;
@@ -794,31 +805,32 @@ static void usage(void)
printf("\n");
printf("Mandatory arguments to long options are mandatory for short options too.\n");
# ifdef HAVE_GETOPT_LONG
printf(" -A, --autoinc increment seed each time a new file is opened\n");
printf(" -B, --max-bytes <n> kill children that output more than <n> bytes\n");
printf(" -c, --cmdline only fuzz files specified in the command line\n");
printf(" -C, --max-crashes <n> stop after <n> children have crashed (default 1)\n");
printf(" -d, --debug print debug messages\n");
printf(" -D, --delay delay between forks\n");
printf(" -E, --exclude <regex> do not fuzz files matching <regex>\n");
printf(" -F, --max-forks <n> number of concurrent children (default 1)\n");
printf(" -i, --stdin fuzz standard input\n");
printf(" -I, --include <regex> only fuzz files matching <regex>\n");
printf(" -m, --md5 compute the output's MD5 hash\n");
printf(" -M, --max-memory <n> maximum child virtual memory size in MB\n");
printf(" -n, --network fuzz network input\n");
printf(" -P, --protect <list> protect bytes and characters in <list>\n");
printf(" -q, --quiet do not print children's messages\n");
printf(" -r, --ratio <ratio> bit fuzzing ratio (default 0.004)\n");
printf(" -R, --refuse <list> refuse bytes and characters in <list>\n");
printf(" -s, --seed <seed> random seed (default 0)\n");
printf(" --seed <start:stop> specify a seed range\n");
printf(" -S, --signal prevent children from diverting crashing signals\n");
printf(" -T, --max-time <n> kill children that run for more than <n> seconds\n");
printf(" -v, --verbose print information during the run\n");
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");
printf(" -A, --autoinc increment seed each time a new file is opened\n");
printf(" -B, --max-bytes <n> kill children that output more than <n> bytes\n");
printf(" -c, --cmdline only fuzz files specified in the command line\n");
printf(" -C, --max-crashes <n> stop after <n> children have crashed (default 1)\n");
printf(" -d, --debug print debug messages\n");
printf(" -D, --delay delay between forks\n");
printf(" -E, --exclude <regex> do not fuzz files matching <regex>\n");
printf(" -F, --max-forks <n> number of concurrent children (default 1)\n");
printf(" -i, --stdin fuzz standard input\n");
printf(" -I, --include <regex> only fuzz files matching <regex>\n");
printf(" -m, --md5 compute the output's MD5 hash\n");
printf(" -M, --max-memory <n> maximum child virtual memory size in MB\n");
printf(" -n, --network fuzz network input\n");
printf(" -P, --protect <list> protect bytes and characters in <list>\n");
printf(" -q, --quiet do not print children's messages\n");
printf(" -r, --ratio <ratio> bit fuzzing ratio (default %g)\n", DEFAULT_RATIO);
printf(" --ratio <start:stop> specify a ratio range\n");
printf(" -R, --refuse <list> refuse bytes and characters in <list>\n");
printf(" -s, --seed <seed> random seed (default %i)\n", DEFAULT_SEED);
printf(" --seed <start:stop> specify a seed range\n");
printf(" -S, --signal prevent children from diverting crashing signals\n");
printf(" -T, --max-time <n> kill children that run for more than <n> seconds\n");
printf(" -v, --verbose print information during the run\n");
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 <n> kill children that output more than <n> bytes\n");
@@ -835,9 +847,10 @@ static void usage(void)
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 0.004)\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 0)\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");