source: zzuf/trunk/src/fuzz.c @ 1621

Last change on this file since 1621 was 1621, checked in by Sam Hocevar, 14 years ago
  • Factor regex stuff into fd.c, so that <regex.h> isn’t needed otherwhere.
  • Property svn:keywords set to Id
File size: 4.7 KB
Line 
1/*
2 *  zzuf - general purpose fuzzer
3 *  Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: fuzz.c 1621 2007-01-07 21:14:26Z 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 *  fuzz.c: fuzz functions
17 */
18
19#include "config.h"
20
21#if defined HAVE_STDINT_H
22#   include <stdint.h>
23#elif defined HAVE_INTTYPES_H
24#   include <inttypes.h>
25#endif
26#include <stdio.h>
27#include <string.h>
28
29#include "libzzuf.h"
30#include "debug.h"
31#include "random.h"
32#include "fuzz.h"
33#include "fd.h"
34
35#define MAGIC1 0x33ea84f7
36#define MAGIC2 0x783bc31f
37
38/* Fuzzing variables */
39static int   protect[256];
40static int   refuse[256];
41static float ratio = 0.004f;
42static int   seed  = 0;
43
44static void readchars(int *, char const *);
45
46void _zz_protect(char const *list)
47{
48    readchars(protect, list);
49}
50
51void _zz_refuse(char const *list)
52{
53    readchars(refuse, list);
54}
55
56void _zz_setseed(int s)
57{
58    seed = s;
59}
60
61void _zz_setratio(float r)
62{
63    if(r < 0.0f)
64        r = 0.0f;
65    else if(r > 5.0f)
66        r = 5.0f;
67    ratio = r;
68}
69
70void _zz_fuzz(int fd, uint8_t *buf, uint64_t len)
71{
72    uint64_t start, stop;
73    struct fuzz *fuzz;
74    uint8_t *aligned_buf;
75    unsigned long int pos = _zz_getpos(fd);
76    unsigned int i, j, todo;
77
78#if 0
79    debug("fuzz(%i, %lli@%li)", fd, (unsigned long long int)len,
80          (unsigned long int)pos);
81#endif
82
83    fuzz = _zz_getfuzz(fd);
84    aligned_buf = buf - pos;
85
86    for(i = pos / CHUNKBYTES;
87        i < (pos + len + CHUNKBYTES - 1) / CHUNKBYTES;
88        i++)
89    {
90        /* Cache bitmask array */
91        if(fuzz->cur != (int)i)
92        {
93            uint32_t chunkseed = i * MAGIC1;
94
95            memset(fuzz->data, 0, CHUNKBYTES);
96
97            /* Add some random dithering to handle ratio < 1.0/CHUNKBYTES */
98            _zz_srand(seed ^ chunkseed);
99            todo = (int)((ratio * (8 * CHUNKBYTES * 1000)
100                                             + _zz_rand(1000)) / 1000.0);
101            _zz_srand(seed ^ chunkseed ^ (todo * MAGIC2));
102
103            while(todo--)
104            {
105                unsigned int idx = _zz_rand(CHUNKBYTES);
106                uint8_t bit = (1 << _zz_rand(8));
107
108                fuzz->data[idx] ^= bit;
109            }
110
111            fuzz->cur = i;
112        }
113
114        /* Apply our bitmask array to the buffer */
115        start = (i * CHUNKBYTES > pos) ? i * CHUNKBYTES : pos;
116
117        stop = ((i + 1) * CHUNKBYTES < pos + len)
118              ? (i + 1) * CHUNKBYTES : pos + len;
119
120        for(j = start; j < stop; j++)
121        {
122            uint8_t byte = aligned_buf[j];
123
124            if(protect[byte])
125                continue;
126
127            byte ^= fuzz->data[j % CHUNKBYTES];
128
129            if(refuse[byte])
130                continue;
131
132            aligned_buf[j] = byte;
133        }
134    }
135}
136
137static void readchars(int *table, char const *list)
138{
139    static char const hex[] = "0123456789abcdef0123456789ABCDEF";
140    char const *tmp;
141    int a, b;
142
143    memset(table, 0, 256 * sizeof(int));
144
145    for(tmp = list, a = b = -1; *tmp; tmp++)
146    {
147        int new;
148
149        if(*tmp == '\\' && tmp[1] == '\0')
150            new = '\\';
151        else if(*tmp == '\\')
152        {
153            tmp++;
154            if(*tmp == 'n')
155                new = '\n';
156            else if(*tmp == 'r')
157                new = '\r';
158            else if(*tmp == 't')
159                new = '\t';
160            else if(tmp[0] >= '0' && tmp[0] <= '7' && tmp[1] >= '0'
161                     && tmp[1] <= '7' && tmp[2] >= '0' && tmp[2] <= '7')
162            {
163                new = tmp[2] - '0';
164                new |= (int)(tmp[1] - '0') << 3;
165                new |= (int)(tmp[0] - '0') << 6;
166                tmp += 2;
167            }
168            else if((*tmp == 'x' || *tmp == 'X')
169                     && tmp[1] && strchr(hex, tmp[1])
170                     && tmp[2] && strchr(hex, tmp[2]))
171            {
172                new = ((strchr(hex, tmp[1]) - hex) & 0xf) << 4;
173                new |= (strchr(hex, tmp[2]) - hex) & 0xf;
174                tmp += 2;
175            }
176            else
177                new = (unsigned char)*tmp; /* XXX: OK for \\, but what else? */
178        }
179        else
180            new = (unsigned char)*tmp;
181
182        if(a != -1 && b == '-' && a <= new)
183        {
184            while(a <= new)
185                table[a++] = 1;
186            a = b = -1;
187        }
188        else
189        {
190            if(a != -1)
191                table[a] = 1;
192            a = b;
193            b = new;
194        }
195    }
196
197    if(a != -1)
198        table[a] = 1;
199    if(b != -1)
200        table[b] = 1;
201}
202
Note: See TracBrowser for help on using the repository browser.