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

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