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

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