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

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