More fread() behaviour improvements, with documentation.

This commit is contained in:
Sam Hocevar 2009-11-23 01:35:23 +00:00 committed by sam
parent 13585b793e
commit 128bcc1770
3 changed files with 168 additions and 112 deletions

View File

@ -146,22 +146,22 @@ static off64_t (*ORIG(__lseek64)) (int fd, off64_t offset, int whence);
#endif #endif
static int (*ORIG(close)) (int fd); static int (*ORIG(close)) (int fd);
#define OPEN(fn) \ #define OPEN(myopen) \
do \ do \
{ \ { \
int mode = 0; \ int mode = 0; \
LOADSYM(fn); \ LOADSYM(myopen); \
if(oflag & O_CREAT) \ if(oflag & O_CREAT) \
{ \ { \
va_list va; \ va_list va; \
va_start(va, oflag); \ va_start(va, oflag); \
mode = va_arg(va, int); \ mode = va_arg(va, int); \
va_end(va); \ va_end(va); \
ret = ORIG(fn)(file, oflag, mode); \ ret = ORIG(myopen)(file, oflag, mode); \
} \ } \
else \ else \
{ \ { \
ret = ORIG(fn)(file, oflag); \ ret = ORIG(myopen)(file, oflag); \
} \ } \
if(!_zz_ready || _zz_islocked(-1)) \ if(!_zz_ready || _zz_islocked(-1)) \
return ret; \ return ret; \
@ -275,11 +275,11 @@ int NEW(accept)(int sockfd, struct sockaddr *addr, SOCKLEN_T *addrlen)
# define case_AF_INET6 # define case_AF_INET6
#endif #endif
#define CONNECTION(fn, addr) \ #define CONNECTION(myconnect, addr) \
do \ do \
{ \ { \
LOADSYM(fn); \ LOADSYM(myconnect); \
ret = ORIG(fn)(sockfd, addr, addrlen); \ ret = ORIG(myconnect)(sockfd, addr, addrlen); \
if(!_zz_ready || _zz_islocked(-1) || !_zz_network) \ if(!_zz_ready || _zz_islocked(-1) || !_zz_network) \
return ret; \ return ret; \
if(ret >= 0) \ if(ret >= 0) \
@ -528,11 +528,11 @@ ssize_t NEW(pread)(int fd, void *buf, size_t count, off_t offset)
} }
#endif #endif
#define LSEEK(fn, off_t) \ #define LSEEK(mylseek, off_t) \
do \ do \
{ \ { \
LOADSYM(fn); \ LOADSYM(mylseek); \
ret = ORIG(fn)(fd, offset, whence); \ ret = ORIG(mylseek)(fd, offset, whence); \
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd) \ if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd) \
|| !_zz_isactive(fd)) \ || !_zz_isactive(fd)) \
return ret; \ return ret; \

View File

@ -248,17 +248,17 @@ int NEW(posix_memalign)(void **memptr, size_t alignment, size_t size)
void **maps = NULL; void **maps = NULL;
int nbmaps = 0; int nbmaps = 0;
#define MMAP(fn, off_t) \ #define MMAP(mymmap, off_t) \
do { \ do { \
char *b = MAP_FAILED; \ char *b = MAP_FAILED; \
LOADSYM(fn); \ LOADSYM(mymmap); \
if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd) \ if(!_zz_ready || !_zz_iswatched(fd) || _zz_islocked(fd) \
|| !_zz_isactive(fd)) \ || !_zz_isactive(fd)) \
return ORIG(fn)(start, length, prot, flags, fd, offset); \ return ORIG(mymmap)(start, length, prot, flags, fd, offset); \
ret = ORIG(fn)(NULL, length, prot, flags, fd, offset); \ ret = ORIG(mymmap)(NULL, length, prot, flags, fd, offset); \
if(ret != MAP_FAILED && length) \ if(ret != MAP_FAILED && length) \
{ \ { \
b = ORIG(fn)(start, length, PROT_READ | PROT_WRITE, \ b = ORIG(mymmap)(start, length, PROT_READ | PROT_WRITE, \
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \
if(b == MAP_FAILED) \ if(b == MAP_FAILED) \
{ \ { \

View File

@ -159,23 +159,34 @@ int (*ORIG(__filbuf)) (FILE *fp);
#endif #endif
/* Helper functions for refill-like functions */ /* Helper functions for refill-like functions */
#if defined HAVE___FILBUF || defined HAVE___SRGET || defined HAVE___UFLOW
static inline uint8_t *get_stream_ptr(FILE *stream) static inline uint8_t *get_stream_ptr(FILE *stream)
{ {
#if defined HAVE___FILBUF || defined HAVE___SRGET || defined HAVE___UFLOW
return (uint8_t *)stream->FILE_PTR; return (uint8_t *)stream->FILE_PTR;
#else
return NULL;
#endif
} }
static inline int get_stream_cnt(FILE *stream) static inline int get_stream_cnt(FILE *stream)
{ {
#if defined HAVE_GLIBC_FP #if defined HAVE_GLIBC_FP
return (int)((uint8_t *)stream->FILE_CNT - (uint8_t *)stream->FILE_PTR); return (int)((uint8_t *)stream->FILE_CNT - (uint8_t *)stream->FILE_PTR);
# else #elif defined HAVE___FILBUF || defined HAVE___SRGET || defined HAVE___UFLOW
return stream->FILE_CNT; return stream->FILE_CNT;
#else
return 0;
#endif #endif
} }
#endif
/* Our function wrappers */ #define DEBUG_STREAM(prefix, fp) \
debug2(prefix "stream([%i], %p, %i)", fileno(fp), \
get_stream_ptr(fp), get_stream_cnt(fp));
/*
* fopen, fopen64 etc.
*/
#if defined REFILL_ONLY_STDIO /* Fuzz fp if we have __srefill() */ #if defined REFILL_ONLY_STDIO /* Fuzz fp if we have __srefill() */
# define FOPEN_FUZZ() \ # define FOPEN_FUZZ() \
_zz_fuzz(fd, get_stream_ptr(ret), get_stream_cnt(ret)) _zz_fuzz(fd, get_stream_ptr(ret), get_stream_cnt(ret))
@ -183,29 +194,21 @@ static inline int get_stream_cnt(FILE *stream)
# define FOPEN_FUZZ() # define FOPEN_FUZZ()
#endif #endif
#define BEGIN_STREAM(fp) \ #define FOPEN(myfopen) \
debug2("oldstream([%i], %p, %i)", fileno(fp), \
get_stream_ptr(fp), get_stream_cnt(fp));
#define END_STREAM(fp) \
debug2("newstream([%i], %p, %i)", fileno(fp), \
get_stream_ptr(fp), get_stream_cnt(fp));
#define FOPEN(fn) \
do \ do \
{ \ { \
LOADSYM(fn); \ LOADSYM(myfopen); \
if(!_zz_ready) \ if(!_zz_ready) \
return ORIG(fn)(path, mode); \ return ORIG(myfopen)(path, mode); \
_zz_lock(-1); \ _zz_lock(-1); \
ret = ORIG(fn)(path, mode); \ ret = ORIG(myfopen)(path, mode); \
_zz_unlock(-1); \ _zz_unlock(-1); \
if(ret && _zz_mustwatch(path)) \ if(ret && _zz_mustwatch(path)) \
{ \ { \
int fd = fileno(ret); \ int fd = fileno(ret); \
_zz_register(fd); \ _zz_register(fd); \
debug("%s(\"%s\", \"%s\") = [%i]", __func__, path, mode, fd); \ debug("%s(\"%s\", \"%s\") = [%i]", __func__, path, mode, fd); \
END_STREAM(ret); \ DEBUG_STREAM("new", ret); \
FOPEN_FUZZ(); \ FOPEN_FUZZ(); \
} \ } \
} while(0) } while(0)
@ -229,18 +232,22 @@ FILE *NEW(__fopen64)(const char *path, const char *mode)
} }
#endif #endif
#define FREOPEN(fn) \ /*
* freopen, freopen64 etc.
*/
#define FREOPEN(myfreopen) \
do \ do \
{ \ { \
int fd0 = -1, fd1 = -1, disp = 0; \ int fd0 = -1, fd1 = -1, disp = 0; \
LOADSYM(fn); \ LOADSYM(myfreopen); \
if(_zz_ready && (fd0 = fileno(stream)) >= 0 && _zz_iswatched(fd0)) \ if(_zz_ready && (fd0 = fileno(stream)) >= 0 && _zz_iswatched(fd0)) \
{ \ { \
_zz_unregister(fd0); \ _zz_unregister(fd0); \
disp = 1; \ disp = 1; \
} \ } \
_zz_lock(-1); \ _zz_lock(-1); \
ret = ORIG(fn)(path, mode, stream); \ ret = ORIG(myfreopen)(path, mode, stream); \
_zz_unlock(-1); \ _zz_unlock(-1); \
if(ret && _zz_mustwatch(path)) \ if(ret && _zz_mustwatch(path)) \
{ \ { \
@ -272,17 +279,21 @@ FILE *NEW(__freopen64)(const char *path, const char *mode, FILE *stream)
} }
#endif #endif
/*
* fseek, fseeko etc.
*/
#if defined REFILL_ONLY_STDIO /* Don't fuzz or seek if we have __srefill() */ #if defined REFILL_ONLY_STDIO /* Don't fuzz or seek if we have __srefill() */
# define FSEEK_FUZZ(fn2) # define FSEEK_FUZZ(myftell)
#else #else
# define FSEEK_FUZZ(fn2) \ # define FSEEK_FUZZ(myftell) \
if(ret == 0) \ if(ret == 0) \
{ \ { \
/* FIXME: check what happens when fseek()ing a pipe */ \ /* FIXME: check what happens when fseek()ing a pipe */ \
switch(whence) \ switch(whence) \
{ \ { \
case SEEK_END: \ case SEEK_END: \
offset = fn2(stream); \ offset = myftell(stream); \
/* fall through */ \ /* fall through */ \
case SEEK_SET: \ case SEEK_SET: \
_zz_setpos(fd, offset); \ _zz_setpos(fd, offset); \
@ -294,22 +305,22 @@ FILE *NEW(__freopen64)(const char *path, const char *mode, FILE *stream)
} }
#endif #endif
#define FSEEK(fn, fn2) \ #define FSEEK(myfseek, myftell) \
do \ do \
{ \ { \
int fd; \ int fd; \
LOADSYM(fn); \ LOADSYM(myfseek); \
fd = fileno(stream); \ fd = fileno(stream); \
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \ if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
return ORIG(fn)(stream, offset, whence); \ return ORIG(myfseek)(stream, offset, whence); \
BEGIN_STREAM(stream); \ DEBUG_STREAM("old", stream); \
_zz_lock(fd); \ _zz_lock(fd); \
ret = ORIG(fn)(stream, offset, whence); \ ret = ORIG(myfseek)(stream, offset, whence); \
_zz_unlock(fd); \ _zz_unlock(fd); \
debug("%s([%i], %lli, %i) = %i", __func__, \ debug("%s([%i], %lli, %i) = %i", __func__, \
fd, (long long int)offset, whence, ret); \ fd, (long long int)offset, whence, ret); \
FSEEK_FUZZ(fn2) \ FSEEK_FUZZ(myftell) \
END_STREAM(stream); \ DEBUG_STREAM("new", stream); \
} while(0) } while(0)
int NEW(fseek)(FILE *stream, long offset, int whence) int NEW(fseek)(FILE *stream, long offset, int whence)
@ -338,22 +349,26 @@ int NEW(__fseeko64)(FILE *stream, off64_t offset, int whence)
} }
#endif #endif
#define FSETPOS(fn) \ /*
* fsetpos64, __fsetpos64
*/
#define FSETPOS(myfsetpos) \
do \ do \
{ \ { \
int fd; \ int fd; \
LOADSYM(fn); \ LOADSYM(myfsetpos); \
fd = fileno(stream); \ fd = fileno(stream); \
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \ if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
return ORIG(fn)(stream, pos); \ return ORIG(myfsetpos)(stream, pos); \
BEGIN_STREAM(stream); \ DEBUG_STREAM("old", stream); \
_zz_lock(fd); \ _zz_lock(fd); \
ret = ORIG(fn)(stream, pos); \ ret = ORIG(myfsetpos)(stream, pos); \
_zz_unlock(fd); \ _zz_unlock(fd); \
debug("%s([%i], %lli) = %i", __func__, \ debug("%s([%i], %lli) = %i", __func__, \
fd, (long long int)FPOS_CAST(*pos), ret); \ fd, (long long int)FPOS_CAST(*pos), ret); \
_zz_setpos(fd, (int64_t)FPOS_CAST(*pos)); \ _zz_setpos(fd, (int64_t)FPOS_CAST(*pos)); \
END_STREAM(stream); \ DEBUG_STREAM("new", stream); \
} \ } \
while(0) while(0)
@ -371,6 +386,10 @@ int NEW(__fsetpos64)(FILE *stream, const fpos64_t *pos)
} }
#endif #endif
/*
* rewind
*/
void NEW(rewind)(FILE *stream) void NEW(rewind)(FILE *stream)
{ {
int fd; int fd;
@ -395,21 +414,25 @@ void NEW(rewind)(FILE *stream)
#endif #endif
} }
/*
* fread, fread_unlocked
*/
/* Compute how many bytes from the stream were already fuzzed by __filbuf, /* Compute how many bytes from the stream were already fuzzed by __filbuf,
* __srget or __uflow, and store it in already_fuzzed. If these functions * __srget or __uflow, and store it in already_fuzzed. If these functions
* are not available, do nothing. */ * are not available, do nothing. */
#if defined HAVE___FILBUF || defined HAVE___SRGET || defined HAVE___UFLOW #if defined HAVE___FILBUF || defined HAVE___SRGET || defined HAVE___UFLOW
# define FREAD_PREFUZZ(fd, pos) \ # define FREAD_PREFUZZ(fd, oldpos) \
do \ do \
{ \ { \
int64_t tmp = _zz_getpos(fd); \ int64_t tmp = _zz_getpos(fd); \
_zz_setpos(fd, pos); \ _zz_setpos(fd, oldpos); \
already_fuzzed = _zz_getfuzzed(fd); \ already_fuzzed = _zz_getfuzzed(fd); \
_zz_setpos(fd, tmp); \ _zz_setpos(fd, tmp); \
} \ } \
while(0) while(0)
#else #else
# define FREAD_PREFUZZ(fd, pos) do {} while(0) # define FREAD_PREFUZZ(fd, oldpos) do {} while(0)
#endif #endif
/* Fuzz the data returned by fread(). If a __fillbuf mechanism already /* Fuzz the data returned by fread(). If a __fillbuf mechanism already
@ -417,14 +440,14 @@ void NEW(rewind)(FILE *stream)
* have __srefill, we just do nothing because that function is the only * have __srefill, we just do nothing because that function is the only
* one that actually fuzzes things. */ * one that actually fuzzes things. */
#if defined REFILL_ONLY_STDIO #if defined REFILL_ONLY_STDIO
# define FREAD_FUZZ(fd, pos) \ # define FREAD_FUZZ(fd, oldpos) \
do \ do \
{ \ { \
debug("%s(%p, %li, %li, [%i]) = %li", __func__, ptr, \ debug("%s(%p, %li, %li, [%i]) = %li", __func__, ptr, \
(long int)size, (long int)nmemb, fd, (long int)ret); \ (long int)size, (long int)nmemb, fd, (long int)ret); \
} while(0) } while(0)
#else #else
# define FREAD_FUZZ(fd, pos) \ # define FREAD_FUZZ(fd, oldpos) \
do \ do \
{ \ { \
int64_t newpos = ftell(stream); \ int64_t newpos = ftell(stream); \
@ -434,23 +457,28 @@ void NEW(rewind)(FILE *stream)
* is then better than nothing. */ \ * is then better than nothing. */ \
if(newpos <= 0) \ if(newpos <= 0) \
{ \ { \
pos = _zz_getpos(fd); \ oldpos = _zz_getpos(fd); \
newpos = pos + ret * size; \ newpos = oldpos + ret * size; \
} \ } \
if(newpos != pos) \ if(newpos != oldpos) \
{ \ { \
char *b = ptr; \ char *b = ptr; \
/* Skip bytes that were already fuzzed by __filbuf or __srget */ \ /* Skip bytes that were already fuzzed by __filbuf or __srget */ \
if(newpos > pos + already_fuzzed) \ if(newpos > oldpos + already_fuzzed) \
{ \ { \
_zz_setpos(fd, pos + already_fuzzed); \ _zz_setpos(fd, oldpos + already_fuzzed); \
_zz_fuzz(fd, ptr, newpos - pos - already_fuzzed); \ _zz_fuzz(fd, ptr, newpos - oldpos - already_fuzzed); \
} \
/* FIXME: we need to fuzz the extra bytes that may have been \ /* FIXME: we need to fuzz the extra bytes that may have been \
* read by the fread call we just made, or subsequent calls \ * read by the fread call we just made, or subsequent calls \
* to getc_unlocked may miss them. */ \ * to getc_unlocked may miss them. */ \
_zz_setpos(fd, newpos); \ _zz_setpos(fd, newpos); \
if(newpos >= pos + 4) \ _zz_fuzz(fd, get_stream_ptr(stream), get_stream_cnt(stream)); \
_zz_setfuzzed(fd, get_stream_cnt(stream)); \
/* FIXME: *AND* we need to fuzz the buffer before the current \
* position, in case fseek() causes us to rewind. */ \
} \
_zz_setpos(fd, newpos); \
if(newpos >= oldpos + 4) \
debug("%s(%p, %li, %li, [%i]) = %li \"%c%c%c%c...", __func__, \ debug("%s(%p, %li, %li, [%i]) = %li \"%c%c%c%c...", __func__, \
ptr, (long int)size, (long int)nmemb, fd, \ ptr, (long int)size, (long int)nmemb, fd, \
(long int)ret, b[0], b[1], b[2], b[3]); \ (long int)ret, b[0], b[1], b[2], b[3]); \
@ -465,23 +493,23 @@ void NEW(rewind)(FILE *stream)
} while(0) } while(0)
#endif #endif
#define FREAD(fn) \ #define FREAD(myfread) \
do \ do \
{ \ { \
int64_t pos; \ int64_t oldpos; \
int fd, already_fuzzed = 0; \ int fd, already_fuzzed = 0; \
LOADSYM(fn); \ LOADSYM(myfread); \
fd = fileno(stream); \ fd = fileno(stream); \
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \ if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
return ORIG(fn)(ptr, size, nmemb, stream); \ return ORIG(myfread)(ptr, size, nmemb, stream); \
BEGIN_STREAM(stream); \ DEBUG_STREAM("old", stream); \
pos = ftell(stream); \ oldpos = ftell(stream); \
_zz_lock(fd); \ _zz_lock(fd); \
ret = ORIG(fn)(ptr, size, nmemb, stream); \ ret = ORIG(myfread)(ptr, size, nmemb, stream); \
_zz_unlock(fd); \ _zz_unlock(fd); \
FREAD_PREFUZZ(fd, pos); \ FREAD_PREFUZZ(fd, oldpos); \
FREAD_FUZZ(fd, pos); \ FREAD_FUZZ(fd, oldpos); \
END_STREAM(stream); \ DEBUG_STREAM("new", stream); \
} while(0) } while(0)
size_t NEW(fread)(void *ptr, size_t size, size_t nmemb, FILE *stream) size_t NEW(fread)(void *ptr, size_t size, size_t nmemb, FILE *stream)
@ -497,6 +525,10 @@ size_t NEW(fread_unlocked)(void *ptr, size_t size, size_t nmemb, FILE *stream)
} }
#endif #endif
/*
* getc, getchar, fgetc etc.
*/
#if defined HAVE___FILBUF || defined HAVE___SRGET || defined HAVE___UFLOW #if defined HAVE___FILBUF || defined HAVE___SRGET || defined HAVE___UFLOW
# define FGETC_PREFUZZ already_fuzzed = _zz_getfuzzed(fd); # define FGETC_PREFUZZ already_fuzzed = _zz_getfuzzed(fd);
#else #else
@ -517,16 +549,16 @@ size_t NEW(fread_unlocked)(void *ptr, size_t size, size_t nmemb, FILE *stream)
} }
#endif #endif
#define FGETC(fn, s, arg) \ #define FGETC(myfgetc, s, arg) \
do { \ do { \
int fd, already_fuzzed = 0; \ int fd, already_fuzzed = 0; \
LOADSYM(fn); \ LOADSYM(myfgetc); \
fd = fileno(s); \ fd = fileno(s); \
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \ if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
return ORIG(fn)(arg); \ return ORIG(myfgetc)(arg); \
BEGIN_STREAM(s); \ DEBUG_STREAM("old", s); \
_zz_lock(fd); \ _zz_lock(fd); \
ret = ORIG(fn)(arg); \ ret = ORIG(myfgetc)(arg); \
_zz_unlock(fd); \ _zz_unlock(fd); \
FGETC_PREFUZZ \ FGETC_PREFUZZ \
FGETC_FUZZ \ FGETC_FUZZ \
@ -534,7 +566,7 @@ size_t NEW(fread_unlocked)(void *ptr, size_t size, size_t nmemb, FILE *stream)
debug("%s([%i]) = EOF", __func__, fd); \ debug("%s([%i]) = EOF", __func__, fd); \
else \ else \
debug("%s([%i]) = '%c'", __func__, fd, ret); \ debug("%s([%i]) = '%c'", __func__, fd, ret); \
END_STREAM(s); \ DEBUG_STREAM("new", s); \
} while(0) } while(0)
#undef getc /* can be a macro; we dont want that */ #undef getc /* can be a macro; we dont want that */
@ -585,13 +617,17 @@ int NEW(fgetc_unlocked)(FILE *stream)
} }
#endif #endif
/*
* fgets, fgets_unlocked
*/
#if defined REFILL_ONLY_STDIO /* Don't fuzz or seek if we have __srefill() */ #if defined REFILL_ONLY_STDIO /* Don't fuzz or seek if we have __srefill() */
# define FGETS_FUZZ(fn, fn2) \ # define FGETS_FUZZ(myfgets, myfgetc) \
_zz_lock(fd); \ _zz_lock(fd); \
ret = ORIG(fn)(s, size, stream); \ ret = ORIG(myfgets)(s, size, stream); \
_zz_unlock(fd); _zz_unlock(fd);
#else #else
# define FGETS_FUZZ(fn, fn2) \ # define FGETS_FUZZ(myfgets, myfgetc) \
if(size <= 0) \ if(size <= 0) \
ret = NULL; \ ret = NULL; \
else if(size == 1) \ else if(size == 1) \
@ -603,7 +639,7 @@ int NEW(fgetc_unlocked)(FILE *stream)
{ \ { \
int ch; \ int ch; \
_zz_lock(fd); \ _zz_lock(fd); \
ch = ORIG(fn2)(stream); \ ch = ORIG(myfgetc)(stream); \
_zz_unlock(fd); \ _zz_unlock(fd); \
if(ch == EOF) \ if(ch == EOF) \
{ \ { \
@ -624,20 +660,20 @@ int NEW(fgetc_unlocked)(FILE *stream)
} }
#endif #endif
#define FGETS(fn, fn2) \ #define FGETS(myfgets, myfgetc) \
do \ do \
{ \ { \
int fd; \ int fd; \
ret = s; \ ret = s; \
LOADSYM(fn); \ LOADSYM(myfgets); \
LOADSYM(fn2); \ LOADSYM(myfgetc); \
fd = fileno(stream); \ fd = fileno(stream); \
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \ if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
return ORIG(fn)(s, size, stream); \ return ORIG(myfgets)(s, size, stream); \
BEGIN_STREAM(s); \ DEBUG_STREAM("old", s); \
FGETS_FUZZ(fn, fn2) \ FGETS_FUZZ(myfgets, myfgetc) \
debug("%s(%p, %i, [%i]) = %p", __func__, s, size, fd, ret); \ debug("%s(%p, %i, [%i]) = %p", __func__, s, size, fd, ret); \
END_STREAM(s); \ DEBUG_STREAM("new", s); \
} while(0) } while(0)
char *NEW(fgets)(char *s, int size, FILE *stream) char *NEW(fgets)(char *s, int size, FILE *stream)
@ -652,6 +688,10 @@ char *NEW(fgets_unlocked)(char *s, int size, FILE *stream)
} }
#endif #endif
/*
* ungetc
*/
int NEW(ungetc)(int c, FILE *stream) int NEW(ungetc)(int c, FILE *stream)
{ {
int ret, fd; int ret, fd;
@ -661,7 +701,7 @@ int NEW(ungetc)(int c, FILE *stream)
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
return ORIG(ungetc)(c, stream); return ORIG(ungetc)(c, stream);
BEGIN_STREAM(stream); DEBUG_STREAM("old", stream);
_zz_lock(fd); _zz_lock(fd);
ret = ORIG(ungetc)(c, stream); ret = ORIG(ungetc)(c, stream);
_zz_unlock(fd); _zz_unlock(fd);
@ -682,10 +722,14 @@ int NEW(ungetc)(int c, FILE *stream)
debug("%s(0x%02x, [%i]) = EOF", __func__, c, fd); debug("%s(0x%02x, [%i]) = EOF", __func__, c, fd);
else else
debug("%s(0x%02x, [%i]) = '%c'", __func__, c, fd, ret); debug("%s(0x%02x, [%i]) = '%c'", __func__, c, fd, ret);
END_STREAM(stream); DEBUG_STREAM("new", stream);
return ret; return ret;
} }
/*
* fclose
*/
int NEW(fclose)(FILE *fp) int NEW(fclose)(FILE *fp)
{ {
int ret, fd; int ret, fd;
@ -695,7 +739,7 @@ int NEW(fclose)(FILE *fp)
if(!_zz_ready || !_zz_iswatched(fd)) if(!_zz_ready || !_zz_iswatched(fd))
return ORIG(fclose)(fp); return ORIG(fclose)(fp);
BEGIN_STREAM(fp); DEBUG_STREAM("old", fp);
_zz_lock(fd); _zz_lock(fd);
ret = ORIG(fclose)(fp); ret = ORIG(fclose)(fp);
_zz_unlock(fd); _zz_unlock(fd);
@ -705,12 +749,16 @@ int NEW(fclose)(FILE *fp)
return ret; return ret;
} }
#define GETDELIM(fn, delim, need_delim) \ /*
* getline, getdelim etc.
*/
#define GETDELIM(mygetdelim, delim, need_delim) \
do { \ do { \
char *line; \ char *line; \
ssize_t done, size; \ ssize_t done, size; \
int fd, already_fuzzed = 0, finished = 0; \ int fd, already_fuzzed = 0, finished = 0; \
LOADSYM(fn); \ LOADSYM(mygetdelim); \
LOADSYM(getdelim); \ LOADSYM(getdelim); \
LOADSYM(fgetc); \ LOADSYM(fgetc); \
fd = fileno(stream); \ fd = fileno(stream); \
@ -719,7 +767,7 @@ int NEW(fclose)(FILE *fp)
ret = ORIG(getdelim)(lineptr, n, delim, stream); \ ret = ORIG(getdelim)(lineptr, n, delim, stream); \
break; \ break; \
} \ } \
BEGIN_STREAM(stream); \ DEBUG_STREAM("old", stream); \
line = *lineptr; \ line = *lineptr; \
size = line ? *n : 0; \ size = line ? *n : 0; \
ret = done = finished = 0; \ ret = done = finished = 0; \
@ -762,7 +810,7 @@ int NEW(fclose)(FILE *fp)
else \ else \
debug("%s(%p, %p, [%i]) = %li", __func__, \ debug("%s(%p, %p, [%i]) = %li", __func__, \
lineptr, n, fd, (long int)ret); \ lineptr, n, fd, (long int)ret); \
END_STREAM(stream); \ DEBUG_STREAM("new", stream); \
break; \ break; \
} while(0) } while(0)
@ -787,6 +835,10 @@ ssize_t NEW(__getdelim)(char **lineptr, size_t *n, int delim, FILE *stream)
} }
#endif #endif
/*
* fgetln
*/
#if defined HAVE_FGETLN #if defined HAVE_FGETLN
char *NEW(fgetln)(FILE *stream, size_t *len) char *NEW(fgetln)(FILE *stream, size_t *len)
{ {
@ -804,7 +856,7 @@ char *NEW(fgetln)(FILE *stream, size_t *len)
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
return ORIG(fgetln)(stream, len); return ORIG(fgetln)(stream, len);
BEGIN_STREAM(stream); DEBUG_STREAM("old", stream);
#if defined REFILL_ONLY_STDIO /* Don't fuzz or seek if we have __srefill() */ #if defined REFILL_ONLY_STDIO /* Don't fuzz or seek if we have __srefill() */
_zz_lock(fd); _zz_lock(fd);
ret = ORIG(fgetln)(stream, len); ret = ORIG(fgetln)(stream, len);
@ -839,31 +891,35 @@ char *NEW(fgetln)(FILE *stream, size_t *len)
#endif #endif
debug("%s([%i], &%li) = %p", __func__, fd, (long int)*len, ret); debug("%s([%i], &%li) = %p", __func__, fd, (long int)*len, ret);
END_STREAM(stream); DEBUG_STREAM("new", stream);
return ret; return ret;
} }
#endif #endif
#if defined HAVE___FILBUF || defined HAVE___SRGET /*
* __srefill, __filbuf, __srget, __uflow
*/
#if defined HAVE___SREFILL || defined HAVE___FILBUF || defined HAVE___SRGET
# define REFILL_RETURNS_INT 1 # define REFILL_RETURNS_INT 1
#elif defined HAVE___UFLOW #elif defined HAVE___UFLOW
# define REFILL_RETURNS_INT 0 # define REFILL_RETURNS_INT 0
#endif #endif
#define REFILL(fn, fn_advances) \ #define REFILL(myrefill, fn_advances) \
do \ do \
{ \ { \
int64_t pos; \ int64_t pos; \
off_t newpos; \ off_t newpos; \
int fd; \ int fd; \
LOADSYM(fn); \ LOADSYM(myrefill); \
fd = fileno(fp); \ fd = fileno(fp); \
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \ if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
return ORIG(fn)(fp); \ return ORIG(myrefill)(fp); \
BEGIN_STREAM(fp); \ DEBUG_STREAM("old", fp); \
pos = _zz_getpos(fd); \ pos = _zz_getpos(fd); \
_zz_lock(fd); \ _zz_lock(fd); \
ret = ORIG(fn)(fp); \ ret = ORIG(myrefill)(fp); \
newpos = lseek(fd, 0, SEEK_CUR); \ newpos = lseek(fd, 0, SEEK_CUR); \
_zz_unlock(fd); \ _zz_unlock(fd); \
if(ret != EOF) \ if(ret != EOF) \
@ -901,7 +957,7 @@ char *NEW(fgetln)(FILE *stream, size_t *len)
debug("%s([%i]) = EOF", __func__, fd, ret); \ debug("%s([%i]) = EOF", __func__, fd, ret); \
else \ else \
debug("%s([%i]) = '%c'", __func__, fd, ret); \ debug("%s([%i]) = '%c'", __func__, fd, ret); \
END_STREAM(fp); \ DEBUG_STREAM("new", fp); \
} \ } \
while(0) while(0)