* If no argument is given, just fuzz standard input.

This commit is contained in:
Sam Hocevar
2007-01-07 18:18:50 +00:00
committed by sam
parent 1fdcd5182f
commit c0aad3b6e5
13 changed files with 418 additions and 254 deletions
+3 -3
View File
@@ -1,12 +1,12 @@
bin_PROGRAMS = zzuf
zzuf_SOURCES = zzuf.c
AM_CPPFLAGS = -DLIBDIR=\"$(libdir)/zzuf\"
zzuf_SOURCES = zzuf.c random.c random.h chars.c chars.h fd.c fd.h fuzz.c fuzz.h
zzuf_CFLAGS = -DLIBDIR=\"$(libdir)/zzuf\"
pkglib_LTLIBRARIES = libzzuf.la
libzzuf_la_SOURCES = libzzuf.c libzzuf.h fuzz.c fuzz.h debug.c debug.h \
load-fd.c load-signal.c load-stream.c load.h \
random.c random.h
fd.c fd.h chars.c chars.h random.c random.h
libzzuf_la_LDFLAGS = -avoid-version -no-undefined
libzzuf_la_LIBADD = @GETOPT_LIBS@ @DL_LIBS@
+96
View File
@@ -0,0 +1,96 @@
/*
* zzuf - general purpose fuzzer
* Copyright (c) 2006 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.
*/
/*
* chars.c: protected/refused characters
*/
#include "config.h"
#if defined HAVE_STDINT_H
# include <stdint.h>
#elif defined HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#include <string.h>
#include "libzzuf.h"
#include "chars.h"
void _zz_readchars(int *table, char const *list)
{
static char const hex[] = "0123456789abcdef0123456789ABCDEF";
char const *tmp;
int a, b;
memset(table, 0, 256 * sizeof(int));
for(tmp = list, a = b = -1; *tmp; tmp++)
{
int new;
if(*tmp == '\\' && tmp[1] == '\0')
new = '\\';
else if(*tmp == '\\')
{
tmp++;
if(*tmp == 'n')
new = '\n';
else if(*tmp == 'r')
new = '\r';
else if(*tmp == 't')
new = '\t';
else if(tmp[0] >= '0' && tmp[0] <= '7' && tmp[1] >= '0'
&& tmp[1] <= '7' && tmp[2] >= '0' && tmp[2] <= '7')
{
new = tmp[2] - '0';
new |= (int)(tmp[1] - '0') << 3;
new |= (int)(tmp[0] - '0') << 6;
tmp += 2;
}
else if((*tmp == 'x' || *tmp == 'X')
&& tmp[1] && strchr(hex, tmp[1])
&& tmp[2] && strchr(hex, tmp[2]))
{
new = ((strchr(hex, tmp[1]) - hex) & 0xf) << 4;
new |= (strchr(hex, tmp[2]) - hex) & 0xf;
tmp += 2;
}
else
new = (unsigned char)*tmp; /* XXX: OK for \\, but what else? */
}
else
new = (unsigned char)*tmp;
if(a != -1 && b == '-' && a <= new)
{
while(a <= new)
table[a++] = 1;
a = b = -1;
}
else
{
if(a != -1)
table[a] = 1;
a = b;
b = new;
}
}
if(a != -1)
table[a] = 1;
if(b != -1)
table[b] = 1;
}
+20
View File
@@ -0,0 +1,20 @@
/*
* zzuf - general purpose fuzzer
* Copyright (c) 2006 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.
*/
/*
* chars.h: character functions
*/
extern void _zz_readchars(int *, char const *);
+180
View File
@@ -0,0 +1,180 @@
/*
* zzuf - general purpose fuzzer
* Copyright (c) 2006 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.
*/
/*
* libzzuf.c: preloaded wrapper library
*/
#include "config.h"
#define _GNU_SOURCE
#if defined HAVE_STDINT_H
# include <stdint.h>
#elif defined HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#include <stdlib.h>
#include <regex.h>
#include "libzzuf.h"
#include "fd.h"
regex_t * re_include = NULL;
regex_t * re_exclude = NULL;
/* File descriptor stuff */
static struct files
{
int managed;
uint64_t seed;
uint64_t pos;
/* Public stuff */
struct fuzz fuzz;
}
*files;
static int *fds;
static int maxfd, nfiles;
void _zz_fd_init(void)
{
files = NULL;
nfiles = 0;
/* Start with one fd in the lookup table */
fds = malloc(1 * sizeof(int));
for(maxfd = 0; maxfd < 1; maxfd++)
fds[maxfd] = -1;
}
void _zz_fd_fini(void)
{
int i;
for(i = 0; i < maxfd; i++)
{
if(!files[fds[i]].managed)
continue;
/* XXX: What are we supposed to do? If filedescriptors weren't
* closed properly, there's a leak, but it's not our problem. */
}
free(files);
free(fds);
}
int _zz_mustwatch(char const *file)
{
if(re_include && regexec(re_include, file, 0, NULL, 0) == REG_NOMATCH)
return 0; /* not included: ignore */
if(re_exclude && regexec(re_exclude, file, 0, NULL, 0) != REG_NOMATCH)
return 0; /* excluded: ignore */
return 1; /* default */
}
int _zz_iswatched(int fd)
{
if(fd < 0 || fd >= maxfd || fds[fd] == -1)
return 0;
return 1;
}
void _zz_register(int fd)
{
int i;
if(fd < 0 || fd > 65535 || (fd < maxfd && fds[fd] != -1))
return;
while(fd >= maxfd)
{
fds = realloc(fds, 2 * maxfd * sizeof(int));
for(i = maxfd; i < maxfd * 2; i++)
fds[i] = -1;
maxfd *= 2;
}
/* Find an empty slot */
for(i = 0; i < nfiles; i++)
if(files[i].managed == 0)
break;
/* No slot found, allocate memory */
if(i == nfiles)
{
nfiles++;
files = realloc(files, nfiles * sizeof(struct files));
}
files[i].managed = 1;
files[i].pos = 0;
files[i].fuzz.cur = -1;
files[i].fuzz.data = malloc(CHUNKBYTES);
#ifdef HAVE_FGETLN
files[i].fuzz.tmp = NULL;
#endif
fds[fd] = i;
}
void _zz_unregister(int fd)
{
if(fd < 0 || fd >= maxfd || fds[fd] == -1)
return;
files[fds[fd]].managed = 0;
free(files[fds[fd]].fuzz.data);
#ifdef HAVE_FGETLN
if(files[fds[fd]].fuzz.tmp)
free(files[fds[fd]].fuzz.tmp);
#endif
fds[fd] = -1;
}
long int _zz_getpos(int fd)
{
if(fd < 0 || fd >= maxfd || fds[fd] == -1)
return 0;
return files[fds[fd]].pos;
}
void _zz_setpos(int fd, long int pos)
{
if(fd < 0 || fd >= maxfd || fds[fd] == -1)
return;
files[fds[fd]].pos = pos;
}
void _zz_addpos(int fd, long int off)
{
if(fd < 0 || fd >= maxfd || fds[fd] == -1)
return;
files[fds[fd]].pos += off;
}
struct fuzz *_zz_getfuzz(int fd)
{
if(fd < 0 || fd >= maxfd || fds[fd] == -1)
return NULL;
return &files[fds[fd]].fuzz;
}
+33
View File
@@ -0,0 +1,33 @@
/*
* zzuf - general purpose fuzzer
* Copyright (c) 2006 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.
*/
/*
* fd.h: file descriptor functions
*/
extern void _zz_fd_init(void);
extern void _zz_fd_fini(void);
extern regex_t * re_include;
extern regex_t * re_exclude;
extern int _zz_mustwatch(char const *);
extern int _zz_iswatched(int);
extern void _zz_register(int);
extern void _zz_unregister(int);
extern long int _zz_getpos(int);
extern void _zz_setpos(int, long int);
extern void _zz_addpos(int, long int);
extern struct fuzz *_zz_getfuzz(int);
+19
View File
@@ -25,15 +25,34 @@
#endif
#include <stdio.h>
#include <string.h>
#include <regex.h>
#include "libzzuf.h"
#include "debug.h"
#include "random.h"
#include "fuzz.h"
#include "fd.h"
#define MAGIC1 0x33ea84f7
#define MAGIC2 0x783bc31f
static float _zz_ratio = 0.004f;
static int _zz_seed = 0;
void _zz_setseed(int seed)
{
_zz_seed = seed;
}
void _zz_setratio(float ratio)
{
_zz_ratio = ratio;
if(_zz_ratio < 0.0f)
_zz_ratio = 0.0f;
else if(_zz_ratio > 5.0f)
_zz_ratio = 5.0f;
}
void _zz_fuzz(int fd, uint8_t *buf, uint64_t len)
{
uint64_t start, stop;
+2
View File
@@ -16,5 +16,7 @@
* fuzz.h: fuzz functions
*/
extern void _zz_setseed(int);
extern void _zz_setratio(float);
extern void _zz_fuzz(int, uint8_t *, uint64_t);
+7 -231
View File
@@ -37,13 +37,14 @@
#include "libzzuf.h"
#include "debug.h"
#include "load.h"
#include "chars.h"
#include "fd.h"
#include "fuzz.h"
/* Global variables */
int _zz_ready = 0;
int _zz_disabled = 0;
int _zz_hasdebug = 0;
float _zz_ratio = 0.004f;
int _zz_seed = 0;
int _zz_signal = 0;
int _zz_network = 0;
@@ -51,15 +52,6 @@ int _zz_network = 0;
int _zz_protect[256];
int _zz_refuse[256];
/* Local variables */
static regex_t * re_include = NULL;
static regex_t * re_exclude = NULL;
/* Local prototypes */
static void _zz_list_init(int *, char const *);
static void _zz_fd_init(void);
static void _zz_fd_fini(void);
/* Library initialisation shit */
void _zz_init(void)
{
@@ -71,23 +63,19 @@ void _zz_init(void)
tmp = getenv("ZZUF_SEED");
if(tmp && *tmp)
_zz_seed = atol(tmp);
_zz_setseed(atol(tmp));
tmp = getenv("ZZUF_RATIO");
if(tmp && *tmp)
_zz_ratio = atof(tmp);
if(_zz_ratio < 0.0f)
_zz_ratio = 0.0f;
else if(_zz_ratio > 5.0f)
_zz_ratio = 5.0f;
_zz_setratio(atof(tmp));
tmp = getenv("ZZUF_PROTECT");
if(tmp && *tmp)
_zz_list_init(_zz_protect, tmp);
_zz_readchars(_zz_protect, tmp);
tmp = getenv("ZZUF_REFUSE");
if(tmp && *tmp)
_zz_list_init(_zz_refuse, tmp);
_zz_readchars(_zz_refuse, tmp);
tmp = getenv("ZZUF_INCLUDE");
if(tmp && *tmp)
@@ -132,215 +120,3 @@ void _zz_fini(void)
_zz_fd_fini();
}
/* Byte list stuff */
static void _zz_list_init(int *table, char const *list)
{
static char const hex[] = "0123456789abcdef0123456789ABCDEF";
char const *tmp;
int a, b;
memset(table, 0, 256 * sizeof(int));
for(tmp = list, a = b = -1; *tmp; tmp++)
{
int new;
if(*tmp == '\\' && tmp[1] == '\0')
new = '\\';
else if(*tmp == '\\')
{
tmp++;
if(*tmp == 'n')
new = '\n';
else if(*tmp == 'r')
new = '\r';
else if(*tmp == 't')
new = '\t';
else if(tmp[0] >= '0' && tmp[0] <= '7' && tmp[1] >= '0'
&& tmp[1] <= '7' && tmp[2] >= '0' && tmp[2] <= '7')
{
new = tmp[2] - '0';
new |= (int)(tmp[1] - '0') << 3;
new |= (int)(tmp[0] - '0') << 6;
tmp += 2;
}
else if((*tmp == 'x' || *tmp == 'X')
&& tmp[1] && strchr(hex, tmp[1])
&& tmp[2] && strchr(hex, tmp[2]))
{
new = ((strchr(hex, tmp[1]) - hex) & 0xf) << 4;
new |= (strchr(hex, tmp[2]) - hex) & 0xf;
tmp += 2;
}
else
new = (unsigned char)*tmp; /* XXX: OK for \\, but what else? */
}
else
new = (unsigned char)*tmp;
if(a != -1 && b == '-' && a <= new)
{
while(a <= new)
table[a++] = 1;
a = b = -1;
}
else
{
if(a != -1)
table[a] = 1;
a = b;
b = new;
}
}
if(a != -1)
table[a] = 1;
if(b != -1)
table[b] = 1;
}
/* File descriptor stuff */
static struct files
{
int managed;
uint64_t seed;
uint64_t pos;
/* Public stuff */
struct fuzz fuzz;
}
*files;
static int *fds;
static int maxfd, nfiles;
static void _zz_fd_init(void)
{
files = NULL;
nfiles = 0;
/* Start with one fd in the lookup table */
fds = malloc(1 * sizeof(int));
for(maxfd = 0; maxfd < 1; maxfd++)
fds[maxfd] = -1;
}
static void _zz_fd_fini(void)
{
int i;
for(i = 0; i < maxfd; i++)
{
if(!files[fds[i]].managed)
continue;
/* XXX: What are we supposed to do? If filedescriptors weren't
* closed properly, there's a leak, but it's not our problem. */
}
free(files);
free(fds);
}
int _zz_mustwatch(char const *file)
{
if(re_include && regexec(re_include, file, 0, NULL, 0) == REG_NOMATCH)
return 0; /* not included: ignore */
if(re_exclude && regexec(re_exclude, file, 0, NULL, 0) != REG_NOMATCH)
return 0; /* excluded: ignore */
return 1; /* default */
}
int _zz_iswatched(int fd)
{
if(fd < 0 || fd >= maxfd || fds[fd] == -1)
return 0;
return 1;
}
void _zz_register(int fd)
{
int i;
if(fd < 0 || fd > 65535 || (fd < maxfd && fds[fd] != -1))
return;
while(fd >= maxfd)
{
fds = realloc(fds, 2 * maxfd * sizeof(int));
for(i = maxfd; i < maxfd * 2; i++)
fds[i] = -1;
maxfd *= 2;
}
/* Find an empty slot */
for(i = 0; i < nfiles; i++)
if(files[i].managed == 0)
break;
/* No slot found, allocate memory */
if(i == nfiles)
{
nfiles++;
files = realloc(files, nfiles * sizeof(struct files));
}
files[i].managed = 1;
files[i].pos = 0;
files[i].fuzz.cur = -1;
files[i].fuzz.data = malloc(CHUNKBYTES);
#ifdef HAVE_FGETLN
files[i].fuzz.tmp = NULL;
#endif
fds[fd] = i;
}
void _zz_unregister(int fd)
{
if(fd < 0 || fd >= maxfd || fds[fd] == -1)
return;
files[fds[fd]].managed = 0;
free(files[fds[fd]].fuzz.data);
#ifdef HAVE_FGETLN
if(files[fds[fd]].fuzz.tmp)
free(files[fds[fd]].fuzz.tmp);
#endif
fds[fd] = -1;
}
long int _zz_getpos(int fd)
{
if(fd < 0 || fd >= maxfd || fds[fd] == -1)
return 0;
return files[fds[fd]].pos;
}
void _zz_setpos(int fd, long int pos)
{
if(fd < 0 || fd >= maxfd || fds[fd] == -1)
return;
files[fds[fd]].pos = pos;
}
void _zz_addpos(int fd, long int off)
{
if(fd < 0 || fd >= maxfd || fds[fd] == -1)
return;
files[fds[fd]].pos += off;
}
struct fuzz *_zz_getfuzz(int fd)
{
if(fd < 0 || fd >= maxfd || fds[fd] == -1)
return NULL;
return &files[fds[fd]].fuzz;
}
-12
View File
@@ -38,8 +38,6 @@ struct fuzz
extern int _zz_ready;
extern int _zz_disabled;
extern int _zz_hasdebug;
extern float _zz_ratio;
extern int _zz_seed;
extern int _zz_signal;
extern int _zz_network;
@@ -51,13 +49,3 @@ extern int _zz_refuse[256];
extern void _zz_init(void) __attribute__((constructor));
extern void _zz_fini(void) __attribute__((destructor));
/* File descriptor handling */
extern int _zz_mustwatch(char const *);
extern int _zz_iswatched(int);
extern void _zz_register(int);
extern void _zz_unregister(int);
extern long int _zz_getpos(int);
extern void _zz_setpos(int, long int);
extern void _zz_addpos(int, long int);
extern struct fuzz *_zz_getfuzz(int);
+2
View File
@@ -31,6 +31,7 @@
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <regex.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -43,6 +44,7 @@
#include "debug.h"
#include "fuzz.h"
#include "load.h"
#include "fd.h"
/* Library functions that we divert */
static int (*open_orig) (const char *file, int oflag, ...);
+1
View File
@@ -28,6 +28,7 @@
#endif
#include <stdlib.h>
#include <dlfcn.h>
#include <regex.h>
#include <string.h>
#include <signal.h>
+2
View File
@@ -27,6 +27,7 @@
#endif
#include <stdlib.h>
#include <dlfcn.h>
#include <regex.h>
#include <stdio.h>
#include <sys/types.h>
@@ -38,6 +39,7 @@
#include "debug.h"
#include "fuzz.h"
#include "load.h"
#include "fd.h"
#if !defined __FreeBSD__ && !defined __OpenBSD__
# undef HAVE___SREFILL
+53 -8
View File
@@ -37,8 +37,11 @@
#include <time.h>
#include <sys/wait.h>
#include "random.h"
#include "libzzuf.h"
#include "random.h"
#include "chars.h"
#include "fd.h"
#include "fuzz.h"
static void spawn_child(char **);
static void clean_children(void);
@@ -52,6 +55,10 @@ static void version(void);
static void usage(void);
#endif
/* Global tables */
int _zz_protect[256];
int _zz_refuse[256];
static struct child_list
{
enum status
@@ -90,9 +97,11 @@ static double maxtime = -1.0;
int main(int argc, char *argv[])
{
char **newargv;
char *parser, *include = NULL, *exclude = NULL;
char *parser, *include, *exclude, *protect, *refuse;
int i, cmdline = 0;
include = exclude = protect = refuse = NULL;
#if defined(HAVE_GETOPT_H)
for(;;)
{
@@ -172,20 +181,21 @@ int main(int argc, char *argv[])
setenv("ZZUF_NETWORK", "1", 1);
break;
case 'P': /* --protect */
setenv("ZZUF_PROTECT", optarg, 1);
protect = optarg;
break;
case 'q': /* --quiet */
quiet = 1;
break;
case 'r': /* --ratio */
setenv("ZZUF_RATIO", optarg, 1);
_zz_setratio(atof(optarg));
break;
case 'R': /* --refuse */
setenv("ZZUF_REFUSE", optarg, 1);
refuse = optarg;
break;
case 's': /* --seed */
parser = strchr(optarg, ':');
seed = atoi(optarg);
_zz_setseed(seed = atol(optarg));
endseed = parser ? atoi(parser + 1) : seed + 1;
break;
case 'S': /* --signal */
@@ -211,11 +221,42 @@ int main(int argc, char *argv[])
int optind = 1;
#endif
/* If asked to read from the standard input */
if(optind >= argc)
{
printf("%s: missing argument\n", argv[0]);
printf(MOREINFO, argv[0]);
return EXIT_FAILURE;
if(endseed != seed + 1)
{
printf("%s: seed ranges are incompatible with stdin fuzzing\n",
argv[0]);
printf(MOREINFO, argv[0]);
return EXIT_FAILURE;
}
if(protect)
_zz_readchars(_zz_protect, protect);
if(refuse)
_zz_readchars(_zz_refuse, protect);
_zz_fd_init();
_zz_register(0);
for(;;)
{
uint8_t buf[12];
int ret = fread(buf, 1, 12, stdin);
if(ret <= 0)
break;
_zz_fuzz(0, buf, ret);
_zz_addpos(0, ret);
fwrite(buf, 1, ret, stdout);
}
_zz_unregister(0);
_zz_fd_fini();
return EXIT_SUCCESS;
}
if(cmdline)
@@ -237,6 +278,10 @@ int main(int argc, char *argv[])
setenv("ZZUF_INCLUDE", include, 1);
if(exclude)
setenv("ZZUF_EXCLUDE", exclude, 1);
if(protect)
setenv("ZZUF_PROTECT", protect, 1);
if(refuse)
setenv("ZZUF_REFUSE", refuse, 1);
/* Allocate memory for children handling */
child_list = malloc(maxforks * sizeof(struct child_list));