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

Revision 1479, 7.2 KB checked in by sam, 6 years ago (diff)
  • Oops, fix a bug in the lseek64() diversion.
  • Property svn:keywords set to Id
Line 
1/*
2 *  zzuf - general purpose fuzzer
3 *  Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id$
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 <errno.h>
37#include <regex.h>
38
39#include <stdarg.h>
40#include <dlfcn.h>
41
42#include "libzzuf.h"
43#include "debug.h"
44#include "fuzz.h"
45#include "preload.h"
46
47/* Library functions that we divert */
48static FILE *  (*fopen_orig)   (const char *path, const char *mode);
49static FILE *  (*fopen64_orig) (const char *path, const char *mode);
50static int     (*fseek_orig)   (FILE *stream, long offset, int whence);
51static size_t  (*fread_orig)   (void *ptr, size_t size, size_t nmemb,
52                                FILE *stream);
53static int     (*fclose_orig)  (FILE *fp);
54
55static int     (*open_orig)    (const char *file, int oflag, ...);
56static int     (*open64_orig)  (const char *file, int oflag, ...);
57static ssize_t (*read_orig)    (int fd, void *buf, size_t count);
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(lseek64);
83    LOADSYM(close);
84
85    debug("libzzuf initialised");
86
87    return 0;
88}
89
90/* Our function wrappers */
91#define FOPEN(fn, path, mode) \
92    do \
93    { \
94        if(!_zzuf_ready) \
95            LOADSYM(fn); \
96        ret = ORIG(fn)(path, mode); \
97        if(!_zzuf_ready) \
98            return ret; \
99        if(ret) \
100        { \
101            if(_zzuf_include && \
102                regexec(_zzuf_include, path, 0, NULL, 0) == REG_NOMATCH) \
103                /* not included: ignore */ ; \
104            else if(_zzuf_exclude && \
105                    regexec(_zzuf_exclude, path, 0, NULL, 0) != REG_NOMATCH) \
106                /* excluded: ignore */ ; \
107            else \
108            { \
109                int fd = fileno(ret); \
110                files[fd].managed = 1; \
111                files[fd].pos = 0; \
112                debug(STR(fn) "(\"%s\", \"%s\") = %p", path, mode, ret); \
113            } \
114        } \
115    } while(0)
116
117FILE *fopen(const char *path, const char *mode)
118{
119    FILE *ret; FOPEN(fopen, path, mode); return ret;
120}
121
122FILE *fopen64(const char *path, const char *mode)
123{
124    FILE *ret; FOPEN(fopen64, path, mode); return ret;
125}
126
127int fseek(FILE *stream, long offset, int whence)
128{
129    int ret, fd;
130
131    if(!_zzuf_ready)
132        LOADSYM(fseek);
133    ret = fseek_orig(stream, offset, whence);
134    if(!_zzuf_ready)
135        return ret;
136
137    fd = fileno(stream);
138    if(!files[fd].managed)
139        return ret;
140
141    debug("fseek(%p, %li, %i) = %i", stream, offset, whence, ret);
142    if(ret == 0)
143    {
144        switch(whence)
145        {
146            case SEEK_SET: files[fd].pos = offset; break;
147            case SEEK_CUR: files[fd].pos += offset; break;
148            case SEEK_END: files[fd].pos = ftell(stream); break;
149        }
150    }
151    return ret;
152}
153
154size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
155{
156    size_t ret;
157    int fd;
158
159    if(!_zzuf_ready)
160        LOADSYM(fread);
161    ret = fread_orig(ptr, size, nmemb, stream);
162    if(!_zzuf_ready)
163        return ret;
164
165    fd = fileno(stream);
166    if(!files[fd].managed)
167        return ret;
168
169    debug("fread(%p, %li, %li, %p) = %li",
170          ptr, (long int)size, (long int)nmemb, stream, (long int)ret);
171    if(ret > 0)
172    {
173        zzuf_fuzz(fd, ptr, ret * size);
174        files[fd].pos += ret * size;
175    }
176    return ret;
177}
178
179int fclose(FILE *fp)
180{
181    int ret, fd;
182
183    if(!_zzuf_ready)
184        LOADSYM(fclose);
185    fd = fileno(fp);
186    ret = fclose_orig(fp);
187    if(!_zzuf_ready)
188        return ret;
189
190    if(!files[fd].managed)
191        return ret;
192
193    debug("fclose(%p) = %i", fp, ret);
194    files[fd].managed = 0;
195
196    return ret;
197}
198
199#define OPEN(fn, file, oflag) \
200    do \
201    { \
202        int mode = 0; \
203        if(!_zzuf_ready) \
204            LOADSYM(fn); \
205        if(oflag & O_CREAT) \
206        { \
207            va_list va; \
208            va_start(va, oflag); \
209            mode = va_arg(va, int); \
210            va_end(va); \
211            ret = ORIG(fn)(file, oflag, mode); \
212        } \
213        else \
214        { \
215            ret = ORIG(fn)(file, oflag); \
216        } \
217        if(!_zzuf_ready) \
218            return ret; \
219        if(ret >= 0 \
220            && ((oflag & (O_RDONLY | O_RDWR | O_WRONLY)) != O_WRONLY)) \
221        { \
222            if(_zzuf_include && \
223                regexec(_zzuf_include, file, 0, NULL, 0) == REG_NOMATCH) \
224                /* not included: ignore */ ; \
225            else if(_zzuf_exclude && \
226                    regexec(_zzuf_exclude, file, 0, NULL, 0) != REG_NOMATCH) \
227                /* excluded: ignore */ ; \
228            else \
229            { \
230                if(oflag & O_CREAT) \
231                    debug(STR(fn) "(\"%s\", %i, %i) = %i", \
232                          file, oflag, mode, ret); \
233                else \
234                    debug(STR(fn) "(\"%s\", %i) = %i", file, oflag, ret); \
235                files[ret].managed = 1; \
236                files[ret].pos = 0; \
237            } \
238        } \
239    } while(0)
240
241int open(const char *file, int oflag, ...)
242{
243    int ret; OPEN(open, file, oflag); return ret;
244}
245
246int open64(const char *file, int oflag, ...)
247{
248    int ret; OPEN(open64, file, oflag); return ret;
249}
250
251ssize_t read(int fd, void *buf, size_t count)
252{
253    int ret;
254
255    if(!_zzuf_ready)
256        LOADSYM(read);
257    ret = read_orig(fd, buf, count);
258    if(!_zzuf_ready)
259        return ret;
260
261    if(!files[fd].managed)
262        return ret;
263
264    debug("read(%i, %p, %li) = %i", fd, buf, (long int)count, ret);
265    if(ret > 0)
266    {
267        zzuf_fuzz(fd, buf, ret);
268        files[fd].pos += ret;
269    }
270    return ret;
271}
272
273off64_t lseek64(int fd, off64_t offset, int whence)
274{
275    int ret;
276
277    if(!_zzuf_ready)
278        LOADSYM(lseek64);
279    ret = lseek64_orig(fd, offset, whence);
280    if(!_zzuf_ready)
281        return ret;
282
283    if(!files[fd].managed)
284        return ret;
285
286    debug("lseek64(%i, %lli, %i) = %i", fd, (long long int)offset, whence, ret);
287    if(ret != (off64_t)-1)
288        files[fd].pos = (int64_t)ret;
289
290    return ret;
291}
292
293int close(int fd)
294{
295    int ret;
296
297    if(!_zzuf_ready)
298        LOADSYM(close);
299    ret = close_orig(fd);
300    if(!_zzuf_ready)
301        return ret;
302
303    if(!files[fd].managed)
304        return ret;
305
306    debug("close(%i) = %i", fd, ret);
307    files[fd].managed = 0;
308
309    return ret;
310}
311
Note: See TracBrowser for help on using the repository browser.