source: zzuf/trunk/src/preload.c @ 1482

Last change on this file since 1482 was 1482, checked in by Sam Hocevar, 16 years ago
  • Implemented lseek() and factored lseek64() code.
  • Property svn:keywords set to Id
File size: 7.6 KB
Line 
1/*
2 *  zzuf - general purpose fuzzer
3 *  Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: preload.c 1482 2006-12-15 13:20:01Z 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 *  preload.c: preloaded library functions
17 */
18
19#include "config.h"
20
21/* Can't remember what that's for */
22#define _GNU_SOURCE
23/* Use this to get lseek64() */
24#define _LARGEFILE64_SOURCE
25
26#if defined HAVE_STDINT_H
27#   include <stdint.h>
28#elif defined HAVE_INTTYPES_H
29#   include <inttypes.h>
30#endif
31#include <stdio.h>
32#include <sys/types.h>
33#include <unistd.h>
34#include <stdlib.h>
35#include <fcntl.h>
36#include <regex.h>
37
38#include <stdarg.h>
39#include <dlfcn.h>
40
41#include "libzzuf.h"
42#include "debug.h"
43#include "fuzz.h"
44#include "preload.h"
45
46/* Library functions that we divert */
47static FILE *  (*fopen_orig)   (const char *path, const char *mode);
48static FILE *  (*fopen64_orig) (const char *path, const char *mode);
49static int     (*fseek_orig)   (FILE *stream, long offset, int whence);
50static size_t  (*fread_orig)   (void *ptr, size_t size, size_t nmemb,
51                                FILE *stream);
52static int     (*fclose_orig)  (FILE *fp);
53
54static int     (*open_orig)    (const char *file, int oflag, ...);
55static int     (*open64_orig)  (const char *file, int oflag, ...);
56static ssize_t (*read_orig)    (int fd, void *buf, size_t count);
57static off_t   (*lseek_orig)   (int fd, off_t offset, int whence);
58static off64_t (*lseek64_orig) (int fd, off64_t offset, int whence);
59static int     (*close_orig)   (int fd);
60
61#define STR(x) #x
62#define ORIG(x) x##_orig
63
64#define LOADSYM(x) \
65    do { \
66        ORIG(x) = dlsym(RTLD_NEXT, STR(x)); \
67        if(!ORIG(x)) \
68            abort(); \
69    } while(0)
70
71int zzuf_preload(void)
72{
73    LOADSYM(fopen);
74    LOADSYM(fopen64);
75    LOADSYM(fseek);
76    LOADSYM(fread);
77    LOADSYM(fclose);
78
79    LOADSYM(open);
80    LOADSYM(open64);
81    LOADSYM(read);
82    LOADSYM(lseek);
83    LOADSYM(lseek64);
84    LOADSYM(close);
85
86    debug("libzzuf initialised");
87
88    return 0;
89}
90
91/* Our function wrappers */
92#define FOPEN(fn) \
93    do \
94    { \
95        if(!_zzuf_ready) \
96            LOADSYM(fn); \
97        ret = ORIG(fn)(path, mode); \
98        if(!_zzuf_ready) \
99            return ret; \
100        if(ret) \
101        { \
102            if(_zzuf_include && \
103                regexec(_zzuf_include, path, 0, NULL, 0) == REG_NOMATCH) \
104                /* not included: ignore */ ; \
105            else if(_zzuf_exclude && \
106                    regexec(_zzuf_exclude, path, 0, NULL, 0) != REG_NOMATCH) \
107                /* excluded: ignore */ ; \
108            else \
109            { \
110                int fd = fileno(ret); \
111                files[fd].managed = 1; \
112                files[fd].pos = 0; \
113                debug(STR(fn) "(\"%s\", \"%s\") = %p", path, mode, ret); \
114            } \
115        } \
116    } while(0)
117
118FILE *fopen(const char *path, const char *mode)
119{
120    FILE *ret; FOPEN(fopen); return ret;
121}
122
123FILE *fopen64(const char *path, const char *mode)
124{
125    FILE *ret; FOPEN(fopen64); return ret;
126}
127
128int fseek(FILE *stream, long offset, int whence)
129{
130    int ret, fd;
131
132    if(!_zzuf_ready)
133        LOADSYM(fseek);
134    ret = fseek_orig(stream, offset, whence);
135    if(!_zzuf_ready)
136        return ret;
137
138    fd = fileno(stream);
139    if(!files[fd].managed)
140        return ret;
141
142    debug("fseek(%p, %li, %i) = %i", stream, offset, whence, ret);
143    if(ret == 0)
144    {
145        switch(whence)
146        {
147            case SEEK_SET: files[fd].pos = offset; break;
148            case SEEK_CUR: files[fd].pos += offset; break;
149            case SEEK_END: files[fd].pos = ftell(stream); break;
150        }
151    }
152    return ret;
153}
154
155size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
156{
157    size_t ret;
158    int fd;
159
160    if(!_zzuf_ready)
161        LOADSYM(fread);
162    ret = fread_orig(ptr, size, nmemb, stream);
163    if(!_zzuf_ready)
164        return ret;
165
166    fd = fileno(stream);
167    if(!files[fd].managed)
168        return ret;
169
170    debug("fread(%p, %li, %li, %p) = %li",
171          ptr, (long int)size, (long int)nmemb, stream, (long int)ret);
172    if(ret > 0)
173    {
174        zzuf_fuzz(fd, ptr, ret * size);
175        files[fd].pos += ret * size;
176    }
177    return ret;
178}
179
180int fclose(FILE *fp)
181{
182    int ret, fd;
183
184    if(!_zzuf_ready)
185        LOADSYM(fclose);
186    fd = fileno(fp);
187    ret = fclose_orig(fp);
188    if(!_zzuf_ready)
189        return ret;
190
191    if(!files[fd].managed)
192        return ret;
193
194    debug("fclose(%p) = %i", fp, ret);
195    files[fd].managed = 0;
196
197    return ret;
198}
199
200#define OPEN(fn) \
201    do \
202    { \
203        int mode = 0; \
204        if(!_zzuf_ready) \
205            LOADSYM(fn); \
206        if(oflag & O_CREAT) \
207        { \
208            va_list va; \
209            va_start(va, oflag); \
210            mode = va_arg(va, int); \
211            va_end(va); \
212            ret = ORIG(fn)(file, oflag, mode); \
213        } \
214        else \
215        { \
216            ret = ORIG(fn)(file, oflag); \
217        } \
218        if(!_zzuf_ready) \
219            return ret; \
220        if(ret >= 0 \
221            && ((oflag & (O_RDONLY | O_RDWR | O_WRONLY)) != O_WRONLY)) \
222        { \
223            if(_zzuf_include && \
224                regexec(_zzuf_include, file, 0, NULL, 0) == REG_NOMATCH) \
225                /* not included: ignore */ ; \
226            else if(_zzuf_exclude && \
227                    regexec(_zzuf_exclude, file, 0, NULL, 0) != REG_NOMATCH) \
228                /* excluded: ignore */ ; \
229            else \
230            { \
231                if(oflag & O_CREAT) \
232                    debug(STR(fn) "(\"%s\", %i, %i) = %i", \
233                          file, oflag, mode, ret); \
234                else \
235                    debug(STR(fn) "(\"%s\", %i) = %i", file, oflag, ret); \
236                files[ret].managed = 1; \
237                files[ret].pos = 0; \
238            } \
239        } \
240    } while(0)
241
242int open(const char *file, int oflag, ...)
243{
244    int ret; OPEN(open); return ret;
245}
246
247int open64(const char *file, int oflag, ...)
248{
249    int ret; OPEN(open64); return ret;
250}
251
252ssize_t read(int fd, void *buf, size_t count)
253{
254    int ret;
255
256    if(!_zzuf_ready)
257        LOADSYM(read);
258    ret = read_orig(fd, buf, count);
259    if(!_zzuf_ready)
260        return ret;
261
262    if(!files[fd].managed)
263        return ret;
264
265    debug("read(%i, %p, %li) = %i", fd, buf, (long int)count, ret);
266    if(ret > 0)
267    {
268        zzuf_fuzz(fd, buf, ret);
269        files[fd].pos += ret;
270    }
271
272    /* Sanity check */
273    if((uint64_t)lseek64_orig(fd, 0, SEEK_CUR) != files[fd].pos)
274        fprintf(stderr, "ZZUF ERROR: OFFSET INCONSISTENCY\n");
275
276    return ret;
277}
278
279#define LSEEK(fn, off_t) \
280    do { \
281        if(!_zzuf_ready) \
282            LOADSYM(fn); \
283        ret = ORIG(fn)(fd, offset, whence); \
284        if(!_zzuf_ready) \
285            return ret; \
286        if(!files[fd].managed) \
287            return ret; \
288        debug(STR(fn)"(%i, %lli, %i) = %lli", \
289              fd, (long long int)offset, whence, (long long int)ret); \
290        if(ret != (off_t)-1) \
291            files[fd].pos = (int64_t)ret; \
292    } while(0)
293
294off_t lseek(int fd, off_t offset, int whence)
295{
296    off_t ret;
297    LSEEK(lseek, off_t);
298    return ret;
299}
300
301off64_t lseek64(int fd, off64_t offset, int whence)
302{
303    off64_t ret;
304    LSEEK(lseek64, off64_t);
305    return ret;
306}
307
308int close(int fd)
309{
310    int ret;
311
312    if(!_zzuf_ready)
313        LOADSYM(close);
314    ret = close_orig(fd);
315    if(!_zzuf_ready)
316        return ret;
317
318    if(!files[fd].managed)
319        return ret;
320
321    debug("close(%i) = %i", fd, ret);
322    files[fd].managed = 0;
323
324    return ret;
325}
326
Note: See TracBrowser for help on using the repository browser.