source: zzuf/trunk/src/fd.c @ 1792

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