* Added -p flag to cherry pick file descriptors that get fuzzed.

This commit is contained in:
Sam Hocevar 2007-07-06 13:40:55 +00:00 committed by sam
parent 71c077ae58
commit 7693a37ae1
11 changed files with 119 additions and 26 deletions

View File

@ -34,6 +34,7 @@
#include "debug.h"
#include "libzzuf.h"
#include "fd.h"
#include "fuzz.h"
/* Regex stuff */
#if defined HAVE_REGEX_H
@ -41,6 +42,10 @@ static regex_t re_include, re_exclude;
static int has_include = 0, has_exclude = 0;
#endif
/* File descriptor cherry picking */
static int *ranges = NULL;
static int ranges_static[512];
/* File descriptor stuff. When program is launched, we use the static array of
* 32 structures, which ought to be enough for most programs. If it happens
* not to be the case, ie. if the process opens more than 32 file descriptors
@ -49,7 +54,7 @@ static int has_include = 0, has_exclude = 0;
#define STATIC_FILES 32
static struct files
{
int managed, locked;
int managed, locked, active;
int64_t pos;
/* Public stuff */
struct fuzz fuzz;
@ -89,6 +94,42 @@ void _zz_exclude(char const *regex)
#endif
}
/* This function is the same as _zz_bytes() */
void _zz_pick(char const *list)
{
char const *parser;
unsigned int i, chunks;
/* Count commas */
for(parser = list, chunks = 1; *parser; parser++)
if(*parser == ',')
chunks++;
/* TODO: free(ranges) if ranges != ranges_static */
if(chunks >= 256)
ranges = malloc((chunks + 1) * 2 * sizeof(unsigned int));
else
ranges = ranges_static;
/* Fill ranges list */
for(parser = list, i = 0; i < chunks; i++)
{
char const *comma = strchr(parser, ',');
char const *dash = strchr(parser, '-');
ranges[i * 2] = (dash == parser) ? 0 : atoi(parser);
if(dash && (dash + 1 == comma || dash[1] == '\0'))
ranges[i * 2 + 1] = ranges[i * 2]; /* special case */
else if(dash && (!comma || dash < comma))
ranges[i * 2 + 1] = atoi(dash + 1) + 1;
else
ranges[i * 2 + 1] = ranges[i * 2] + 1;
parser = comma + 1;
}
ranges[i * 2] = ranges[i * 2 + 1] = 0;
}
void _zz_setseed(int32_t s)
{
seed = s;
@ -258,6 +299,26 @@ void _zz_register(int fd)
#endif
files[i].fuzz.uflag = 0;
/* Check whether we should ignore the fd */
if(ranges)
{
static int idx = 0;
int *r;
idx++;
for(r = ranges; r[1]; r += 2)
if(idx >= r[0] && (r[0] == r[1] || idx < r[1]))
goto range_ok;
files[i].active = 0;
}
else
{
range_ok:
files[i].active = 1;
}
if(autoinc)
seed++;
@ -311,6 +372,14 @@ int _zz_islocked(int fd)
return files[fds[fd]].locked;
}
int _zz_isactive(int fd)
{
if(fd < 0 || fd >= maxfd || fds[fd] == -1)
return 1;
return files[fds[fd]].active;
}
int64_t _zz_getpos(int fd)
{
if(fd < 0 || fd >= maxfd || fds[fd] == -1)

View File

@ -32,6 +32,7 @@ extern void _zz_unregister(int);
extern void _zz_lock(int);
extern void _zz_unlock(int);
extern int _zz_islocked(int);
extern int _zz_isactive(int);
extern int64_t _zz_getpos(int);
extern void _zz_setpos(int, int64_t);
extern void _zz_addpos(int, int64_t);

View File

@ -64,6 +64,7 @@ extern void _zz_fuzzing(char const *mode)
fuzzing = FUZZING_UNSET;
}
/* This function is the same as _zz_pick() */
void _zz_bytes(char const *list)
{
char const *parser;

View File

@ -18,6 +18,7 @@
extern void _zz_fuzzing(char const *);
extern void _zz_bytes(char const *);
extern void _zz_pick(char const *);
extern void _zz_protect(char const *);
extern void _zz_refuse(char const *);

View File

@ -207,7 +207,7 @@ RECV_T NEW(recv)(int s, void *buf, size_t len, int flags)
LOADSYM(recv);
ret = ORIG(recv)(s, buf, len, flags);
if(!_zz_ready || !_zz_iswatched(s) || _zz_islocked(s))
if(!_zz_ready || !_zz_iswatched(s) || _zz_islocked(s) || !_zz_isactive(s))
return ret;
if(ret > 0)
@ -240,7 +240,7 @@ RECV_T NEW(recvfrom)(int s, void *buf, size_t len, int flags,
LOADSYM(recvfrom);
ret = ORIG(recvfrom)(s, buf, len, flags, from, fromlen);
if(!_zz_ready || !_zz_iswatched(s) || _zz_islocked(s))
if(!_zz_ready || !_zz_iswatched(s) || _zz_islocked(s) || !_zz_isactive(s))
return ret;
if(ret > 0)
@ -273,7 +273,7 @@ RECV_T NEW(recvmsg)(int s, struct msghdr *hdr, int flags)
LOADSYM(recvmsg);
ret = ORIG(recvmsg)(s, hdr, flags);
if(!_zz_ready || !_zz_iswatched(s) || _zz_islocked(s))
if(!_zz_ready || !_zz_iswatched(s) || _zz_islocked(s) || !_zz_isactive(s))
return ret;
fuzz_iovec(s, hdr->msg_iov, ret);
@ -293,7 +293,8 @@ int NEW(read)(int fd, void *buf, unsigned int count)
LOADSYM(read);
ret = ORIG(read)(fd, buf, count);
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd))
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd)
|| !_zz_isactive(fd))
return ret;
if(ret > 0)
@ -324,7 +325,8 @@ ssize_t NEW(readv)(int fd, const struct iovec *iov, int count)
LOADSYM(readv);
ret = ORIG(readv)(fd, iov, count);
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd))
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd)
|| !_zz_isactive(fd))
return ret;
fuzz_iovec(fd, iov, ret);
@ -342,7 +344,8 @@ ssize_t NEW(pread)(int fd, void *buf, size_t count, off_t offset)
LOADSYM(pread);
ret = ORIG(pread)(fd, buf, count, offset);
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd))
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd)
|| !_zz_isactive(fd))
return ret;
if(ret > 0)
@ -375,7 +378,8 @@ ssize_t NEW(pread)(int fd, void *buf, size_t count, off_t offset)
{ \
LOADSYM(fn); \
ret = ORIG(fn)(fd, offset, whence); \
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd)) \
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd) \
|| !_zz_isactive(fd)) \
return ret; \
debug("%s(%i, %lli, %i) = %lli", __func__, fd, \
(long long int)offset, whence, (long long int)ret); \
@ -406,7 +410,7 @@ int NEW(aio_read)(struct aiocb *aiocbp)
int fd = aiocbp->aio_fildes;
LOADSYM(aio_read);
if(!_zz_ready || !_zz_iswatched(fd))
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
return ORIG(aio_read)(aiocbp);
_zz_lock(fd);
@ -425,7 +429,7 @@ ssize_t NEW(aio_return)(struct aiocb *aiocbp)
int fd = aiocbp->aio_fildes;
LOADSYM(aio_return);
if(!_zz_ready || !_zz_iswatched(fd))
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
return ORIG(aio_return)(aiocbp);
ret = ORIG(aio_return)(aiocbp);

View File

@ -223,7 +223,8 @@ int nbmaps = 0;
do { \
char *b = MAP_FAILED; \
LOADSYM(fn); \
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd)) \
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd) \
|| !_zz_isactive(fd)) \
return ORIG(fn)(start, length, prot, flags, fd, offset); \
ret = ORIG(fn)(NULL, length, prot, flags, fd, offset); \
if(ret != MAP_FAILED && length) \
@ -317,7 +318,8 @@ kern_return_t NEW(map_fd)(int fd, vm_offset_t offset, vm_offset_t *addr,
LOADSYM(map_fd);
ret = ORIG(map_fd)(fd, offset, addr, find_space, numbytes);
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd))
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd)
|| !_zz_isactive(fd))
return ret;
if(ret == 0 && numbytes)

View File

@ -175,7 +175,7 @@ FILE *NEW(freopen)(const char *path, const char *mode, FILE *stream)
int fd; \
LOADSYM(fn); \
fd = fileno(stream); \
if(!_zz_ready || !_zz_iswatched(fd)) \
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
return ORIG(fn)(stream, offset, whence); \
_zz_lock(fd); \
ret = ORIG(fn)(stream, offset, whence); \
@ -203,7 +203,7 @@ void NEW(rewind)(FILE *stream)
LOADSYM(rewind);
fd = fileno(stream);
if(!_zz_ready || !_zz_iswatched(fd))
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
{
ORIG(rewind)(stream);
return;
@ -233,7 +233,7 @@ size_t NEW(fread)(void *ptr, size_t size, size_t nmemb, FILE *stream)
LOADSYM(fread);
fd = fileno(stream);
if(!_zz_ready || !_zz_iswatched(fd))
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
return ORIG(fread)(ptr, size, nmemb, stream);
pos = ftell(stream);
@ -294,7 +294,7 @@ size_t NEW(fread)(void *ptr, size_t size, size_t nmemb, FILE *stream)
int fd; \
LOADSYM(fn); \
fd = fileno(stream); \
if(!_zz_ready || !_zz_iswatched(fd)) \
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
return ORIG(fn)(stream); \
_zz_lock(fd); \
ret = ORIG(fn)(stream); \
@ -332,7 +332,7 @@ char *NEW(fgets)(char *s, int size, FILE *stream)
LOADSYM(fgets);
LOADSYM(fgetc);
fd = fileno(stream);
if(!_zz_ready || !_zz_iswatched(fd))
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
return ORIG(fgets)(s, size, stream);
#if defined HAVE___SREFILL /* Don't fuzz or seek if we have __srefill() */
@ -385,7 +385,7 @@ int NEW(ungetc)(int c, FILE *stream)
LOADSYM(ungetc);
fd = fileno(stream);
if(!_zz_ready || !_zz_iswatched(fd))
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
return ORIG(ungetc)(c, stream);
_zz_lock(fd);
@ -439,7 +439,7 @@ int NEW(fclose)(FILE *fp)
LOADSYM(getdelim); \
LOADSYM(fgetc); \
fd = fileno(stream); \
if(!_zz_ready || !_zz_iswatched(fd)) \
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
return ORIG(getdelim)(lineptr, n, delim, stream); \
line = *lineptr; \
size = line ? *n : 0; \
@ -521,7 +521,7 @@ char *NEW(fgetln)(FILE *stream, size_t *len)
LOADSYM(fgetln);
LOADSYM(fgetc);
fd = fileno(stream);
if(!_zz_ready || !_zz_iswatched(fd))
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
return ORIG(fgetln)(stream, len);
#if defined HAVE___SREFILL /* Don't fuzz or seek if we have __srefill() */
@ -570,7 +570,7 @@ int NEW(__srefill)(FILE *fp)
LOADSYM(__srefill);
fd = fileno(fp);
if(!_zz_ready || !_zz_iswatched(fd))
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
return ORIG(__srefill)(fp);
_zz_lock(fd);

View File

@ -90,6 +90,10 @@ void _zz_init(void)
if(tmp && *tmp)
_zz_bytes(tmp);
tmp = getenv("ZZUF_PICK");
if(tmp && *tmp)
_zz_pick(tmp);
tmp = getenv("ZZUF_PROTECT");
if(tmp && *tmp)
_zz_protect(tmp);

View File

@ -33,7 +33,8 @@
void _zz_opts_init(struct opts *opts)
{
opts->fuzzing = opts->bytes = opts->protect = opts->refuse = NULL;
opts->fuzzing = opts->bytes = opts->pick = NULL;
opts->protect = opts->refuse = NULL;
opts->seed = DEFAULT_SEED;
opts->endseed = DEFAULT_SEED + 1;
opts->minratio = opts->maxratio = DEFAULT_RATIO;

View File

@ -20,7 +20,7 @@ struct opts
{
char **oldargv;
char **newargv;
char *fuzzing, *bytes, *protect, *refuse;
char *fuzzing, *bytes, *pick, *protect, *refuse;
uint32_t seed;
uint32_t endseed;
double minratio;

View File

@ -157,7 +157,7 @@ int main(int argc, char *argv[])
# define OPTSTR_RLIMIT ""
#endif
#define OPTSTR OPTSTR_REGEX OPTSTR_RLIMIT \
"Ab:B:C:dD:f:F:imnP:qr:R:s:ST:vxhV"
"Ab:B:C:dD:f:F:imnp:P:qr:R:s:ST:vxhV"
#define MOREINFO "Try `%s --help' for more information.\n"
int option_index = 0;
static struct myoption long_options[] =
@ -184,6 +184,7 @@ int main(int argc, char *argv[])
{ "md5", 0, NULL, 'm' },
{ "max-memory", 1, NULL, 'M' },
{ "network", 0, NULL, 'n' },
{ "pick", 1, NULL, 'p' },
{ "protect", 1, NULL, 'P' },
{ "quiet", 0, NULL, 'q' },
{ "ratio", 1, NULL, 'r' },
@ -274,6 +275,9 @@ int main(int argc, char *argv[])
case 'n': /* --network */
setenv("ZZUF_NETWORK", "1", 1);
break;
case 'p': /* --pick */
opts->pick = myoptarg;
break;
case 'P': /* --protect */
opts->protect = myoptarg;
break;
@ -375,6 +379,8 @@ int main(int argc, char *argv[])
setenv("ZZUF_FUZZING", opts->fuzzing, 1);
if(opts->bytes)
setenv("ZZUF_BYTES", opts->bytes, 1);
if(opts->pick)
setenv("ZZUF_PICK", opts->pick, 1);
if(opts->protect)
setenv("ZZUF_PROTECT", opts->protect, 1);
if(opts->refuse)
@ -427,6 +433,8 @@ static void loop_stdin(struct opts *opts)
_zz_fuzzing(opts->fuzzing);
if(opts->bytes)
_zz_bytes(opts->bytes);
if(opts->pick)
_zz_pick(opts->pick);
if(opts->protect)
_zz_protect(opts->protect);
if(opts->refuse)
@ -1085,9 +1093,10 @@ static void usage(void)
printf(" [-T seconds] [-b ranges] [-P protect] [-R refuse]\n");
#endif
#if defined HAVE_REGEX_H
printf(" [-I include] [-E exclude] [PROGRAM [--] [ARGS]...]\n");
#else
printf(" [-p descriptors] [-I include] [-E exclude]\n");
printf(" [PROGRAM [--] [ARGS]...]\n");
#else
printf(" [-I include] [-E exclude] [PROGRAM [--] [ARGS]...]\n");
#endif
printf(" zzuf -h | --help\n");
printf(" zzuf -V | --version\n");
@ -1117,6 +1126,7 @@ static void usage(void)
printf(" -M, --max-memory <n> maximum child virtual memory size in MB\n");
#endif
printf(" -n, --network fuzz network input\n");
printf(" -p, --pick <list> only fuzz Nth descriptor with N in <list>\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);