Reimplement __uflow() under Linux. Unlocked IO now works on Linux, except
in combination with getdelim()/getline().
This commit is contained in:
parent
f36a3e475c
commit
9ec47e4193
29
configure.ac
29
configure.ac
@ -78,23 +78,30 @@ AC_MSG_RESULT($ac_v_recv_t)
|
||||
AC_DEFINE_UNQUOTED(RECV_T, $ac_v_recv_t, [Define to the recv() return type])
|
||||
|
||||
AC_MSG_CHECKING(for FILE* internal members)
|
||||
ac_cv_have_glibc_fp="no"
|
||||
ac_v_fp_cnt="unknown"
|
||||
ac_v_fp_ptr="unknown"
|
||||
AC_TRY_COMPILE([#include <stdio.h>],
|
||||
[FILE *fp; fp->__cnt++; fp->__ptr++],
|
||||
[ac_v_fp_cnt=__cnt; ac_v_fp_ptr=__ptr],
|
||||
[FILE *fp; fp->_IO_read_ptr++; fp->_IO_read_end++],
|
||||
[ac_cv_have_glibc_fp=yes; ac_v_fp_cnt=_IO_read_end; ac_v_fp_ptr=_IO_read_ptr],
|
||||
[AC_TRY_COMPILE([#include <stdio.h>],
|
||||
[FILE *fp; fp->_cnt++; fp->_ptr++],
|
||||
[ac_v_fp_cnt=_cnt; ac_v_fp_ptr=_ptr],
|
||||
[FILE *fp; fp->__cnt++; fp->__ptr++],
|
||||
[ac_v_fp_cnt=__cnt; ac_v_fp_ptr=__ptr],
|
||||
[AC_TRY_COMPILE([#include <stdio.h>],
|
||||
[FILE *fp; fp->_c++; fp->_p++],
|
||||
[ac_v_fp_cnt=_c; ac_v_fp_ptr=_p],
|
||||
[FILE *fp; fp->_cnt++; fp->_ptr++],
|
||||
[ac_v_fp_cnt=_cnt; ac_v_fp_ptr=_ptr],
|
||||
[AC_TRY_COMPILE([#include <stdio.h>],
|
||||
[FILE *fp; fp->_r++; fp->_p++],
|
||||
[ac_v_fp_cnt=_r; ac_v_fp_ptr=_p])])])])
|
||||
AC_MSG_RESULT($ac_v_fp_cnt/$ac_v_fp_ptr)
|
||||
AC_DEFINE_UNQUOTED(FILE_CNT, $ac_v_fp_cnt, [Define to the FILE::cnt member name])
|
||||
AC_DEFINE_UNQUOTED(FILE_PTR, $ac_v_fp_ptr, [Define to the FILE::ptr member name])
|
||||
[FILE *fp; fp->_c++; fp->_p++],
|
||||
[ac_v_fp_cnt=_c; ac_v_fp_ptr=_p],
|
||||
[AC_TRY_COMPILE([#include <stdio.h>],
|
||||
[FILE *fp; fp->_r++; fp->_p++],
|
||||
[ac_v_fp_cnt=_r; ac_v_fp_ptr=_p])])])])])
|
||||
AC_MSG_RESULT($ac_v_fp_ptr/$ac_v_fp_cnt)
|
||||
if test "$ac_cv_have_glibc_fp" != "no"; then
|
||||
AC_DEFINE(HAVE_GLIBC_FP, 1, [Define to 1 if FILE has glibc-style members])
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED(FILE_PTR, $ac_v_fp_ptr, [Define to the FILE::ptr member])
|
||||
AC_DEFINE_UNQUOTED(FILE_CNT, $ac_v_fp_cnt, [Define to the FILE::cnt member])
|
||||
|
||||
dnl On HP-UX, fpos64_t == int64_t, but on Linux it's a compound object.
|
||||
AC_MSG_CHECKING(how to access fpos64_t x)
|
||||
|
||||
@ -49,6 +49,7 @@
|
||||
#define HAVE_GETOPT_LONG 1
|
||||
#define HAVE_GETPAGESIZE 1
|
||||
#define HAVE_GETTIMEOFDAY 1
|
||||
/* #undef HAVE_GLIBC_FP */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
#define HAVE_IO_H 1
|
||||
/* #undef HAVE_KILL */
|
||||
|
||||
105
src/lib-stream.c
105
src/lib-stream.c
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* zzuf - general purpose fuzzer
|
||||
* Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
|
||||
* Copyright (c) 2006-2009 Sam Hocevar <sam@hocevar.net>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* $Id$
|
||||
@ -59,6 +59,10 @@ int NEW(__filbuf)(FILE *fp);
|
||||
int NEW(__srget)(FILE *fp);
|
||||
#endif
|
||||
|
||||
#if defined HAVE___UFLOW
|
||||
int NEW(__uflow)(FILE *fp);
|
||||
#endif
|
||||
|
||||
/* Library functions that we divert */
|
||||
static FILE * (*ORIG(fopen)) (const char *path, const char *mode);
|
||||
#if defined HAVE_FOPEN64
|
||||
@ -134,6 +138,9 @@ static ssize_t (*ORIG(getdelim)) (char **lineptr, size_t *n, int delim,
|
||||
static ssize_t (*ORIG(__getdelim)) (char **lineptr, size_t *n, int delim,
|
||||
FILE *stream);
|
||||
#endif
|
||||
#if defined HAVE___UFLOW
|
||||
static int (*ORIG(__uflow)) (FILE *fp);
|
||||
#endif
|
||||
|
||||
/* Additional BSDisms */
|
||||
#if defined HAVE_FGETLN
|
||||
@ -151,14 +158,39 @@ int (*ORIG(__srget)) (FILE *fp);
|
||||
int (*ORIG(__filbuf)) (FILE *fp);
|
||||
#endif
|
||||
|
||||
/* 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)
|
||||
{
|
||||
return (uint8_t *)stream->FILE_PTR;
|
||||
}
|
||||
|
||||
static inline int get_stream_cnt(FILE *stream)
|
||||
{
|
||||
# if defined HAVE_GLIBC_FP
|
||||
return (int)((uint8_t *)stream->FILE_CNT - (uint8_t *)stream->FILE_PTR);
|
||||
# else
|
||||
return stream->FILE_CNT;
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Our function wrappers */
|
||||
#if defined REFILL_ONLY_STDIO /* Fuzz fp if we have __srefill() */
|
||||
# define FOPEN_FUZZ() \
|
||||
_zz_fuzz(fd, ret->FILE_PTR, ret->FILE_CNT)
|
||||
_zz_fuzz(fd, get_stream_ptr(ret), get_stream_cnt(ret))
|
||||
#else
|
||||
# define FOPEN_FUZZ()
|
||||
#endif
|
||||
|
||||
#define BEGIN_STREAM(fp) \
|
||||
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 \
|
||||
{ \
|
||||
@ -173,6 +205,7 @@ int (*ORIG(__filbuf)) (FILE *fp);
|
||||
int fd = fileno(ret); \
|
||||
_zz_register(fd); \
|
||||
debug("%s(\"%s\", \"%s\") = [%i]", __func__, path, mode, fd); \
|
||||
END_STREAM(ret); \
|
||||
FOPEN_FUZZ(); \
|
||||
} \
|
||||
} while(0)
|
||||
@ -269,12 +302,14 @@ FILE *NEW(__freopen64)(const char *path, const char *mode, FILE *stream)
|
||||
fd = fileno(stream); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
|
||||
return ORIG(fn)(stream, offset, whence); \
|
||||
BEGIN_STREAM(stream); \
|
||||
_zz_lock(fd); \
|
||||
ret = ORIG(fn)(stream, offset, whence); \
|
||||
_zz_unlock(fd); \
|
||||
debug("%s([%i], %lli, %i) = %i", __func__, \
|
||||
fd, (long long int)offset, whence, ret); \
|
||||
FSEEK_FUZZ(fn2) \
|
||||
END_STREAM(stream); \
|
||||
} while(0)
|
||||
|
||||
int NEW(fseek)(FILE *stream, long offset, int whence)
|
||||
@ -311,12 +346,14 @@ int NEW(__fseeko64)(FILE *stream, off64_t offset, int whence)
|
||||
fd = fileno(stream); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
|
||||
return ORIG(fn)(stream, pos); \
|
||||
BEGIN_STREAM(stream); \
|
||||
_zz_lock(fd); \
|
||||
ret = ORIG(fn)(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)); \
|
||||
END_STREAM(stream); \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
@ -358,7 +395,7 @@ void NEW(rewind)(FILE *stream)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined HAVE___FILBUF || defined HAVE___SRGET
|
||||
#if defined HAVE___FILBUF || defined HAVE___SRGET || defined HAVE___UFLOW
|
||||
# define FREAD_PREFUZZ() \
|
||||
do \
|
||||
{ \
|
||||
@ -427,12 +464,14 @@ void NEW(rewind)(FILE *stream)
|
||||
fd = fileno(stream); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
|
||||
return ORIG(fn)(ptr, size, nmemb, stream); \
|
||||
BEGIN_STREAM(stream); \
|
||||
pos = ftell(stream); \
|
||||
_zz_lock(fd); \
|
||||
ret = ORIG(fn)(ptr, size, nmemb, stream); \
|
||||
_zz_unlock(fd); \
|
||||
FREAD_PREFUZZ(); \
|
||||
FREAD_FUZZ(); \
|
||||
END_STREAM(stream); \
|
||||
} while(0)
|
||||
|
||||
size_t NEW(fread)(void *ptr, size_t size, size_t nmemb, FILE *stream)
|
||||
@ -448,7 +487,7 @@ size_t NEW(fread_unlocked)(void *ptr, size_t size, size_t nmemb, FILE *stream)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined HAVE___FILBUF || defined HAVE___SRGET
|
||||
#if defined HAVE___FILBUF || defined HAVE___SRGET || defined HAVE___UFLOW
|
||||
# define FGETC_PREFUZZ already_fuzzed = _zz_getfuzzed(fd);
|
||||
#else
|
||||
# define FGETC_PREFUZZ
|
||||
@ -475,6 +514,7 @@ size_t NEW(fread_unlocked)(void *ptr, size_t size, size_t nmemb, FILE *stream)
|
||||
fd = fileno(s); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
|
||||
return ORIG(fn)(arg); \
|
||||
BEGIN_STREAM(s); \
|
||||
_zz_lock(fd); \
|
||||
ret = ORIG(fn)(arg); \
|
||||
_zz_unlock(fd); \
|
||||
@ -484,6 +524,7 @@ size_t NEW(fread_unlocked)(void *ptr, size_t size, size_t nmemb, FILE *stream)
|
||||
debug("%s([%i]) = EOF", __func__, fd); \
|
||||
else \
|
||||
debug("%s([%i]) = '%c'", __func__, fd, ret); \
|
||||
END_STREAM(s); \
|
||||
} while(0)
|
||||
|
||||
#undef getc /* can be a macro; we don’t want that */
|
||||
@ -583,8 +624,10 @@ int NEW(fgetc_unlocked)(FILE *stream)
|
||||
fd = fileno(stream); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
|
||||
return ORIG(fn)(s, size, stream); \
|
||||
BEGIN_STREAM(s); \
|
||||
FGETS_FUZZ(fn, fn2) \
|
||||
debug("%s(%p, %i, [%i]) = %p", __func__, s, size, fd, ret); \
|
||||
END_STREAM(s); \
|
||||
} while(0)
|
||||
|
||||
char *NEW(fgets)(char *s, int size, FILE *stream)
|
||||
@ -608,6 +651,7 @@ int NEW(ungetc)(int c, FILE *stream)
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
|
||||
return ORIG(ungetc)(c, stream);
|
||||
|
||||
BEGIN_STREAM(stream);
|
||||
_zz_lock(fd);
|
||||
ret = ORIG(ungetc)(c, stream);
|
||||
_zz_unlock(fd);
|
||||
@ -628,7 +672,7 @@ int NEW(ungetc)(int c, FILE *stream)
|
||||
debug("%s(0x%02x, [%i]) = EOF", __func__, c, fd);
|
||||
else
|
||||
debug("%s(0x%02x, [%i]) = '%c'", __func__, c, fd, ret);
|
||||
|
||||
END_STREAM(stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -641,6 +685,7 @@ int NEW(fclose)(FILE *fp)
|
||||
if(!_zz_ready || !_zz_iswatched(fd))
|
||||
return ORIG(fclose)(fp);
|
||||
|
||||
BEGIN_STREAM(fp);
|
||||
_zz_lock(fd);
|
||||
ret = ORIG(fclose)(fp);
|
||||
_zz_unlock(fd);
|
||||
@ -660,7 +705,11 @@ int NEW(fclose)(FILE *fp)
|
||||
LOADSYM(fgetc); \
|
||||
fd = fileno(stream); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
|
||||
return ORIG(getdelim)(lineptr, n, delim, stream); \
|
||||
{ \
|
||||
ret = ORIG(getdelim)(lineptr, n, delim, stream); \
|
||||
break; \
|
||||
} \
|
||||
BEGIN_STREAM(stream); \
|
||||
line = *lineptr; \
|
||||
size = line ? *n : 0; \
|
||||
ret = done = finished = 0; \
|
||||
@ -703,7 +752,8 @@ int NEW(fclose)(FILE *fp)
|
||||
else \
|
||||
debug("%s(%p, %p, [%i]) = %li", __func__, \
|
||||
lineptr, n, fd, (long int)ret); \
|
||||
return ret; \
|
||||
END_STREAM(stream); \
|
||||
break; \
|
||||
} while(0)
|
||||
|
||||
#if defined HAVE_GETLINE
|
||||
@ -744,6 +794,7 @@ char *NEW(fgetln)(FILE *stream, size_t *len)
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
|
||||
return ORIG(fgetln)(stream, len);
|
||||
|
||||
BEGIN_STREAM(stream);
|
||||
#if defined REFILL_ONLY_STDIO /* Don't fuzz or seek if we have __srefill() */
|
||||
_zz_lock(fd);
|
||||
ret = ORIG(fgetln)(stream, len);
|
||||
@ -778,10 +829,17 @@ char *NEW(fgetln)(FILE *stream, size_t *len)
|
||||
#endif
|
||||
|
||||
debug("%s([%i], &%li) = %p", __func__, fd, (long int)*len, ret);
|
||||
END_STREAM(stream);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined HAVE___FILBUF || defined HAVE___SRGET
|
||||
# define REFILL_RETURNS_INT 1
|
||||
#elif defined HAVE___UFLOW
|
||||
# define REFILL_RETURNS_INT 0
|
||||
#endif
|
||||
|
||||
#define REFILL(fn, fn_advances) \
|
||||
do \
|
||||
{ \
|
||||
@ -792,6 +850,7 @@ char *NEW(fgetln)(FILE *stream, size_t *len)
|
||||
fd = fileno(fp); \
|
||||
if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
|
||||
return ORIG(fn)(fp); \
|
||||
BEGIN_STREAM(fp); \
|
||||
pos = _zz_getpos(fd); \
|
||||
_zz_lock(fd); \
|
||||
ret = ORIG(fn)(fp); \
|
||||
@ -804,28 +863,35 @@ char *NEW(fgetln)(FILE *stream, size_t *len)
|
||||
{ \
|
||||
uint8_t ch = (uint8_t)(unsigned int)ret; \
|
||||
if(newpos != -1) \
|
||||
_zz_setpos(fd, newpos - fp->FILE_CNT - 1); \
|
||||
_zz_setpos(fd, newpos - get_stream_cnt(fp) - 1); \
|
||||
already_fuzzed = _zz_getfuzzed(fd); \
|
||||
_zz_fuzz(fd, &ch, 1); \
|
||||
ret = fp->FILE_PTR[-1] = ch; \
|
||||
_zz_setfuzzed(fd, fp->FILE_CNT + 1); \
|
||||
ret = get_stream_ptr(fp)[-1] = ch; \
|
||||
_zz_setfuzzed(fd, get_stream_cnt(fp) + 1); \
|
||||
_zz_addpos(fd, 1); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
_zz_setfuzzed(fd, fp->FILE_CNT); \
|
||||
_zz_setfuzzed(fd, get_stream_cnt(fp)); \
|
||||
if(newpos != -1) \
|
||||
_zz_setpos(fd, newpos - fp->FILE_CNT); \
|
||||
_zz_setpos(fd, newpos - get_stream_cnt(fp)); \
|
||||
} \
|
||||
if(fp->FILE_CNT > already_fuzzed) \
|
||||
if(get_stream_cnt(fp) > already_fuzzed) \
|
||||
{ \
|
||||
_zz_addpos(fd, already_fuzzed); \
|
||||
_zz_fuzz(fd, fp->FILE_PTR, fp->FILE_CNT - already_fuzzed); \
|
||||
_zz_fuzz(fd, get_stream_ptr(fp), \
|
||||
get_stream_cnt(fp) - already_fuzzed); \
|
||||
} \
|
||||
_zz_addpos(fd, fp->FILE_CNT - already_fuzzed); \
|
||||
_zz_addpos(fd, get_stream_cnt(fp) - already_fuzzed); \
|
||||
} \
|
||||
_zz_setpos(fd, pos); /* FIXME: do we always need to do this? */ \
|
||||
debug("%s([%i]) = %i", __func__, fd, ret); \
|
||||
if (REFILL_RETURNS_INT) \
|
||||
debug("%s([%i]) = %i", __func__, fd, ret); \
|
||||
else if (ret == EOF) \
|
||||
debug("%s([%i]) = EOF", __func__, fd, ret); \
|
||||
else \
|
||||
debug("%s([%i]) = '%c'", __func__, fd, ret); \
|
||||
END_STREAM(fp); \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
@ -850,3 +916,10 @@ int NEW(__filbuf)(FILE *fp)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined HAVE___UFLOW
|
||||
int NEW(__uflow)(FILE *fp)
|
||||
{
|
||||
int ret; REFILL(__uflow, 1); return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user