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

Last change on this file since 4253 was 4253, checked in by sam, 4 years ago

Fix copyright information and remove Id tag everywhere.

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