source: zzuf/trunk/src/lib-stream.c @ 2542

Last change on this file since 2542 was 2542, checked in by Sam Hocevar, 12 years ago
  • Fix a few HP-UX warnings caused by missing headers.
  • Property svn:keywords set to Id
File size: 20.2 KB
Line 
1/*
2 *  zzuf - general purpose fuzzer
3 *  Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: lib-stream.c 2542 2008-07-16 17:23:29Z 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 *  load-stream.c: loaded stream functions
17 */
18
19#include "config.h"
20
21/* Needed for getline() and getdelim() */
22#define _GNU_SOURCE
23
24#if defined HAVE___SREFILL || defined HAVE___FILBUF
25#   define HAVE_REFILL_STDIO
26#endif
27
28#if defined HAVE_STDINT_H
29#   include <stdint.h>
30#elif defined HAVE_INTTYPES_H
31#   include <inttypes.h>
32#endif
33#include <stdlib.h>
34
35#include <stdio.h>
36#include <sys/types.h>
37#if defined HAVE_REFILL_STDIO && defined HAVE_UNISTD_H
38#   include <unistd.h> /* Needed for __srefill’s lseek() call */
39#endif
40
41#include "libzzuf.h"
42#include "lib-load.h"
43#include "debug.h"
44#include "fuzz.h"
45#include "fd.h"
46
47#if defined HAVE___SREFILL
48int NEW(__srefill)(FILE *fp);
49#endif
50
51#if defined HAVE___FILBUF
52int NEW(__filbuf)(FILE *fp);
53#endif
54
55/* Library functions that we divert */
56static FILE *  (*ORIG(fopen))    (const char *path, const char *mode);
57#if defined HAVE_FOPEN64
58static FILE *  (*ORIG(fopen64))  (const char *path, const char *mode);
59#endif
60#if defined HAVE___FOPEN64
61static FILE *  (*ORIG(__fopen64))(const char *path, const char *mode);
62#endif
63static FILE *  (*ORIG(freopen))  (const char *path, const char *mode,
64                                  FILE *stream);
65#if defined HAVE___FREOPEN64
66static FILE *  (*ORIG(__freopen64)) (const char *path, const char *mode,
67                                     FILE *stream);
68#endif
69static int     (*ORIG(fseek))    (FILE *stream, long offset, int whence);
70#if defined HAVE_FSEEKO
71static int     (*ORIG(fseeko))   (FILE *stream, off_t offset, int whence);
72#endif
73#if defined HAVE___FSEEKO64
74static int     (*ORIG(__fseeko64)) (FILE *stream, off_t offset, int whence);
75#endif
76#if defined HAVE___FSETPOS64
77static int     (*ORIG(__fsetpos64)) (FILE *stream, const fpos64_t *pos);
78#endif
79static void    (*ORIG(rewind))   (FILE *stream);
80static size_t  (*ORIG(fread))    (void *ptr, size_t size, size_t nmemb,
81                                  FILE *stream);
82#if defined HAVE_FREAD_UNLOCKED
83static size_t  (*ORIG(fread_unlocked))  (void *ptr, size_t size, size_t nmemb,
84                                         FILE *stream);
85#endif
86static int     (*ORIG(getc))     (FILE *stream);
87static int     (*ORIG(getchar))  (void);
88static int     (*ORIG(fgetc))    (FILE *stream);
89#if defined HAVE__IO_GETC
90static int     (*ORIG(_IO_getc)) (FILE *stream);
91#endif
92#if defined HAVE_GETC_UNLOCKED
93static int     (*ORIG(getc_unlocked))    (FILE *stream);
94#endif
95#if defined HAVE_GETCHAR_UNLOCKED
96static int     (*ORIG(getchar_unlocked)) (void);
97#endif
98#if defined HAVE_FGETC_UNLOCKED
99static int     (*ORIG(fgetc_unlocked))   (FILE *stream);
100#endif
101static char *  (*ORIG(fgets))    (char *s, int size, FILE *stream);
102#if defined HAVE_FGETS_UNLOCKED
103static char *  (*ORIG(fgets_unlocked))   (char *s, int size, FILE *stream);
104#endif
105static int     (*ORIG(ungetc))   (int c, FILE *stream);
106static int     (*ORIG(fclose))   (FILE *fp);
107
108/* Additional GNUisms */
109#if defined HAVE_GETLINE
110static ssize_t (*ORIG(getline))    (char **lineptr, size_t *n, FILE *stream);
111#endif
112#if defined HAVE_GETDELIM
113static ssize_t (*ORIG(getdelim))   (char **lineptr, size_t *n, int delim,
114                                    FILE *stream);
115#endif
116#if defined HAVE___GETDELIM
117static ssize_t (*ORIG(__getdelim)) (char **lineptr, size_t *n, int delim,
118                                    FILE *stream);
119#endif
120
121/* Additional BSDisms */
122#if defined HAVE_FGETLN
123static char *  (*ORIG(fgetln))    (FILE *stream, size_t *len);
124#endif
125#if defined HAVE___SREFILL
126int            (*ORIG(__srefill)) (FILE *fp);
127#endif
128
129/* Additional HP-UXisms */
130#if defined HAVE___FILBUF
131int            (*ORIG(__filbuf))  (FILE *fp);
132#endif
133
134/* Our function wrappers */
135#if defined HAVE_REFILL_STDIO /* Fuzz fp if we have __srefill() */
136#   define FOPEN_FUZZ() \
137    _zz_fuzz(fd, ret->__ptr, ret->__cnt)
138#else
139#   define FOPEN_FUZZ()
140#endif
141
142#define FOPEN(fn) \
143    do \
144    { \
145        LOADSYM(fn); \
146        if(!_zz_ready) \
147            return ORIG(fn)(path, mode); \
148        _zz_lock(-1); \
149        ret = ORIG(fn)(path, mode); \
150        _zz_unlock(-1); \
151        if(ret && _zz_mustwatch(path)) \
152        { \
153            int fd = fileno(ret); \
154            _zz_register(fd); \
155            debug("%s(\"%s\", \"%s\") = [%i]", __func__, path, mode, fd); \
156            FOPEN_FUZZ(); \
157        } \
158    } while(0)
159
160FILE *NEW(fopen)(const char *path, const char *mode)
161{
162    FILE *ret; FOPEN(fopen); return ret;
163}
164
165#if defined HAVE_FOPEN64
166FILE *NEW(fopen64)(const char *path, const char *mode)
167{
168    FILE *ret; FOPEN(fopen64); return ret;
169}
170#endif
171
172#if defined HAVE___FOPEN64
173FILE *NEW(__fopen64)(const char *path, const char *mode)
174{
175    FILE *ret; FOPEN(__fopen64); return ret;
176}
177#endif
178
179#define FREOPEN(fn) \
180    do \
181    { \
182        int fd0 = -1, fd1 = -1, disp = 0; \
183        LOADSYM(fn); \
184        if(_zz_ready && (fd0 = fileno(stream)) >= 0 && _zz_iswatched(fd0)) \
185        { \
186            _zz_unregister(fd0); \
187            disp = 1; \
188        } \
189        _zz_lock(-1); \
190        ret = ORIG(fn)(path, mode, stream); \
191        _zz_unlock(-1); \
192        if(ret && _zz_mustwatch(path)) \
193        { \
194            fd1 = fileno(ret); \
195            _zz_register(fd1); \
196            disp = 1; \
197        } \
198        if(disp) \
199            debug("%s(\"%s\", \"%s\", [%i]) = [%i]", __func__, \
200                  path, mode, fd0, fd1); \
201    } while(0)
202
203FILE *NEW(freopen)(const char *path, const char *mode, FILE *stream)
204{
205    FILE *ret; FREOPEN(freopen); return ret;
206}
207
208#if defined HAVE___FREOPEN64
209FILE *NEW(__freopen64)(const char *path, const char *mode, FILE *stream)
210{
211    FILE *ret; FREOPEN(__freopen64); return ret;
212}
213#endif
214
215#if defined HAVE_REFILL_STDIO /* Don't fuzz or seek if we have __srefill() */
216#   define FSEEK_FUZZ(fn2)
217#else
218#   define FSEEK_FUZZ(fn2) \
219        if(ret == 0) \
220        { \
221            /* FIXME: check what happens when fseek()ing a pipe */ \
222            switch(whence) \
223            { \
224                case SEEK_END: \
225                    offset = fn2(stream); \
226                    /* fall through */ \
227                case SEEK_SET: \
228                    _zz_setpos(fd, offset); \
229                    break; \
230                case SEEK_CUR: \
231                    _zz_addpos(fd, offset); \
232                    break; \
233            } \
234        }
235#endif
236
237#define FSEEK(fn, fn2) \
238    do \
239    { \
240        int fd; \
241        LOADSYM(fn); \
242        fd = fileno(stream); \
243        if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
244            return ORIG(fn)(stream, offset, whence); \
245        _zz_lock(fd); \
246        ret = ORIG(fn)(stream, offset, whence); \
247        _zz_unlock(fd); \
248        debug("%s([%i], %lli, %i) = %i", __func__, \
249              fd, (long long int)offset, whence, ret); \
250        FSEEK_FUZZ(fn2) \
251    } while(0)
252
253int NEW(fseek)(FILE *stream, long offset, int whence)
254{
255    int ret; FSEEK(fseek, ftell); return ret;
256}
257
258#if defined HAVE_FSEEKO
259int NEW(fseeko)(FILE *stream, off_t offset, int whence)
260{
261    int ret; FSEEK(fseeko, ftello); return ret;
262}
263#endif
264
265#if defined HAVE___FSEEKO64
266int NEW(__fseeko64)(FILE *stream, off64_t offset, int whence)
267{
268    int ret; FSEEK(__fseeko64, ftello); return ret;
269}
270#endif
271
272#if defined HAVE___FSETPOS64
273int NEW(__fsetpos64)(FILE *stream, const fpos64_t *pos)
274{
275    int ret, fd;
276
277    LOADSYM(__fsetpos64);
278    fd = fileno(stream);
279    if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
280        return ORIG(__fsetpos64)(stream, pos);
281    _zz_lock(fd);
282    ret = ORIG(__fsetpos64)(stream, pos);
283    _zz_unlock(fd);
284    debug("%s([%i], %lli) = %i", __func__,
285          fd, (long long int)*pos, ret);
286    /* On HP-UX at least, fpos64_t == int64_t */
287    _zz_setpos(fd, (int64_t)*pos);
288
289    return ret;
290}
291#endif
292
293void NEW(rewind)(FILE *stream)
294{
295    int fd;
296
297    LOADSYM(rewind);
298    fd = fileno(stream);
299    if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
300    {
301        ORIG(rewind)(stream);
302        return;
303    }
304
305    _zz_lock(fd);
306    ORIG(rewind)(stream);
307    _zz_unlock(fd);
308    debug("%s([%i])", __func__, fd);
309
310#if defined HAVE_REFILL_STDIO /* Don't fuzz or seek if we have __srefill() */
311#else
312    /* FIXME: check what happens when rewind()ing a pipe */
313    _zz_setpos(fd, 0);
314#endif
315}
316
317#if defined HAVE_REFILL_STDIO /* Don't fuzz or seek if we have __srefill() */
318#   define FREAD_FUZZ() \
319    do \
320    { \
321        debug("%s(%p, %li, %li, [%i]) = %li", __func__, ptr, \
322              (long int)size, (long int)nmemb, fd, (long int)ret); \
323    } while(0)
324#else
325#   define FREAD_FUZZ() \
326    do \
327    { \
328        int64_t newpos = ftell(stream); \
329        /* XXX: the number of bytes read is not ret * size, because \
330         * a partial read may have advanced the stream pointer. However, \
331         * when reading from a pipe ftell() will return 0, and ret * size \
332         * is then better than nothing. */ \
333        if(newpos <= 0) \
334        { \
335            pos = _zz_getpos(fd); \
336            newpos = pos + ret * size; \
337        } \
338        if(newpos != pos) \
339        { \
340            char *b = ptr; \
341            _zz_fuzz(fd, ptr, newpos - pos); \
342            _zz_setpos(fd, newpos); \
343            if(newpos >= pos + 4) \
344                debug("%s(%p, %li, %li, [%i]) = %li \"%c%c%c%c...", __func__, \
345                      ptr, (long int)size, (long int)nmemb, fd, \
346                      (long int)ret, b[0], b[1], b[2], b[3]); \
347            else \
348                debug("%s(%p, %li, %li, [%i]) = %li \"%c...", __func__, ptr, \
349                      (long int)size, (long int)nmemb, fd, \
350                      (long int)ret, b[0]); \
351        } \
352        else \
353            debug("%s(%p, %li, %li, [%i]) = %li", __func__, ptr, \
354                  (long int)size, (long int)nmemb, fd, (long int)ret); \
355    } while(0)
356#endif
357
358#define FREAD(fn) \
359    do \
360    { \
361        int64_t pos; \
362        int fd; \
363        LOADSYM(fn); \
364        fd = fileno(stream); \
365        if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
366            return ORIG(fn)(ptr, size, nmemb, stream); \
367        pos = ftell(stream); \
368        _zz_lock(fd); \
369        ret = ORIG(fn)(ptr, size, nmemb, stream); \
370        _zz_unlock(fd); \
371        FREAD_FUZZ(); \
372    } while(0)
373
374size_t NEW(fread)(void *ptr, size_t size, size_t nmemb, FILE *stream)
375{
376    size_t ret; FREAD(fread); return ret;
377}
378
379#if defined HAVE_FREAD_UNLOCKED
380#undef fread_unlocked /* can be a macro; we don’t want that */
381size_t NEW(fread_unlocked)(void *ptr, size_t size, size_t nmemb, FILE *stream)
382{
383    size_t ret; FREAD(fread_unlocked); return ret;
384}
385#endif
386
387#if defined HAVE_REFILL_STDIO /* Don't fuzz or seek if we have __srefill() */
388#   define FGETC_FUZZ
389#else
390#   define FGETC_FUZZ \
391        if(ret != EOF) \
392        { \
393            uint8_t ch = ret; \
394            _zz_fuzz(fd, &ch, 1); \
395            _zz_addpos(fd, 1); \
396            ret = ch; \
397        }
398#endif
399
400#define FGETC(fn, s, arg) \
401    do { \
402        int fd; \
403        LOADSYM(fn); \
404        fd = fileno(s); \
405        if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
406            return ORIG(fn)(arg); \
407        _zz_lock(fd); \
408        ret = ORIG(fn)(arg); \
409        _zz_unlock(fd); \
410        FGETC_FUZZ \
411        if(ret == EOF) \
412            debug("%s([%i]) = EOF", __func__, fd); \
413        else \
414            debug("%s([%i]) = '%c'", __func__, fd, ret); \
415    } while(0)
416
417#undef getc /* can be a macro; we don’t want that */
418int NEW(getc)(FILE *stream)
419{
420    int ret; FGETC(getc, stream, stream); return ret;
421}
422
423#undef getchar /* can be a macro; we don’t want that */
424int NEW(getchar)(void)
425{
426    int ret; FGETC(getchar, stdin, /* empty */); return ret;
427}
428
429int NEW(fgetc)(FILE *stream)
430{
431    int ret; FGETC(fgetc, stream, stream); return ret;
432}
433
434#if defined HAVE__IO_GETC
435int NEW(_IO_getc)(FILE *stream)
436{
437    int ret; FGETC(_IO_getc, stream, stream); return ret;
438}
439#endif
440
441#if defined HAVE_GETC_UNLOCKED
442#undef getc_unlocked /* can be a macro; we don’t want that */
443int NEW(getc_unlocked)(FILE *stream)
444{
445    int ret; FGETC(getc_unlocked, stream, stream); return ret;
446}
447#endif
448
449#if defined HAVE_GETCHAR_UNLOCKED
450#undef getchar_unlocked /* can be a macro; we don’t want that */
451int NEW(getchar_unlocked)(void)
452{
453    int ret; FGETC(getchar_unlocked, stdin, /* empty */); return ret;
454}
455#endif
456
457#if defined HAVE_FGETC_UNLOCKED
458#undef fgetc_unlocked /* can be a macro; we don’t want that */
459int NEW(fgetc_unlocked)(FILE *stream)
460{
461    int ret; FGETC(fgetc_unlocked, stream, stream); return ret;
462}
463#endif
464
465#if defined HAVE_REFILL_STDIO /* Don't fuzz or seek if we have __srefill() */
466#   define FGETS_FUZZ(fn, fn2) \
467        _zz_lock(fd); \
468        ret = ORIG(fn)(s, size, stream); \
469        _zz_unlock(fd);
470#else
471#   define FGETS_FUZZ(fn, fn2) \
472        if(size <= 0) \
473            ret = NULL; \
474        else if(size == 1) \
475            s[0] = '\0'; \
476        else \
477        { \
478            int i; \
479            for(i = 0; i < size - 1; i++) \
480            { \
481                int ch; \
482                _zz_lock(fd); \
483                ch = ORIG(fn2)(stream); \
484                _zz_unlock(fd); \
485                if(ch == EOF) \
486                { \
487                    s[i] = '\0'; \
488                    if(!i) \
489                        ret = NULL; \
490                    break; \
491                } \
492                s[i] = (char)(unsigned char)ch; \
493                _zz_fuzz(fd, (uint8_t *)s + i, 1); /* rather inefficient */ \
494                _zz_addpos(fd, 1); \
495                if(s[i] == '\n') \
496                { \
497                    s[i + 1] = '\0'; \
498                    break; \
499                } \
500            } \
501        }
502#endif
503
504#define FGETS(fn, fn2) \
505    do \
506    { \
507        int fd; \
508        ret = s; \
509        LOADSYM(fn); \
510        LOADSYM(fn2); \
511        fd = fileno(stream); \
512        if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
513            return ORIG(fn)(s, size, stream); \
514        FGETS_FUZZ(fn, fn2) \
515        debug("%s(%p, %i, [%i]) = %p", __func__, s, size, fd, ret); \
516    } while(0)
517
518char *NEW(fgets)(char *s, int size, FILE *stream)
519{
520    char *ret; FGETS(fgets, fgetc); return ret;
521}
522
523#if defined HAVE_FGETS_UNLOCKED
524char *NEW(fgets_unlocked)(char *s, int size, FILE *stream)
525{
526    char *ret; FGETS(fgets_unlocked, fgetc_unlocked); return ret;
527}
528#endif
529
530int NEW(ungetc)(int c, FILE *stream)
531{
532    int ret, fd;
533
534    LOADSYM(ungetc);
535    fd = fileno(stream);
536    if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
537        return ORIG(ungetc)(c, stream);
538
539    _zz_lock(fd);
540    ret = ORIG(ungetc)(c, stream);
541    _zz_unlock(fd);
542
543    if(ret != EOF)
544    {
545        struct fuzz *fuzz = _zz_getfuzz(fd);
546        fuzz->uflag = 1;
547        fuzz->upos = _zz_getpos(fd) - 1;
548        fuzz->uchar = c;
549#if defined HAVE_REFILL_STDIO /* Don't fuzz or seek if we have __srefill() */
550#else
551        _zz_addpos(fd, -1);
552#endif
553    }
554
555    if(ret == EOF)
556        debug("%s(0x%02x, [%i]) = EOF", __func__, c, fd);
557    else
558        debug("%s(0x%02x, [%i]) = '%c'", __func__, c, fd, ret);
559
560    return ret;
561}
562
563int NEW(fclose)(FILE *fp)
564{
565    int ret, fd;
566
567    LOADSYM(fclose);
568    fd = fileno(fp);
569    if(!_zz_ready || !_zz_iswatched(fd))
570        return ORIG(fclose)(fp);
571
572    _zz_lock(fd);
573    ret = ORIG(fclose)(fp);
574    _zz_unlock(fd);
575    debug("%s([%i]) = %i", __func__, fd, ret);
576    _zz_unregister(fd);
577
578    return ret;
579}
580
581#define GETDELIM(fn, delim, need_delim) \
582    do { \
583        char *line; \
584        ssize_t done, size; \
585        int fd, finished = 0; \
586        LOADSYM(fn); \
587        LOADSYM(getdelim); \
588        LOADSYM(fgetc); \
589        fd = fileno(stream); \
590        if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
591            return ORIG(getdelim)(lineptr, n, delim, stream); \
592        line = *lineptr; \
593        size = line ? *n : 0; \
594        ret = done = finished = 0; \
595        for(;;) \
596        { \
597            int ch; \
598            if(done >= size) /* highly inefficient but I don't care */ \
599                line = realloc(line, size = done + 1); \
600            if(finished) \
601            { \
602                line[done] = '\0'; \
603                *n = size; \
604                *lineptr = line; \
605                break; \
606            } \
607            _zz_lock(fd); \
608            ch = ORIG(fgetc)(stream); \
609            _zz_unlock(fd); \
610            if(ch == EOF) \
611            { \
612                finished = 1; \
613                ret = done; \
614            } \
615            else \
616            { \
617                unsigned char c = ch; \
618                _zz_fuzz(fd, &c, 1); /* even more inefficient */ \
619                line[done++] = c; \
620                _zz_addpos(fd, 1); \
621                if(c == delim) \
622                { \
623                    finished = 1; \
624                    ret = done; \
625                } \
626            } \
627        } \
628        if(need_delim) \
629            debug("%s(%p, %p, '%c', [%i]) = %li", __func__, \
630                  lineptr, n, delim, fd, (long int)ret); \
631        else \
632            debug("%s(%p, %p, [%i]) = %li", __func__, \
633                  lineptr, n, fd, (long int)ret); \
634        return ret; \
635    } while(0)
636
637#if defined HAVE_GETLINE
638ssize_t NEW(getline)(char **lineptr, size_t *n, FILE *stream)
639{
640    ssize_t ret; GETDELIM(getline, '\n', 0); return ret;
641}
642#endif
643
644#if defined HAVE_GETDELIM
645ssize_t NEW(getdelim)(char **lineptr, size_t *n, int delim, FILE *stream)
646{
647    ssize_t ret; GETDELIM(getdelim, delim, 1); return ret;
648}
649#endif
650
651#if defined HAVE___GETDELIM
652ssize_t NEW(__getdelim)(char **lineptr, size_t *n, int delim, FILE *stream)
653{
654    ssize_t ret; GETDELIM(__getdelim, delim, 1); return ret;
655}
656#endif
657
658#if defined HAVE_FGETLN
659char *NEW(fgetln)(FILE *stream, size_t *len)
660{
661    char *ret;
662#if defined HAVE_REFILL_STDIO /* Don't fuzz or seek if we have __srefill() */
663#else
664    struct fuzz *fuzz;
665    size_t i, size;
666#endif
667    int fd;
668
669    LOADSYM(fgetln);
670    LOADSYM(fgetc);
671    fd = fileno(stream);
672    if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
673        return ORIG(fgetln)(stream, len);
674
675#if defined HAVE_REFILL_STDIO /* Don't fuzz or seek if we have __srefill() */
676    _zz_lock(fd);
677    ret = ORIG(fgetln)(stream, len);
678    _zz_unlock(fd);
679#else
680    fuzz = _zz_getfuzz(fd);
681
682    for(i = size = 0; ; /* i is incremented below */)
683    {
684        int ch;
685
686        _zz_lock(fd);
687        ch = ORIG(fgetc)(stream);
688        _zz_unlock(fd);
689
690        if(ch == EOF)
691            break;
692
693        if(i >= size)
694            fuzz->tmp = realloc(fuzz->tmp, (size += 80));
695
696        fuzz->tmp[i] = (char)(unsigned char)ch;
697        _zz_fuzz(fd, (uint8_t *)fuzz->tmp + i, 1); /* rather inefficient */
698        _zz_addpos(fd, 1);
699
700        if(fuzz->tmp[i++] == '\n')
701            break;
702    }
703
704    *len = i;
705    ret = fuzz->tmp;
706#endif
707
708    debug("%s([%i], &%li) = %p", __func__, fd, (long int)*len, ret);
709    return ret;
710}
711#endif
712
713#if defined HAVE___SREFILL
714int NEW(__srefill)(FILE *fp)
715{
716    off_t newpos;
717    int ret, fd;
718
719    LOADSYM(__srefill);
720    fd = fileno(fp);
721    if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
722        return ORIG(__srefill)(fp);
723
724    _zz_lock(fd);
725    ret = ORIG(__srefill)(fp);
726    newpos = lseek(fd, 0, SEEK_CUR);
727    _zz_unlock(fd);
728    if(ret != EOF)
729    {
730        /* FIXME: do we have to fuzz ret, too, like in __filbuf? */
731        if(newpos != -1)
732            _zz_setpos(fd, newpos - fp->_r);
733        _zz_fuzz(fd, fp->_p, fp->_r);
734        _zz_addpos(fd, fp->_r);
735    }
736
737    if(!_zz_islocked(fd))
738        debug("%s([%i]) = %i", __func__, fd, ret);
739
740    return ret;
741}
742#endif
743
744#if defined HAVE___FILBUF
745int NEW(__filbuf)(FILE *fp)
746{
747    off_t newpos;
748    int ret, fd;
749
750    LOADSYM(__filbuf);
751    fd = fileno(fp);
752    if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
753        return ORIG(__filbuf)(fp);
754
755    _zz_lock(fd);
756    ret = ORIG(__filbuf)(fp);
757    newpos = lseek(fd, 0, SEEK_CUR);
758    _zz_unlock(fd);
759    if(ret != EOF)
760    {
761        if(newpos != -1)
762            _zz_setpos(fd, newpos - fp->__cnt - 1);
763        _zz_fuzz(fd, fp->__ptr - 1, fp->__cnt + 1);
764        ret = (uint8_t)fp->__ptr[-1];
765        _zz_addpos(fd, fp->__cnt + 1);
766    }
767
768    if(!_zz_islocked(fd))
769        debug("%s([%i]) = %i", __func__, fd, ret);
770
771    return ret;
772}
773#endif
774
Note: See TracBrowser for help on using the repository browser.