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

Last change on this file since 4112 was 4112, checked in by sam, 5 years ago

Reorganise source code to better separate zzuf and libzzuf. Note: the Win32
build is now broken.

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