source: zzuf/trunk/src/libzzuf.c @ 1554

Revision 1554, 6.5 KB checked in by sam, 6 years ago (diff)
  • Implement -P / --protect.
  • Property svn:keywords set to Id
Line 
1/*
2 *  zzuf - general purpose fuzzer
3 *  Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id$
7 *
8 *  This program is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15/*
16 *  libzzuf.c: preloaded wrapper library
17 */
18
19#include "config.h"
20#define _GNU_SOURCE
21
22#if defined HAVE_STDINT_H
23#   include <stdint.h>
24#elif defined HAVE_INTTYPES_H
25#   include <inttypes.h>
26#endif
27#include <stdio.h>
28#include <unistd.h>
29#include <stdlib.h>
30#include <string.h>
31#include <fcntl.h>
32#include <regex.h>
33
34#include <stdarg.h>
35#include <dlfcn.h>
36
37#include "libzzuf.h"
38#include "debug.h"
39#include "load.h"
40
41/* Global variables */
42int   _zz_ready    = 0;
43int   _zz_disabled = 0;
44int   _zz_hasdebug = 0;
45float _zz_ratio    = 0.004f;
46int   _zz_seed     = 0;
47int   _zz_signal   = 0;
48
49/* Global tables */
50int   _zz_protect[256];
51
52/* Local variables */
53static regex_t * re_include = NULL;
54static regex_t * re_exclude = NULL;
55
56/* Local prototypes */
57static void _zz_protect_init(char const *);
58static void _zz_fd_init(void);
59static void _zz_fd_fini(void);
60
61/* Library initialisation shit */
62void _zz_init(void)
63{
64    char *tmp;
65
66    tmp = getenv("ZZUF_DEBUG");
67    if(tmp && *tmp == '1')
68        _zz_hasdebug = 1;
69
70    tmp = getenv("ZZUF_SEED");
71    if(tmp && *tmp)
72        _zz_seed = atol(tmp);
73
74    tmp = getenv("ZZUF_RATIO");
75    if(tmp && *tmp)
76        _zz_ratio = atof(tmp);
77    if(_zz_ratio < 0.0f)
78        _zz_ratio = 0.0f;
79    else if(_zz_ratio > 5.0f)
80        _zz_ratio = 5.0f;
81
82    tmp = getenv("ZZUF_PROTECT");
83    if(tmp && *tmp)
84        _zz_protect_init(tmp);
85
86    tmp = getenv("ZZUF_INCLUDE");
87    if(tmp && *tmp)
88    {
89        re_include = malloc(sizeof(*re_include));
90        regcomp(re_include, tmp, REG_EXTENDED);
91    }
92
93    tmp = getenv("ZZUF_EXCLUDE");
94    if(tmp && *tmp)
95    {
96        re_exclude = malloc(sizeof(*re_exclude));
97        regcomp(re_exclude, tmp, REG_EXTENDED);
98    }
99
100    tmp = getenv("ZZUF_SIGNAL");
101    if(tmp && *tmp == '1')
102        _zz_signal = 1;
103
104    _zz_fd_init();
105
106    tmp = getenv("ZZUF_STDIN");
107    if(tmp && *tmp == '1')
108        _zz_register(0);
109
110    _zz_load_fd();
111    _zz_load_signal();
112    _zz_load_stream();
113
114    _zz_ready = 1;
115
116    debug("libzzuf initialised");
117}
118
119/* Deinitialisation */
120void _zz_fini(void)
121{
122    _zz_fd_fini();
123}
124
125/* Byte list stuff */
126static void _zz_protect_init(char const *list)
127{
128    static char const hex[] = "0123456789abcdef0123456789ABCDEF";
129    char const *tmp;
130    int a, b;
131
132    memset(_zz_protect, 0, 256 * sizeof(int));
133
134    for(tmp = list, a = b = -1; *tmp; tmp++)
135    {
136        int new;
137
138        if(*tmp == '\\' && tmp[1] == '\0')
139            new = '\\';
140        else if(*tmp == '\\')
141        {
142            tmp++;
143            if(*tmp == 'n')
144                new = '\n';
145            else if(*tmp == 'r')
146                new = '\r';
147            else if(*tmp == 't')
148                new = '\t';
149            else if(*tmp == '0')
150                new = '\0';
151            else if((*tmp == 'x' || *tmp == 'X')
152                     && tmp[1] && strchr(hex, tmp[1])
153                     && tmp[2] && strchr(hex, tmp[2]))
154            {
155                new = ((strchr(hex, tmp[1]) - hex) & 0xf) << 4;
156                new |= (strchr(hex, tmp[2]) - hex) & 0xf;
157                tmp += 2;
158            }
159            else
160                new = (unsigned char)*tmp; /* XXX: OK for \\, but what else? */
161        }
162        else
163            new = (unsigned char)*tmp;
164
165        if(a != -1 && b == '-' && a <= new)
166        {
167            while(a <= new)
168                _zz_protect[a++] = 1;
169            a = b = -1;
170        }
171        else
172        {
173            if(a != -1)
174                _zz_protect[a] = 1;
175            a = b;
176            b = new;
177        }
178    }
179
180    if(a != -1)
181        _zz_protect[a] = 1;
182    if(b != -1)
183        _zz_protect[b] = 1;
184}
185
186/* File descriptor stuff */
187static struct files
188{
189    int managed;
190    uint64_t seed;
191    uint64_t pos;
192    /* Public stuff */
193    struct fuzz fuzz;
194}
195*files;
196static int *fds;
197static int maxfd, nfiles;
198
199static void _zz_fd_init(void)
200{
201    files = NULL;
202    nfiles = 0;
203
204    /* Start with one fd in the lookup table */
205    fds = malloc(1 * sizeof(int));
206    for(maxfd = 0; maxfd < 1; maxfd++)
207        fds[maxfd] = -1;
208}
209
210static void _zz_fd_fini(void)
211{
212    int i;
213
214    for(i = 0; i < maxfd; i++)
215    {
216        if(!files[fds[i]].managed)
217            continue;
218
219        /* XXX: What are we supposed to do? If filedescriptors weren't
220         * closed properly, there's a leak, but it's not our problem. */
221    }
222
223    free(files);
224    free(fds);
225}
226
227int _zz_mustwatch(char const *file)
228{
229    if(re_include && regexec(re_include, file, 0, NULL, 0) == REG_NOMATCH)
230        return 0; /* not included: ignore */
231
232    if(re_exclude && regexec(re_exclude, file, 0, NULL, 0) != REG_NOMATCH)
233        return 0; /* excluded: ignore */
234
235    return 1; /* default */
236}
237
238int _zz_iswatched(int fd)
239{
240    if(fd < 0 || fd >= maxfd || fds[fd] == -1)
241        return 0;
242
243    return 1;
244}
245
246void _zz_register(int fd)
247{
248    int i;
249
250    if(fd < 0 || fd > 65535 || (fd < maxfd && fds[fd] != -1))
251        return;
252
253    while(fd >= maxfd)
254    {
255        fds = realloc(fds, 2 * maxfd * sizeof(int));
256        for(i = maxfd; i < maxfd * 2; i++)
257            fds[i] = -1;
258        maxfd *= 2;
259    }
260           
261    /* Find an empty slot */
262    for(i = 0; i < nfiles; i++)
263        if(files[i].managed == 0)
264            break;
265
266    /* No slot found, allocate memory */
267    if(i == nfiles)
268    {
269        nfiles++;
270        files = realloc(files, nfiles * sizeof(struct files));
271    }
272
273    files[i].managed = 1;
274    files[i].pos = 0;
275    files[i].fuzz.cur = -1;
276    files[i].fuzz.data = malloc(CHUNKBYTES);
277
278    fds[fd] = i;
279}
280
281void _zz_unregister(int fd)
282{
283    if(fd < 0 || fd >= maxfd || fds[fd] == -1)
284        return;
285
286    files[fds[fd]].managed = 0;
287    free(files[fds[fd]].fuzz.data);
288
289    fds[fd] = -1;
290}
291
292long int _zz_getpos(int fd)
293{
294    if(fd < 0 || fd >= maxfd || fds[fd] == -1)
295        return 0;
296
297    return files[fds[fd]].pos;
298}
299
300void _zz_setpos(int fd, long int pos)
301{
302    if(fd < 0 || fd >= maxfd || fds[fd] == -1)
303        return;
304
305    files[fds[fd]].pos = pos;
306}
307
308void _zz_addpos(int fd, long int off)
309{
310    if(fd < 0 || fd >= maxfd || fds[fd] == -1)
311        return;
312
313    files[fds[fd]].pos += off;
314}
315
316struct fuzz *_zz_getfuzz(int fd)
317{
318    if(fd < 0 || fd >= maxfd || fds[fd] == -1)
319        return NULL;
320
321    return &files[fds[fd]].fuzz;
322}
323
Note: See TracBrowser for help on using the repository browser.