Refactor the stream diversions.
This commit is contained in:
+288
-285
@@ -213,15 +213,12 @@ static inline void debug_stream(char const *prefix, FILE *stream)
|
||||
|
||||
/*
|
||||
* fopen, fopen64 etc.
|
||||
* freopen, freopen64 etc.
|
||||
*
|
||||
* Strategy: we call the original function, register the new file descriptor
|
||||
* and immediately fuzz whatever's preloaded in the stream structure.
|
||||
*/
|
||||
|
||||
#if defined HAVE_DARWIN_STDIO /* Fuzz fp if we have __srefill() */
|
||||
# define FOPEN_FUZZ() \
|
||||
_zz_fuzz(fd, get_stream_ptr(ret), get_stream_cnt(ret))
|
||||
#else
|
||||
# define FOPEN_FUZZ()
|
||||
#endif
|
||||
|
||||
#define FOPEN(myfopen) \
|
||||
do \
|
||||
{ \
|
||||
@@ -235,12 +232,37 @@ static inline void debug_stream(char const *prefix, FILE *stream)
|
||||
{ \
|
||||
int fd = fileno(ret); \
|
||||
_zz_register(fd); \
|
||||
_zz_fuzz(fd, get_stream_ptr(ret), get_stream_cnt(ret)); \
|
||||
debug("%s(\"%s\", \"%s\") = [%i]", __func__, path, mode, fd); \
|
||||
debug_stream("new", ret); \
|
||||
FOPEN_FUZZ(); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define FREOPEN(myfreopen) \
|
||||
do \
|
||||
{ \
|
||||
int fd0 = -1, fd1 = -1, disp = 0; \
|
||||
LOADSYM(myfreopen); \
|
||||
if(_zz_ready && (fd0 = fileno(stream)) >= 0 && _zz_iswatched(fd0)) \
|
||||
{ \
|
||||
_zz_unregister(fd0); \
|
||||
disp = 1; \
|
||||
} \
|
||||
_zz_lock(-1); \
|
||||
ret = ORIG(myfreopen)(path, mode, stream); \
|
||||
_zz_unlock(-1); \
|
||||
if(ret && _zz_mustwatch(path)) \
|
||||
{ \
|
||||
fd1 = fileno(ret); \
|
||||
_zz_register(fd1); \
|
||||
_zz_fuzz(fd1, get_stream_ptr(ret), get_stream_cnt(ret)); \
|
||||
disp = 1; \
|
||||
} \
|
||||
if(disp) \
|
||||
debug("%s(\"%s\", \"%s\", [%i]) = [%i]", __func__, \
|
||||
path, mode, fd0, fd1); \
|
||||
} while(0)
|
||||
|
||||
FILE *NEW(fopen)(const char *path, const char *mode)
|
||||
{
|
||||
FILE *ret; FOPEN(fopen); return ret;
|
||||
@@ -260,34 +282,6 @@ FILE *NEW(__fopen64)(const char *path, const char *mode)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* freopen, freopen64 etc.
|
||||
*/
|
||||
|
||||
#define FREOPEN(myfreopen) \
|
||||
do \
|
||||
{ \
|
||||
int fd0 = -1, fd1 = -1, disp = 0; \
|
||||
LOADSYM(myfreopen); \
|
||||
if(_zz_ready && (fd0 = fileno(stream)) >= 0 && _zz_iswatched(fd0)) \
|
||||
{ \
|
||||
_zz_unregister(fd0); \
|
||||
disp = 1; \
|
||||
} \
|
||||
_zz_lock(-1); \
|
||||
ret = ORIG(myfreopen)(path, mode, stream); \
|
||||
_zz_unlock(-1); \
|
||||
if(ret && _zz_mustwatch(path)) \
|
||||
{ \
|
||||
fd1 = fileno(ret); \
|
||||
_zz_register(fd1); \
|
||||
disp = 1; \
|
||||
} \
|
||||
if(disp) \
|
||||
debug("%s(\"%s\", \"%s\", [%i]) = [%i]", __func__, \
|
||||
path, mode, fd0, fd1); \
|
||||
} while(0)
|
||||
|
||||
FILE *NEW(freopen)(const char *path, const char *mode, FILE *stream)
|
||||
{
|
||||
FILE *ret; FREOPEN(freopen); return ret;
|
||||
@@ -309,45 +303,105 @@ FILE *NEW(__freopen64)(const char *path, const char *mode, FILE *stream)
|
||||
|
||||
/*
|
||||
* fseek, fseeko etc.
|
||||
* fsetpos64, __fsetpos64
|
||||
* rewind
|
||||
*
|
||||
* Strategy: we store the previous file position and internal buffer
|
||||
* status, then call the original function. If the new file position
|
||||
* lies outside the previous internal buffer, it means the buffer has
|
||||
* been invalidated, so we fuzz whatever's preloaded in it.
|
||||
*/
|
||||
|
||||
#if defined HAVE_DARWIN_STDIO /* Don't fuzz or seek if we have __srefill() */
|
||||
# define FSEEK_FUZZ()
|
||||
#else
|
||||
# define FSEEK_FUZZ() \
|
||||
if(ret == 0) \
|
||||
{ \
|
||||
/* FIXME: check what happens when fseek()ing a pipe */ \
|
||||
switch(whence) \
|
||||
{ \
|
||||
case SEEK_END: \
|
||||
offset = MYFTELL(stream); \
|
||||
/* fall through */ \
|
||||
case SEEK_SET: \
|
||||
_zz_setpos(fd, offset); \
|
||||
break; \
|
||||
case SEEK_CUR: \
|
||||
_zz_addpos(fd, offset); \
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define FSEEK(myfseek) \
|
||||
do \
|
||||
{ \
|
||||
int64_t oldpos, newpos; \
|
||||
int oldoff, oldcnt; \
|
||||
int fd; \
|
||||
LOADSYM(myfseek); \
|
||||
fd = fileno(stream); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
|
||||
return ORIG(myfseek)(stream, offset, whence); \
|
||||
debug_stream("old", stream); \
|
||||
/* FIXME: ftell() will return -1 on a pipe such as stdin */ \
|
||||
oldpos = MYFTELL(stream); \
|
||||
oldoff = get_stream_off(stream); \
|
||||
oldcnt = get_stream_cnt(stream); \
|
||||
_zz_lock(fd); \
|
||||
ret = ORIG(myfseek)(stream, offset, whence); \
|
||||
_zz_unlock(fd); \
|
||||
newpos = MYFTELL(stream); \
|
||||
if (newpos > oldpos + oldcnt || newpos < oldpos - oldoff) \
|
||||
{ \
|
||||
_zz_setpos(fd, newpos - get_stream_off(stream)); \
|
||||
_zz_fuzz(fd, get_stream_ptr(stream) - get_stream_off(stream), \
|
||||
get_stream_cnt(stream) + get_stream_off(stream)); \
|
||||
} \
|
||||
_zz_setpos(fd, newpos); \
|
||||
debug("%s([%i], %lli, %i) = %i", __func__, \
|
||||
fd, (long long int)offset, whence, ret); \
|
||||
FSEEK_FUZZ() \
|
||||
debug_stream("new", stream); \
|
||||
} while(0)
|
||||
|
||||
#define FSETPOS(myfsetpos) \
|
||||
do \
|
||||
{ \
|
||||
int64_t oldpos, newpos; \
|
||||
int oldoff, oldcnt; \
|
||||
int fd; \
|
||||
LOADSYM(myfsetpos); \
|
||||
fd = fileno(stream); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
|
||||
return ORIG(myfsetpos)(stream, pos); \
|
||||
debug_stream("old", stream); \
|
||||
/* FIXME: ftell() will return -1 on a pipe such as stdin */ \
|
||||
oldpos = MYFTELL(stream); \
|
||||
oldoff = get_stream_off(stream); \
|
||||
oldcnt = get_stream_cnt(stream); \
|
||||
_zz_lock(fd); \
|
||||
ret = ORIG(myfsetpos)(stream, pos); \
|
||||
_zz_unlock(fd); \
|
||||
newpos = MYFTELL(stream); \
|
||||
if (newpos > oldpos + oldcnt || newpos < oldpos - oldoff) \
|
||||
{ \
|
||||
_zz_setpos(fd, newpos - get_stream_off(stream)); \
|
||||
_zz_fuzz(fd, get_stream_ptr(stream) - get_stream_off(stream), \
|
||||
get_stream_cnt(stream) + get_stream_off(stream)); \
|
||||
} \
|
||||
_zz_setpos(fd, (int64_t)FPOS_CAST(*pos)); \
|
||||
debug("%s([%i], %lli) = %i", __func__, \
|
||||
fd, (long long int)FPOS_CAST(*pos), ret); \
|
||||
debug_stream("new", stream); \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#define REWIND(myrewind) \
|
||||
do \
|
||||
{ \
|
||||
int64_t oldpos, newpos; \
|
||||
int oldoff, oldcnt; \
|
||||
int fd; \
|
||||
LOADSYM(rewind); \
|
||||
fd = fileno(stream); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
|
||||
return ORIG(rewind)(stream); \
|
||||
debug_stream("old", stream); \
|
||||
/* FIXME: ftell() will return -1 on a pipe such as stdin */ \
|
||||
oldpos = MYFTELL(stream); \
|
||||
oldoff = get_stream_off(stream); \
|
||||
oldcnt = get_stream_cnt(stream); \
|
||||
_zz_lock(fd); \
|
||||
ORIG(rewind)(stream); \
|
||||
_zz_unlock(fd); \
|
||||
newpos = MYFTELL(stream); \
|
||||
if (newpos > oldpos + oldcnt || newpos < oldpos - oldoff) \
|
||||
{ \
|
||||
_zz_setpos(fd, newpos - get_stream_off(stream)); \
|
||||
_zz_fuzz(fd, get_stream_ptr(stream) - get_stream_off(stream), \
|
||||
get_stream_cnt(stream) + get_stream_off(stream)); \
|
||||
} \
|
||||
_zz_setpos(fd, newpos); \
|
||||
debug("%s([%i])", __func__, fd); \
|
||||
debug_stream("new", stream); \
|
||||
} while(0)
|
||||
|
||||
@@ -377,29 +431,6 @@ int NEW(__fseeko64)(FILE *stream, off64_t offset, int whence)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* fsetpos64, __fsetpos64
|
||||
*/
|
||||
|
||||
#define FSETPOS(myfsetpos) \
|
||||
do \
|
||||
{ \
|
||||
int fd; \
|
||||
LOADSYM(myfsetpos); \
|
||||
fd = fileno(stream); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
|
||||
return ORIG(myfsetpos)(stream, pos); \
|
||||
debug_stream("old", stream); \
|
||||
_zz_lock(fd); \
|
||||
ret = ORIG(myfsetpos)(stream, pos); \
|
||||
_zz_unlock(fd); \
|
||||
debug("%s([%i], %lli) = %i", __func__, \
|
||||
fd, (long long int)FPOS_CAST(*pos), ret); \
|
||||
_zz_setpos(fd, (int64_t)FPOS_CAST(*pos)); \
|
||||
debug_stream("new", stream); \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#if defined HAVE_FSETPOS64
|
||||
int NEW(fsetpos64)(FILE *stream, const fpos64_t *pos)
|
||||
{
|
||||
@@ -414,130 +445,62 @@ int NEW(__fsetpos64)(FILE *stream, const fpos64_t *pos)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* rewind
|
||||
*/
|
||||
|
||||
void NEW(rewind)(FILE *stream)
|
||||
{
|
||||
int fd;
|
||||
|
||||
LOADSYM(rewind);
|
||||
fd = fileno(stream);
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
|
||||
{
|
||||
ORIG(rewind)(stream);
|
||||
return;
|
||||
}
|
||||
|
||||
_zz_lock(fd);
|
||||
ORIG(rewind)(stream);
|
||||
_zz_unlock(fd);
|
||||
debug("%s([%i])", __func__, fd);
|
||||
|
||||
#if defined HAVE_DARWIN_STDIO /* Don't fuzz or seek if we have __srefill() */
|
||||
#else
|
||||
/* FIXME: check what happens when rewind()ing a pipe */
|
||||
_zz_setpos(fd, 0);
|
||||
#endif
|
||||
REWIND(rewind);
|
||||
}
|
||||
|
||||
/*
|
||||
* fread, fread_unlocked
|
||||
*
|
||||
* Strategy: we store the previous file position and internal buffer
|
||||
* status, then call the original function. If the new file position
|
||||
* lies outside the previous internal buffer, it means the buffer has
|
||||
* been invalidated, so we fuzz whatever's preloaded in it.
|
||||
*/
|
||||
|
||||
/* Compute how many bytes from the stream were already fuzzed by __filbuf,
|
||||
* __srget or __uflow, and store it in already_fuzzed. If these functions
|
||||
* are not available, do nothing. */
|
||||
#if defined HAVE_BSD_STDIO
|
||||
# define FREAD_PREFUZZ(fd, oldpos) \
|
||||
#define FREAD(myfread) /* NEW */ \
|
||||
do \
|
||||
{ \
|
||||
int64_t tmp = _zz_getpos(fd); \
|
||||
_zz_setpos(fd, oldpos); \
|
||||
already_fuzzed = _zz_getfuzzed(fd); \
|
||||
_zz_setpos(fd, tmp); \
|
||||
} \
|
||||
while(0)
|
||||
#else
|
||||
# define FREAD_PREFUZZ(fd, oldpos) do {} while(0)
|
||||
#endif
|
||||
|
||||
/* Fuzz the data returned by fread(). If a __fillbuf mechanism already
|
||||
* fuzzed some of our data, we skip the relevant amount of bytes. If we
|
||||
* have __srefill, we just do nothing because that function is the only
|
||||
* one that actually fuzzes things. */
|
||||
#if defined HAVE_DARWIN_STDIO
|
||||
# define FREAD_FUZZ(fd, oldpos) \
|
||||
do \
|
||||
{ \
|
||||
debug("%s(%p, %li, %li, [%i]) = %li", __func__, ptr, \
|
||||
(long int)size, (long int)nmemb, fd, (long int)ret); \
|
||||
} while(0)
|
||||
#else
|
||||
# define FREAD_FUZZ(fd, oldpos) \
|
||||
do \
|
||||
{ \
|
||||
int64_t newpos = MYFTELL(stream); \
|
||||
/* XXX: the number of bytes read is not ret * size, because \
|
||||
* a partial read may have advanced the stream pointer. However, \
|
||||
* when reading from a pipe ftell() will return 0, and ret * size \
|
||||
* is then better than nothing. */ \
|
||||
if(newpos <= 0) \
|
||||
{ \
|
||||
oldpos = _zz_getpos(fd); \
|
||||
newpos = oldpos + ret * size; \
|
||||
} \
|
||||
if(newpos != oldpos) \
|
||||
{ \
|
||||
char *b = ptr; \
|
||||
/* Skip bytes that were already fuzzed by __filbuf or __srget */ \
|
||||
if(newpos > oldpos + already_fuzzed) \
|
||||
{ \
|
||||
_zz_setpos(fd, oldpos + already_fuzzed); \
|
||||
_zz_fuzz(fd, ptr, newpos - oldpos - already_fuzzed); \
|
||||
/* FIXME: we need to fuzz the extra bytes that may have been \
|
||||
* read by the fread call we just made, or subsequent calls \
|
||||
* to getc_unlocked may miss them. */ \
|
||||
_zz_setpos(fd, newpos); \
|
||||
_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__, \
|
||||
ptr, (long int)size, (long int)nmemb, fd, \
|
||||
(long int)ret, b[0], b[1], b[2], b[3]); \
|
||||
else \
|
||||
debug("%s(%p, %li, %li, [%i]) = %li \"%c...", __func__, ptr, \
|
||||
(long int)size, (long int)nmemb, fd, \
|
||||
(long int)ret, b[0]); \
|
||||
} \
|
||||
else \
|
||||
debug("%s(%p, %li, %li, [%i]) = %li", __func__, ptr, \
|
||||
(long int)size, (long int)nmemb, fd, (long int)ret); \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
#define FREAD(myfread) \
|
||||
do \
|
||||
{ \
|
||||
int64_t oldpos; \
|
||||
int fd, already_fuzzed = 0; \
|
||||
int64_t oldpos, newpos; \
|
||||
uint8_t *b = ptr;\
|
||||
int oldoff, oldcnt; \
|
||||
int fd; \
|
||||
LOADSYM(myfread); \
|
||||
fd = fileno(stream); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
|
||||
return ORIG(myfread)(ptr, size, nmemb, stream); \
|
||||
debug_stream("old", stream); \
|
||||
/* FIXME: ftell() will return -1 on a pipe such as stdin */ \
|
||||
oldpos = MYFTELL(stream); \
|
||||
_zz_setpos(fd, oldpos); \
|
||||
oldoff = get_stream_off(stream); \
|
||||
oldcnt = get_stream_cnt(stream); \
|
||||
_zz_lock(fd); \
|
||||
ret = ORIG(myfread)(ptr, size, nmemb, stream); \
|
||||
_zz_unlock(fd); \
|
||||
FREAD_PREFUZZ(fd, oldpos); \
|
||||
FREAD_FUZZ(fd, oldpos); \
|
||||
newpos = MYFTELL(stream); \
|
||||
if (newpos > oldpos + oldcnt) \
|
||||
{ \
|
||||
/* Fuzz returned data that wasn't in the old internal buffer */ \
|
||||
_zz_setpos(fd, oldpos + oldcnt); \
|
||||
_zz_fuzz(fd, b + oldcnt, newpos - oldpos - oldcnt); \
|
||||
/* Fuzz the internal stream buffer */ \
|
||||
_zz_setpos(fd, newpos - get_stream_off(stream)); \
|
||||
_zz_fuzz(fd, get_stream_ptr(stream) - get_stream_off(stream), \
|
||||
get_stream_cnt(stream) + get_stream_off(stream)); \
|
||||
} \
|
||||
_zz_setpos(fd, newpos); \
|
||||
if (newpos > oldpos + 4) \
|
||||
debug("%s(%p, %li, %li, [%i]) = %li \"%c%c%c%c...", __func__, \
|
||||
ptr, (long int)size, (long int)nmemb, fd, \
|
||||
(long int)ret, b[0], b[1], b[2], b[3]); \
|
||||
else if (newpos > oldpos) \
|
||||
debug("%s(%p, %li, %li, [%i]) = %li \"%c...", __func__, ptr, \
|
||||
(long int)size, (long int)nmemb, fd, \
|
||||
(long int)ret, b[0]); \
|
||||
else \
|
||||
debug("%s(%p, %li, %li, [%i]) = %li", __func__, ptr, \
|
||||
(long int)size, (long int)nmemb, fd, (long int)ret); \
|
||||
debug_stream("new", stream); \
|
||||
} while(0)
|
||||
|
||||
@@ -556,42 +519,46 @@ size_t NEW(fread_unlocked)(void *ptr, size_t size, size_t nmemb, FILE *stream)
|
||||
|
||||
/*
|
||||
* getc, getchar, fgetc etc.
|
||||
*
|
||||
* Strategy: we store the previous file position and internal buffer
|
||||
* status, then call the original function. If the new file position
|
||||
* lies outside the previous internal buffer, it means the buffer has
|
||||
* been invalidated, so we fuzz whatever's preloaded in it.
|
||||
*/
|
||||
|
||||
#if defined HAVE_BSD_STDIO
|
||||
# define FGETC_PREFUZZ already_fuzzed = _zz_getfuzzed(fd);
|
||||
#else
|
||||
# define FGETC_PREFUZZ
|
||||
#endif
|
||||
|
||||
#if defined HAVE_DARWIN_STDIO /* Don't fuzz or seek if we have __srefill() */
|
||||
# define FGETC_FUZZ
|
||||
#else
|
||||
# define FGETC_FUZZ \
|
||||
if(ret != EOF) \
|
||||
{ \
|
||||
uint8_t ch = ret; \
|
||||
if(already_fuzzed <= 0) \
|
||||
_zz_fuzz(fd, &ch, 1); \
|
||||
_zz_addpos(fd, 1); \
|
||||
ret = ch; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define FGETC(myfgetc, s, arg) \
|
||||
do { \
|
||||
int fd, already_fuzzed = 0; \
|
||||
int64_t oldpos, newpos; \
|
||||
int oldoff, oldcnt; \
|
||||
int fd; \
|
||||
LOADSYM(myfgetc); \
|
||||
fd = fileno(s); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
|
||||
return ORIG(myfgetc)(arg); \
|
||||
debug_stream("old", s); \
|
||||
_zz_setpos(fd, MYFTELL(s)); \
|
||||
oldpos = MYFTELL(s); \
|
||||
oldoff = get_stream_off(s); \
|
||||
oldcnt = get_stream_cnt(s); \
|
||||
_zz_lock(fd); \
|
||||
ret = ORIG(myfgetc)(arg); \
|
||||
_zz_unlock(fd); \
|
||||
FGETC_PREFUZZ \
|
||||
FGETC_FUZZ \
|
||||
newpos = MYFTELL(s); \
|
||||
if (oldcnt == 0 && ret != EOF) \
|
||||
{ \
|
||||
/* Fuzz returned data that wasn't in the old internal buffer */ \
|
||||
uint8_t ch = ret; \
|
||||
_zz_setpos(fd, oldpos); \
|
||||
_zz_fuzz(fd, &ch, 1); \
|
||||
ret = ch; \
|
||||
} \
|
||||
if (newpos > oldpos + oldcnt) \
|
||||
{ \
|
||||
/* Fuzz the internal stream buffer */ \
|
||||
_zz_setpos(fd, newpos - get_stream_off(s)); \
|
||||
_zz_fuzz(fd, get_stream_ptr(s) - get_stream_off(s), \
|
||||
get_stream_cnt(s) + get_stream_off(s)); \
|
||||
} \
|
||||
_zz_setpos(fd, newpos); \
|
||||
if(ret == EOF) \
|
||||
debug("%s([%i]) = EOF", __func__, fd); \
|
||||
else \
|
||||
@@ -651,13 +618,23 @@ int NEW(fgetc_unlocked)(FILE *stream)
|
||||
* fgets, fgets_unlocked
|
||||
*/
|
||||
|
||||
#if defined HAVE_DARWIN_STDIO /* Don't fuzz or seek if we have __srefill() */
|
||||
# define FGETS_FUZZ(myfgets, myfgetc) \
|
||||
_zz_lock(fd); \
|
||||
ret = ORIG(myfgets)(s, size, stream); \
|
||||
_zz_unlock(fd);
|
||||
#else
|
||||
# define FGETS_FUZZ(myfgets, myfgetc) \
|
||||
#define FGETS(myfgets, myfgetc) \
|
||||
do \
|
||||
{ \
|
||||
int64_t oldpos, newpos; \
|
||||
int oldoff, oldcnt; \
|
||||
int fd; \
|
||||
ret = s; \
|
||||
LOADSYM(myfgets); \
|
||||
LOADSYM(myfgetc); \
|
||||
fd = fileno(stream); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
|
||||
return ORIG(myfgets)(s, size, stream); \
|
||||
debug_stream("old", stream); \
|
||||
oldpos = MYFTELL(stream); \
|
||||
oldoff = get_stream_off(stream); \
|
||||
oldcnt = get_stream_cnt(stream); \
|
||||
newpos = oldpos; \
|
||||
if(size <= 0) \
|
||||
ret = NULL; \
|
||||
else if(size == 1) \
|
||||
@@ -667,44 +644,47 @@ int NEW(fgetc_unlocked)(FILE *stream)
|
||||
int i; \
|
||||
for(i = 0; i < size - 1; i++) \
|
||||
{ \
|
||||
int ch; \
|
||||
int chr; \
|
||||
_zz_lock(fd); \
|
||||
ch = ORIG(myfgetc)(stream); \
|
||||
chr = ORIG(myfgetc)(stream); \
|
||||
_zz_unlock(fd); \
|
||||
if(ch == EOF) \
|
||||
newpos = oldpos + 1; \
|
||||
if (oldcnt == 0 && chr != EOF) \
|
||||
{ \
|
||||
/* Fuzz returned data that wasn't in the old buffer */ \
|
||||
uint8_t ch = chr; \
|
||||
_zz_setpos(fd, oldpos); \
|
||||
_zz_fuzz(fd, &ch, 1); \
|
||||
chr = ch; \
|
||||
} \
|
||||
if (newpos > oldpos + oldcnt) \
|
||||
{ \
|
||||
/* Fuzz the internal stream buffer, if necessary */ \
|
||||
_zz_setpos(fd, newpos - get_stream_off(stream)); \
|
||||
_zz_fuzz(fd, get_stream_ptr(stream) - get_stream_off(stream), \
|
||||
get_stream_cnt(stream) + get_stream_off(stream)); \
|
||||
} \
|
||||
oldpos = newpos; \
|
||||
oldoff = get_stream_off(stream); \
|
||||
oldcnt = get_stream_cnt(stream); \
|
||||
if(chr == EOF) \
|
||||
{ \
|
||||
s[i] = '\0'; \
|
||||
if(!i) \
|
||||
ret = NULL; \
|
||||
break; \
|
||||
} \
|
||||
s[i] = (char)(unsigned char)ch; \
|
||||
_zz_fuzz(fd, (uint8_t *)s + i, 1); /* rather inefficient */ \
|
||||
_zz_addpos(fd, 1); \
|
||||
s[i] = (char)(unsigned char)chr; \
|
||||
if(s[i] == '\n') \
|
||||
{ \
|
||||
s[i + 1] = '\0'; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define FGETS(myfgets, myfgetc) \
|
||||
do \
|
||||
{ \
|
||||
int fd; \
|
||||
ret = s; \
|
||||
LOADSYM(myfgets); \
|
||||
LOADSYM(myfgetc); \
|
||||
fd = fileno(stream); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
|
||||
return ORIG(myfgets)(s, size, stream); \
|
||||
debug_stream("old", s); \
|
||||
_zz_setpos(fd, MYFTELL(stream)); \
|
||||
FGETS_FUZZ(myfgets, myfgetc) \
|
||||
} \
|
||||
_zz_setpos(fd, newpos); \
|
||||
debug("%s(%p, %i, [%i]) = %p", __func__, s, size, fd, ret); \
|
||||
debug_stream("new", s); \
|
||||
debug_stream("new", stream); \
|
||||
} while(0)
|
||||
|
||||
char *NEW(fgets)(char *s, int size, FILE *stream)
|
||||
@@ -725,7 +705,7 @@ char *NEW(fgets_unlocked)(char *s, int size, FILE *stream)
|
||||
|
||||
int NEW(ungetc)(int c, FILE *stream)
|
||||
{
|
||||
int ret, fd;
|
||||
int oldpos, ret, fd;
|
||||
|
||||
LOADSYM(ungetc);
|
||||
fd = fileno(stream);
|
||||
@@ -733,22 +713,11 @@ int NEW(ungetc)(int c, FILE *stream)
|
||||
return ORIG(ungetc)(c, stream);
|
||||
|
||||
debug_stream("old", stream);
|
||||
_zz_setpos(fd, MYFTELL(stream));
|
||||
oldpos = MYFTELL(stream);
|
||||
_zz_lock(fd);
|
||||
ret = ORIG(ungetc)(c, stream);
|
||||
_zz_unlock(fd);
|
||||
|
||||
if(ret != EOF)
|
||||
{
|
||||
struct fuzz *fuzz = _zz_getfuzz(fd);
|
||||
fuzz->uflag = 1;
|
||||
fuzz->upos = _zz_getpos(fd) - 1;
|
||||
fuzz->uchar = c;
|
||||
#if defined HAVE_DARWIN_STDIO /* Don't fuzz or seek if we have __srefill() */
|
||||
#else
|
||||
_zz_addpos(fd, -1);
|
||||
#endif
|
||||
}
|
||||
_zz_setpos(fd, oldpos - 1);
|
||||
|
||||
if(ret == EOF)
|
||||
debug("%s(0x%02x, [%i]) = EOF", __func__, c, fd);
|
||||
@@ -787,26 +756,28 @@ int NEW(fclose)(FILE *fp)
|
||||
|
||||
#define GETDELIM(mygetdelim, delim, need_delim) \
|
||||
do { \
|
||||
int64_t oldpos, newpos; \
|
||||
char *line; \
|
||||
ssize_t done, size; \
|
||||
int fd, already_fuzzed = 0, finished = 0; \
|
||||
int oldoff, oldcnt; \
|
||||
int fd, finished = 0; \
|
||||
LOADSYM(mygetdelim); \
|
||||
LOADSYM(getdelim); \
|
||||
LOADSYM(fgetc); \
|
||||
fd = fileno(stream); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
|
||||
{ \
|
||||
ret = ORIG(getdelim)(lineptr, n, delim, stream); \
|
||||
break; \
|
||||
} \
|
||||
return ORIG(getdelim)(lineptr, n, delim, stream); \
|
||||
debug_stream("old", stream); \
|
||||
_zz_setpos(fd, MYFTELL(stream)); \
|
||||
oldpos = MYFTELL(stream); \
|
||||
oldoff = get_stream_off(stream); \
|
||||
oldcnt = get_stream_cnt(stream); \
|
||||
newpos = oldpos; \
|
||||
line = *lineptr; \
|
||||
size = line ? *n : 0; \
|
||||
ret = done = finished = 0; \
|
||||
for(;;) \
|
||||
{ \
|
||||
int ch; \
|
||||
int chr; \
|
||||
if(done >= size) /* highly inefficient but I don't care */ \
|
||||
line = realloc(line, size = done + 1); \
|
||||
if(finished) \
|
||||
@@ -817,19 +788,36 @@ int NEW(fclose)(FILE *fp)
|
||||
break; \
|
||||
} \
|
||||
_zz_lock(fd); \
|
||||
ch = ORIG(fgetc)(stream); \
|
||||
chr = ORIG(fgetc)(stream); \
|
||||
_zz_unlock(fd); \
|
||||
if(ch == EOF) \
|
||||
newpos = oldpos + 1; \
|
||||
if (oldcnt == 0 && chr != EOF) \
|
||||
{ \
|
||||
/* Fuzz returned data that wasn't in the old buffer */ \
|
||||
uint8_t ch = chr; \
|
||||
_zz_setpos(fd, oldpos); \
|
||||
_zz_fuzz(fd, &ch, 1); \
|
||||
chr = ch; \
|
||||
} \
|
||||
if (newpos > oldpos + oldcnt) \
|
||||
{ \
|
||||
/* Fuzz the internal stream buffer, if necessary */ \
|
||||
_zz_setpos(fd, newpos - get_stream_off(stream)); \
|
||||
_zz_fuzz(fd, get_stream_ptr(stream) - get_stream_off(stream), \
|
||||
get_stream_cnt(stream) + get_stream_off(stream)); \
|
||||
} \
|
||||
oldpos = newpos; \
|
||||
oldoff = get_stream_off(stream); \
|
||||
oldcnt = get_stream_cnt(stream); \
|
||||
if(chr == EOF) \
|
||||
{ \
|
||||
finished = 1; \
|
||||
ret = done; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
unsigned char c = ch; \
|
||||
_zz_fuzz(fd, &c, 1); /* even more inefficient */ \
|
||||
unsigned char c = chr; \
|
||||
line[done++] = c; \
|
||||
_zz_addpos(fd, 1); \
|
||||
if(c == delim) \
|
||||
{ \
|
||||
finished = 1; \
|
||||
@@ -837,6 +825,7 @@ int NEW(fclose)(FILE *fp)
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
_zz_setpos(fd, newpos); \
|
||||
if(need_delim) \
|
||||
debug("%s(%p, %p, '%c', [%i]) = %li", __func__, \
|
||||
lineptr, n, delim, fd, (long int)ret); \
|
||||
@@ -875,13 +864,11 @@ ssize_t NEW(__getdelim)(char **lineptr, size_t *n, int delim, FILE *stream)
|
||||
#if defined HAVE_FGETLN
|
||||
char *NEW(fgetln)(FILE *stream, size_t *len)
|
||||
{
|
||||
int64_t oldpos, newpos;
|
||||
char *ret;
|
||||
#if defined HAVE_DARWIN_STDIO /* Don't fuzz or seek if we have __srefill() */
|
||||
#else
|
||||
struct fuzz *fuzz;
|
||||
size_t i, size;
|
||||
#endif
|
||||
int fd;
|
||||
int oldoff, oldcnt, fd;
|
||||
|
||||
LOADSYM(fgetln);
|
||||
LOADSYM(fgetc);
|
||||
@@ -890,31 +877,48 @@ char *NEW(fgetln)(FILE *stream, size_t *len)
|
||||
return ORIG(fgetln)(stream, len);
|
||||
|
||||
debug_stream("old", stream);
|
||||
#if defined HAVE_DARWIN_STDIO /* Don't fuzz or seek if we have __srefill() */
|
||||
_zz_lock(fd);
|
||||
ret = ORIG(fgetln)(stream, len);
|
||||
_zz_unlock(fd);
|
||||
#else
|
||||
_zz_setpos(fd, MYFTELL(stream));
|
||||
oldpos = MYFTELL(stream);
|
||||
oldoff = get_stream_off(stream);
|
||||
oldcnt = get_stream_cnt(stream);
|
||||
newpos = oldpos;
|
||||
|
||||
fuzz = _zz_getfuzz(fd);
|
||||
|
||||
for(i = size = 0; ; /* i is incremented below */)
|
||||
{
|
||||
int ch;
|
||||
int chr;
|
||||
|
||||
_zz_lock(fd);
|
||||
ch = ORIG(fgetc)(stream);
|
||||
chr = ORIG(fgetc)(stream);
|
||||
_zz_unlock(fd);
|
||||
|
||||
if(ch == EOF)
|
||||
newpos = oldpos + 1;
|
||||
if (oldcnt == 0 && chr != EOF)
|
||||
{
|
||||
/* Fuzz returned data that wasn't in the old buffer */
|
||||
uint8_t ch = chr;
|
||||
_zz_setpos(fd, oldpos);
|
||||
_zz_fuzz(fd, &ch, 1);
|
||||
chr = ch;
|
||||
}
|
||||
if (newpos > oldpos + oldcnt)
|
||||
{
|
||||
/* Fuzz the internal stream buffer, if necessary */
|
||||
_zz_setpos(fd, newpos - get_stream_off(stream));
|
||||
_zz_fuzz(fd, get_stream_ptr(stream) - get_stream_off(stream),
|
||||
get_stream_cnt(stream) + get_stream_off(stream));
|
||||
}
|
||||
oldpos = newpos;
|
||||
oldoff = get_stream_off(stream);
|
||||
oldcnt = get_stream_cnt(stream);
|
||||
|
||||
if(chr == EOF)
|
||||
break;
|
||||
|
||||
if(i >= size)
|
||||
fuzz->tmp = realloc(fuzz->tmp, (size += 80));
|
||||
|
||||
fuzz->tmp[i] = (char)(unsigned char)ch;
|
||||
_zz_fuzz(fd, (uint8_t *)fuzz->tmp + i, 1); /* rather inefficient */
|
||||
_zz_addpos(fd, 1);
|
||||
fuzz->tmp[i] = (char)(unsigned char)chr;
|
||||
|
||||
if(fuzz->tmp[i++] == '\n')
|
||||
break;
|
||||
@@ -922,7 +926,6 @@ char *NEW(fgetln)(FILE *stream, size_t *len)
|
||||
|
||||
*len = i;
|
||||
ret = fuzz->tmp;
|
||||
#endif
|
||||
|
||||
debug("%s([%i], &%li) = %p", __func__, fd, (long int)*len, ret);
|
||||
debug_stream("new", stream);
|
||||
@@ -988,7 +991,7 @@ char *NEW(fgetln)(FILE *stream, size_t *len)
|
||||
if (REFILL_RETURNS_INT) \
|
||||
debug("%s([%i]) = %i", __func__, fd, ret); \
|
||||
else if (ret == EOF) \
|
||||
debug("%s([%i]) = EOF", __func__, fd, ret); \
|
||||
debug("%s([%i]) = EOF", __func__, fd); \
|
||||
else \
|
||||
debug("%s([%i]) = '%c'", __func__, fd, ret); \
|
||||
debug_stream("new", fp); \
|
||||
|
||||
Reference in New Issue
Block a user