diff --git a/doc/zzuf.1 b/doc/zzuf.1 index 3aa4a37..1ab7515 100644 --- a/doc/zzuf.1 +++ b/doc/zzuf.1 @@ -2,13 +2,13 @@ .SH NAME zzuf \- multiple purpose fuzzer .SH SYNOPSIS -\fBzzuf\fR [\fB\-cdiMnqSx\fR] [\fB\-r\fR \fIratio\fR] [\fB\-s\fR \fIseed\fR|\fB\-s\fR \fIstart:stop\fR] +\fBzzuf\fR [\fB\-AcdiMnqSx\fR] [\fB\-r\fR \fIratio\fR] [\fB\-s\fR \fIseed\fR|\fB\-s\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] + [\fB\-D\fR \fIdelay\fR] [\fB\-F\fR \fIforks\fR] [\fB\-C\fR \fIcrashes\fR] [\fB\-B\fR \fIbytes\fR] .br - [\fB\-T\fR \fIseconds\fR] [\fB\-M\fR \fImegabytes\fR] [\fB\-P\fR \fIprotect\fR] [\fB\-R\fR \fIrefuse\fR] + [\fB\-T\fR \fIseconds\fR] [\fB\-M\fR \fImegabytes\fR] [\fB\-P\fR \fIprotect\fR] [\fB\-R\fR \fIrefuse\fR] .br - [\fB\-I\fR \fIinclude\fR] [\fB\-E\fR \fIexclude\fR] [\fIPROGRAM\fR [\fB\-\-\fR] [\fIARGS\fR]...] + [\fB\-I\fR \fIinclude\fR] [\fB\-E\fR \fIexclude\fR] [\fIPROGRAM\fR [\fB\-\-\fR] [\fIARGS\fR]...] .br \fBzzuf \-h\fR | \fB\-\-help\fR .br @@ -38,6 +38,11 @@ if the \fBcat\fR utility had been called: \fB zzuf < /dev/zero\fR .SH OPTIONS .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. +.TP \fB\-B\fR, \fB\-\-max\-bytes\fR=\fIn\fR Automatically terminate child processes that output more than \fIn\fR bytes on the standard output and standard error channels. This is useful to detect @@ -252,6 +257,13 @@ 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 mplayer \-\- \-benchmark \-vo null \-fps 1000 movie.avi\fR +.PP +Create an HTML-like file that loads 1000 times the same \fBhello.gif\fR image +and open it in \fBFirefox\fR in auto-increment mode (\fB\-A\fR): +.PP +\fB awk \(aqBEGIN { for(i=0; i<1000; i++) { print \\\fR +\fB "" }}\(aq > hello.html\fR +\fB zzuf -A -I \(aqhello[.]gif\(aq -r 0.001 firefox hello.html\fR .SH RESTRICTIONS .PP Due to \fBzzuf\fR using shared object preloading (\fBLD_PRELOAD\fR, diff --git a/src/fd.c b/src/fd.c index f643920..43a4b47 100644 --- a/src/fd.c +++ b/src/fd.c @@ -28,6 +28,7 @@ #include #include +#include "debug.h" #include "libzzuf.h" #include "fd.h" @@ -44,7 +45,6 @@ static int has_include = 0, has_exclude = 0; static struct files { int managed; - uint64_t seed; uint64_t pos; /* Public stuff */ struct fuzz fuzz; @@ -53,6 +53,10 @@ static struct files static int *fds, static_fds[STATIC_FILES]; static int maxfd, nfiles; +static int32_t seed = 0; +static float ratio = 0.004f; +static int autoinc = 0; + void _zz_include(char const *regex) { if(regcomp(&re_include, regex, REG_EXTENDED) == 0) @@ -65,6 +69,25 @@ void _zz_exclude(char const *regex) has_exclude = 1; } +void _zz_setseed(int32_t s) +{ + seed = s; +} + +void _zz_setratio(float r) +{ + if(r < 0.0f) + r = 0.0f; + else if(r > 5.0f) + r = 5.0f; + ratio = r; +} + +void _zz_setautoinc(void) +{ + autoinc = 1; +} + void _zz_fd_init(void) { /* We start with 32 file descriptors. This is to reduce the number of @@ -124,6 +147,11 @@ void _zz_register(int fd) if(fd < 0 || fd > 65535 || (fd < maxfd && fds[fd] != -1)) return; +#if 0 + if(autoinc) + debug("using seed %li", (long int)seed); +#endif + /* If filedescriptor is outside our bounds */ while(fd >= maxfd) { @@ -159,11 +187,16 @@ 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.cur = -1; #ifdef HAVE_FGETLN files[i].fuzz.tmp = NULL; #endif + if(autoinc) + seed++; + fds[fd] = i; } diff --git a/src/fd.h b/src/fd.h index a079ee9..8a3be39 100644 --- a/src/fd.h +++ b/src/fd.h @@ -18,6 +18,9 @@ extern void _zz_include(char const *); extern void _zz_exclude(char const *); +extern void _zz_setseed(int32_t); +extern void _zz_setratio(float); +extern void _zz_setautoinc(void); extern void _zz_fd_init(void); extern void _zz_fd_fini(void); diff --git a/src/fuzz.c b/src/fuzz.c index 6b305fb..2fa3b78 100644 --- a/src/fuzz.c +++ b/src/fuzz.c @@ -36,11 +36,10 @@ #define MAGIC2 0x783bc31f /* Fuzzing variables */ -static int protect[256]; -static int refuse[256]; -static float ratio = 0.004f; -static int seed = 0; +static int protect[256]; +static int refuse[256]; +/* Local prototypes */ static void readchars(int *, char const *); void _zz_protect(char const *list) @@ -53,20 +52,6 @@ void _zz_refuse(char const *list) readchars(refuse, list); } -void _zz_setseed(int s) -{ - seed = s; -} - -void _zz_setratio(float r) -{ - if(r < 0.0f) - r = 0.0f; - else if(r > 5.0f) - r = 5.0f; - ratio = r; -} - void _zz_fuzz(int fd, uint8_t *buf, uint64_t len) { uint64_t start, stop; @@ -90,16 +75,14 @@ void _zz_fuzz(int fd, uint8_t *buf, uint64_t len) /* Cache bitmask array */ if(fuzz->cur != (int)i) { - uint32_t chunkseed = i * MAGIC1; + uint32_t chunkseed = (i + (int)(fuzz->ratio * MAGIC1)) ^ MAGIC2; + _zz_srand(fuzz->seed ^ chunkseed); memset(fuzz->data, 0, CHUNKBYTES); /* Add some random dithering to handle ratio < 1.0/CHUNKBYTES */ - _zz_srand(seed ^ chunkseed); - todo = (int)((ratio * (8 * CHUNKBYTES * 1000) + todo = (int)((fuzz->ratio * (8 * CHUNKBYTES * 1000) + _zz_rand(1000)) / 1000.0); - _zz_srand(seed ^ chunkseed ^ (todo * MAGIC2)); - while(todo--) { unsigned int idx = _zz_rand(CHUNKBYTES); diff --git a/src/fuzz.h b/src/fuzz.h index e818e11..1562dd3 100644 --- a/src/fuzz.h +++ b/src/fuzz.h @@ -18,8 +18,6 @@ extern void _zz_protect(char const *); extern void _zz_refuse(char const *); -extern void _zz_setseed(int); -extern void _zz_setratio(float); extern void _zz_fuzz(int, uint8_t *, uint64_t); diff --git a/src/libzzuf.c b/src/libzzuf.c index b5fb105..9c77bcb 100644 --- a/src/libzzuf.c +++ b/src/libzzuf.c @@ -70,6 +70,10 @@ void _zz_init(void) if(tmp && *tmp) _zz_setratio(atof(tmp)); + tmp = getenv("ZZUF_AUTOINC"); + if(tmp && *tmp == '1') + _zz_setautoinc(); + tmp = getenv("ZZUF_PROTECT"); if(tmp && *tmp) _zz_protect(tmp); diff --git a/src/libzzuf.h b/src/libzzuf.h index e798a58..35f606a 100644 --- a/src/libzzuf.h +++ b/src/libzzuf.h @@ -27,6 +27,8 @@ struct fuzz { + uint32_t seed; + float ratio; int cur; #ifdef HAVE_FGETLN char *tmp; @@ -35,12 +37,13 @@ struct fuzz }; /* Internal variables */ -extern int _zz_ready; -extern int _zz_disabled; -extern int _zz_hasdebug; -extern int _zz_signal; -extern int _zz_memory; -extern int _zz_network; +extern int _zz_ready; +extern int _zz_disabled; +extern int _zz_hasdebug; +extern int _zz_signal; +extern int _zz_memory; +extern int _zz_network; +extern int _zz_autoinc; /* Library initialisation shit */ extern void _zz_init(void) __attribute__((constructor)); diff --git a/src/zzuf.c b/src/zzuf.c index 5c50e9c..5b4f163 100644 --- a/src/zzuf.c +++ b/src/zzuf.c @@ -111,13 +111,14 @@ int main(int argc, char *argv[]) #if defined(HAVE_GETOPT_H) for(;;) { -# define OPTSTR "B:cC:dD:E:F:iI:mM:nP:qr:R:s:ST:xhv" +# define OPTSTR "AB:cC:dD:E:F:iI:mM:nP:qr:R:s:ST:xhv" # ifdef HAVE_GETOPT_LONG # define MOREINFO "Try `%s --help' for more information.\n" int option_index = 0; static struct option long_options[] = { /* Long option, needs arg, flag, short option */ + { "autoinc", 0, NULL, 'A' }, { "max-bytes", 1, NULL, 'B' }, { "cmdline", 0, NULL, 'c' }, { "max-crashes", 1, NULL, 'C' }, @@ -151,6 +152,9 @@ int main(int argc, char *argv[]) switch(c) { + case 'A': /* --autoinc */ + setenv("ZZUF_AUTOINC", "1", 1); + break; case 'B': /* --max-bytes */ maxbytes = atoi(optarg); break; @@ -722,10 +726,10 @@ static void version(void) #if defined(HAVE_GETOPT_H) static void usage(void) { - printf("Usage: zzuf [-cdimnqSx] [-r ratio] [-s seed | -s start:stop]\n"); - printf(" [-D delay] [-F forks] [-C crashes] [-B bytes]\n"); - printf(" [-T seconds] [-M bytes] [-P protect] [-R refuse]\n"); - printf(" [-I include] [-E exclude] [PROGRAM [--] [ARGS]...]\n"); + printf("Usage: zzuf [-AcdimnqSx] [-r ratio] [-s seed | -s start:stop]\n"); + printf(" [-D delay] [-F forks] [-C crashes] [-B bytes]\n"); + printf(" [-T seconds] [-M bytes] [-P protect] [-R refuse]\n"); + printf(" [-I include] [-E exclude] [PROGRAM [--] [ARGS]...]\n"); # ifdef HAVE_GETOPT_LONG printf(" zzuf -h | --help\n"); printf(" zzuf -v | --version\n"); @@ -737,6 +741,7 @@ 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 kill children that output more than bytes\n"); printf(" -c, --cmdline only fuzz files specified in the command line\n"); printf(" -C, --max-crashes stop after children have crashed (default 1)\n"); @@ -761,6 +766,7 @@ static void usage(void) 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 kill children that output more than bytes\n"); printf(" -c only fuzz files specified in the command line\n"); printf(" -C stop after children have crashed (default 1)\n");