source: zzuf/trunk/src/common/fd.c @ 4836

Last change on this file since 4836 was 4836, checked in by Sam Hocevar, 8 years ago

build: fix compilation by including <wchar.h> and checking for regwexec.

  • Property svn:keywords set to Id
File size: 9.2 KB
Line 
1/*
2 *  zzuf - general purpose fuzzer
3 *  Copyright (c) 2006-2010 Sam Hocevar <sam@hocevar.net>
4 *                All Rights Reserved
5 *
6 *  This program is free software. It comes without any warranty, to
7 *  the extent permitted by applicable law. You can redistribute it
8 *  and/or modify it under the terms of the Do What The Fuck You Want
9 *  To Public License, Version 2, as published by Sam Hocevar. See
10 *  http://sam.zoy.org/wtfpl/COPYING for more details.
11 */
12
13/*
14 *  libzzuf.c: preloaded wrapper library
15 */
16
17#include "config.h"
18#define _GNU_SOURCE
19
20#if defined HAVE_STDINT_H
21#   include <stdint.h>
22#elif defined HAVE_INTTYPES_H
23#   include <inttypes.h>
24#endif
25#include <stdlib.h>
26#if defined HAVE_REGEX_H
27#   if _WIN32
28#       include "../com_regexp.hpp"
29#   else
30#       include <regex.h>
31#   endif
32#endif
33#include <string.h>
34#include <math.h>
35
36#include "common.h"
37#include "fd.h"
38#include "fuzz.h"
39#include "ranges.h"
40#if defined LIBZZUF
41#   include "debug.h"
42#   include "network.h"
43#endif
44
45/* Regex stuff */
46#if defined HAVE_REGEX_H
47static regex_t re_include, re_exclude;
48static int has_include = 0, has_exclude = 0;
49#endif
50
51/* File descriptor cherry picking */
52static int64_t *list = NULL;
53static int64_t static_list[512];
54
55/* File descriptor stuff. When program is launched, we use the static array of
56 * 32 structures, which ought to be enough for most programs. If it happens
57 * not to be the case, ie. if the process opens more than 32 file descriptors
58 * at the same time, a bigger array is malloc()ed and replaces the static one.
59 */
60#define STATIC_FILES 32
61static struct files
62{
63    int managed, locked, active, already_fuzzed;
64    int64_t pos, already_pos;
65    /* Public stuff */
66    struct fuzz fuzz;
67}
68*files, static_files[STATIC_FILES];
69static int *fds, static_fds[STATIC_FILES];
70static int maxfd, nfiles;
71
72/* Create lock. This lock variable is used to disable file descriptor
73 * creation wrappers. For instance on Mac OS X, fopen() calls open()
74 * and we don’t want open() to do any zzuf-related stuff: fopen() takes
75 * care of everything. */
76static int create_lock = 0;
77
78static int32_t seed = DEFAULT_SEED;
79static double  minratio = DEFAULT_RATIO;
80static double  maxratio = DEFAULT_RATIO;
81static int     autoinc = 0;
82
83void _zz_include(char const *regex)
84{
85#if defined HAVE_REGEX_H
86    if(regcomp(&re_include, regex, REG_EXTENDED) == 0)
87        has_include = 1;
88#else
89    (void)regex;
90#endif
91}
92
93void _zz_exclude(char const *regex)
94{
95#if defined HAVE_REGEX_H
96    if(regcomp(&re_exclude, regex, REG_EXTENDED) == 0)
97        has_exclude = 1;
98#else
99    (void)regex;
100#endif
101}
102
103void _zz_list(char const *fdlist)
104{
105    list = _zz_allocrange(fdlist, static_list);
106}
107
108void _zz_setseed(int32_t s)
109{
110    seed = s;
111}
112
113void _zz_setratio(double r0, double r1)
114{
115    if(r0 == 0.0 && r1 == 0.0)
116    {
117        maxratio = minratio = 0.0;
118        return;
119    }
120
121    minratio = r0 < MIN_RATIO ? MIN_RATIO : r0 > MAX_RATIO ? MAX_RATIO : r0;
122    maxratio = r1 < MIN_RATIO ? MIN_RATIO : r1 > MAX_RATIO ? MAX_RATIO : r1;
123    if(maxratio < minratio)
124        maxratio = minratio;
125}
126
127double _zz_getratio(void)
128{
129    uint8_t const shuffle[16] =
130    { 0, 12, 2, 10,
131      14, 8, 15, 7,
132      9, 13, 3, 6,
133      4, 1, 11, 5 };
134    uint16_t rate;
135    double min, max, cur;
136
137    if(minratio == maxratio)
138        return minratio; /* this also takes care of 0.0 */
139
140    rate = shuffle[seed & 0xf] << 12;
141    rate |= (seed & 0xf0) << 4;
142    rate |= (seed & 0xf00) >> 4;
143    rate |= (seed & 0xf000) >> 12;
144
145    min = log(minratio);
146    max = log(maxratio);
147
148    cur = min + (max - min) * rate / 0xffff;
149
150    return exp(cur);
151}
152
153void _zz_setautoinc(void)
154{
155    autoinc = 1;
156}
157
158void _zz_fd_init(void)
159{
160    /* We start with 32 file descriptors. This is to reduce the number of
161     * calls to malloc() that we do, so we get better chances that memory
162     * corruption errors are reproducible */
163    files = static_files;
164    for(nfiles = 0; nfiles < 32; nfiles++)
165        files[nfiles].managed = 0;
166
167    fds = static_fds;
168    for(maxfd = 0; maxfd < 32; maxfd++)
169        fds[maxfd] = -1;
170}
171
172void _zz_fd_fini(void)
173{
174    int i;
175
176    for(i = 0; i < maxfd; i++)
177    {
178        if(!files[fds[i]].managed)
179            continue;
180
181        /* XXX: What are we supposed to do? If filedescriptors weren't
182         * closed properly, there's a leak, but it's not our problem. */
183    }
184
185#if defined HAVE_REGEX_H
186    if(has_include)
187        regfree(&re_include);
188    if(has_exclude)
189        regfree(&re_exclude);
190#endif
191
192    if(files != static_files)
193       free(files);
194    if(fds != static_fds)
195        free(fds);
196    if(list != static_list)
197        free(list);
198}
199
200int _zz_mustwatch(char const *file)
201{
202#if defined HAVE_REGEXEC
203    if(has_include && regexec(&re_include, file, 0, NULL, 0) == REG_NOMATCH)
204        return 0; /* not included: ignore */
205
206    if(has_exclude && regexec(&re_exclude, file, 0, NULL, 0) != REG_NOMATCH)
207        return 0; /* excluded: ignore */
208#else
209    (void)file;
210#endif
211
212    return 1; /* default */
213}
214
215int _zz_mustwatchw(wchar_t const *file)
216{
217#if defined HAVE_REGWEXEC
218    if(has_include && regwexec(&re_include, file, 0, NULL, 0) == REG_NOMATCH)
219        return 0; /* not included: ignore */
220
221    if(has_exclude && regwexec(&re_exclude, file, 0, NULL, 0) != REG_NOMATCH)
222        return 0; /* excluded: ignore */
223#else
224    (void)file;
225#endif
226
227    return 1; /* default */
228}
229
230int _zz_iswatched(int fd)
231{
232    if(fd < 0 || fd >= maxfd || fds[fd] == -1)
233        return 0;
234
235    return 1;
236}
237
238void _zz_register(int fd)
239{
240    int i;
241
242    if(fd < 0 || fd > 65535 || (fd < maxfd && fds[fd] != -1))
243        return;
244
245#if defined LIBZZUF
246    if(autoinc)
247        debug2("using seed %li", (long int)seed);
248#endif
249
250    /* If filedescriptor is outside our bounds */
251    while(fd >= maxfd)
252    {
253        if(fds == static_fds)
254        {
255            fds = malloc(2 * maxfd * sizeof(*fds));
256            memcpy(fds, static_fds, maxfd * sizeof(*fds));
257        }
258        else
259            fds = realloc(fds, 2 * maxfd * sizeof(*fds));
260        for(i = maxfd; i < maxfd * 2; i++)
261            fds[i] = -1;
262        maxfd *= 2;
263    }
264
265    /* Find an empty slot */
266    for(i = 0; i < nfiles; i++)
267        if(files[i].managed == 0)
268            break;
269
270    /* No slot found, allocate memory */
271    if(i == nfiles)
272    {
273        nfiles++;
274        if(files == static_files)
275        {
276            files = malloc(nfiles * sizeof(*files));
277            memcpy(files, static_files, nfiles * sizeof(*files));
278        }
279        else
280            files = realloc(files, nfiles * sizeof(*files));
281    }
282
283    files[i].managed = 1;
284    files[i].locked = 0;
285    files[i].pos = 0;
286    files[i].fuzz.seed = seed;
287    files[i].fuzz.ratio = _zz_getratio();
288    files[i].fuzz.cur = -1;
289#if defined HAVE_FGETLN
290    files[i].fuzz.tmp = NULL;
291#endif
292    files[i].fuzz.uflag = 0;
293
294    /* Check whether we should ignore the fd */
295    if(list)
296    {
297        static int idx = 0;
298
299        files[i].active = _zz_isinrange(++idx, list);
300    }
301    else
302        files[i].active = 1;
303
304    if(autoinc)
305        seed++;
306
307    fds[fd] = i;
308}
309
310void _zz_unregister(int fd)
311{
312    if(fd < 0 || fd >= maxfd || fds[fd] == -1)
313        return;
314
315    files[fds[fd]].managed = 0;
316#if defined HAVE_FGETLN
317    if(files[fds[fd]].fuzz.tmp)
318        free(files[fds[fd]].fuzz.tmp);
319#endif
320
321    fds[fd] = -1;
322}
323
324void _zz_lock(int fd)
325{
326    if(fd < -1 || fd >= maxfd || fds[fd] == -1)
327        return;
328
329    if(fd == -1)
330        create_lock++;
331    else
332        files[fds[fd]].locked++;
333}
334
335void _zz_unlock(int fd)
336{
337    if(fd < -1 || fd >= maxfd || fds[fd] == -1)
338        return;
339
340    if(fd == -1)
341        create_lock--;
342    else
343        files[fds[fd]].locked--;
344}
345
346int _zz_islocked(int fd)
347{
348    if(fd < -1 || fd >= maxfd || fds[fd] == -1)
349        return 0;
350
351    if(fd == -1)
352        return create_lock;
353    else
354        return files[fds[fd]].locked;
355}
356
357int _zz_isactive(int fd)
358{
359    if(fd < 0 || fd >= maxfd || fds[fd] == -1)
360        return 1;
361
362    return files[fds[fd]].active;
363}
364
365int64_t _zz_getpos(int fd)
366{
367    if(fd < 0 || fd >= maxfd || fds[fd] == -1)
368        return 0;
369
370    return files[fds[fd]].pos;
371}
372
373void _zz_setpos(int fd, int64_t pos)
374{
375    if(fd < 0 || fd >= maxfd || fds[fd] == -1)
376        return;
377
378    files[fds[fd]].pos = pos;
379}
380
381void _zz_addpos(int fd, int64_t off)
382{
383    if(fd < 0 || fd >= maxfd || fds[fd] == -1)
384        return;
385
386    files[fds[fd]].pos += off;
387}
388
389void _zz_setfuzzed(int fd, int count)
390{
391    if(fd < 0 || fd >= maxfd || fds[fd] == -1)
392        return;
393
394    /* FIXME: what if we just slightly advanced? */
395    if(files[fds[fd]].pos == files[fds[fd]].already_pos
396        && count <= files[fds[fd]].already_fuzzed)
397        return;
398
399#if defined LIBZZUF
400    debug2("setfuzzed(%i, %i)", fd, count);
401#endif
402
403    files[fds[fd]].already_pos = files[fds[fd]].pos;
404    files[fds[fd]].already_fuzzed = count;
405}
406
407int _zz_getfuzzed(int fd)
408{
409    if(fd < 0 || fd >= maxfd || fds[fd] == -1)
410        return 0;
411
412    if(files[fds[fd]].pos < files[fds[fd]].already_pos)
413        return 0;
414
415    if(files[fds[fd]].pos >= files[fds[fd]].already_pos
416                               + files[fds[fd]].already_fuzzed)
417        return 0;
418
419    return (int)(files[fds[fd]].already_fuzzed + files[fds[fd]].already_pos
420                                               - files[fds[fd]].pos);
421}
422
423struct fuzz *_zz_getfuzz(int fd)
424{
425    if(fd < 0 || fd >= maxfd || fds[fd] == -1)
426        return NULL;
427
428    return &files[fds[fd]].fuzz;
429}
430
Note: See TracBrowser for help on using the repository browser.