Changeset 4117 for zzuf/trunk


Ignore:
Timestamp:
Dec 12, 2009, 11:20:22 PM (11 years ago)
Author:
Sam Hocevar
Message:

Refactor the stream diversions.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • zzuf/trunk/src/libzzuf/lib-stream.c

    r4114 r4117  
    214214/*
    215215 * fopen, fopen64 etc.
    216  */
    217 
    218 #if defined HAVE_DARWIN_STDIO /* Fuzz fp if we have __srefill() */
    219 #   define FOPEN_FUZZ() \
    220     _zz_fuzz(fd, get_stream_ptr(ret), get_stream_cnt(ret))
    221 #else
    222 #   define FOPEN_FUZZ()
    223 #endif
     216 * freopen, freopen64 etc.
     217 *
     218 * Strategy: we call the original function, register the new file descriptor
     219 * and immediately fuzz whatever's preloaded in the stream structure.
     220 */
    224221
    225222#define FOPEN(myfopen) \
     
    236233            int fd = fileno(ret); \
    237234            _zz_register(fd); \
     235            _zz_fuzz(fd, get_stream_ptr(ret), get_stream_cnt(ret)); \
    238236            debug("%s(\"%s\", \"%s\") = [%i]", __func__, path, mode, fd); \
    239237            debug_stream("new", ret); \
    240             FOPEN_FUZZ(); \
    241238        } \
    242239    } while(0)
    243 
    244 FILE *NEW(fopen)(const char *path, const char *mode)
    245 {
    246     FILE *ret; FOPEN(fopen); return ret;
    247 }
    248 
    249 #if defined HAVE_FOPEN64
    250 FILE *NEW(fopen64)(const char *path, const char *mode)
    251 {
    252     FILE *ret; FOPEN(fopen64); return ret;
    253 }
    254 #endif
    255 
    256 #if defined HAVE___FOPEN64
    257 FILE *NEW(__fopen64)(const char *path, const char *mode)
    258 {
    259     FILE *ret; FOPEN(__fopen64); return ret;
    260 }
    261 #endif
    262 
    263 /*
    264  * freopen, freopen64 etc.
    265  */
    266240
    267241#define FREOPEN(myfreopen) \
     
    282256            fd1 = fileno(ret); \
    283257            _zz_register(fd1); \
     258            _zz_fuzz(fd1, get_stream_ptr(ret), get_stream_cnt(ret)); \
    284259            disp = 1; \
    285260        } \
     
    289264    } while(0)
    290265
     266FILE *NEW(fopen)(const char *path, const char *mode)
     267{
     268    FILE *ret; FOPEN(fopen); return ret;
     269}
     270
     271#if defined HAVE_FOPEN64
     272FILE *NEW(fopen64)(const char *path, const char *mode)
     273{
     274    FILE *ret; FOPEN(fopen64); return ret;
     275}
     276#endif
     277
     278#if defined HAVE___FOPEN64
     279FILE *NEW(__fopen64)(const char *path, const char *mode)
     280{
     281    FILE *ret; FOPEN(__fopen64); return ret;
     282}
     283#endif
     284
    291285FILE *NEW(freopen)(const char *path, const char *mode, FILE *stream)
    292286{
     
    310304/*
    311305 * fseek, fseeko etc.
    312  */
    313 
    314 #if defined HAVE_DARWIN_STDIO /* Don't fuzz or seek if we have __srefill() */
    315 #   define FSEEK_FUZZ()
    316 #else
    317 #   define FSEEK_FUZZ() \
    318         if(ret == 0) \
    319         { \
    320             /* FIXME: check what happens when fseek()ing a pipe */ \
    321             switch(whence) \
    322             { \
    323                 case SEEK_END: \
    324                     offset = MYFTELL(stream); \
    325                     /* fall through */ \
    326                 case SEEK_SET: \
    327                     _zz_setpos(fd, offset); \
    328                     break; \
    329                 case SEEK_CUR: \
    330                     _zz_addpos(fd, offset); \
    331                     break; \
    332             } \
    333         }
    334 #endif
     306 * fsetpos64, __fsetpos64
     307 * rewind
     308 *
     309 * Strategy: we store the previous file position and internal buffer
     310 * status, then call the original function. If the new file position
     311 * lies outside the previous internal buffer, it means the buffer has
     312 * been invalidated, so we fuzz whatever's preloaded in it.
     313 */
    335314
    336315#define FSEEK(myfseek) \
    337316    do \
    338317    { \
     318        int64_t oldpos, newpos; \
     319        int oldoff, oldcnt; \
    339320        int fd; \
    340321        LOADSYM(myfseek); \
     
    343324            return ORIG(myfseek)(stream, offset, whence); \
    344325        debug_stream("old", stream); \
     326        /* FIXME: ftell() will return -1 on a pipe such as stdin */ \
     327        oldpos = MYFTELL(stream); \
     328        oldoff = get_stream_off(stream); \
     329        oldcnt = get_stream_cnt(stream); \
    345330        _zz_lock(fd); \
    346331        ret = ORIG(myfseek)(stream, offset, whence); \
    347332        _zz_unlock(fd); \
     333        newpos = MYFTELL(stream); \
     334        if (newpos > oldpos + oldcnt || newpos < oldpos - oldoff) \
     335        { \
     336            _zz_setpos(fd, newpos - get_stream_off(stream)); \
     337            _zz_fuzz(fd, get_stream_ptr(stream) - get_stream_off(stream), \
     338                         get_stream_cnt(stream) + get_stream_off(stream)); \
     339        } \
     340        _zz_setpos(fd, newpos); \
    348341        debug("%s([%i], %lli, %i) = %i", __func__, \
    349342              fd, (long long int)offset, whence, ret); \
    350         FSEEK_FUZZ() \
    351343        debug_stream("new", stream); \
    352344    } while(0)
    353 
    354 int NEW(fseek)(FILE *stream, long offset, int whence)
    355 {
    356     int ret; FSEEK(fseek); return ret;
    357 }
    358 
    359 #if defined HAVE_FSEEKO
    360 int NEW(fseeko)(FILE *stream, off_t offset, int whence)
    361 {
    362     int ret; FSEEK(fseeko); return ret;
    363 }
    364 #endif
    365 
    366 #if defined HAVE_FSEEKO64
    367 int NEW(fseeko64)(FILE *stream, off64_t offset, int whence)
    368 {
    369     int ret; FSEEK(fseeko64); return ret;
    370 }
    371 #endif
    372 
    373 #if defined HAVE___FSEEKO64
    374 int NEW(__fseeko64)(FILE *stream, off64_t offset, int whence)
    375 {
    376     int ret; FSEEK(__fseeko64); return ret;
    377 }
    378 #endif
    379 
    380 /*
    381  * fsetpos64, __fsetpos64
    382  */
    383345
    384346#define FSETPOS(myfsetpos) \
    385347    do \
    386348    { \
     349        int64_t oldpos, newpos; \
     350        int oldoff, oldcnt; \
    387351        int fd; \
    388352        LOADSYM(myfsetpos); \
     
    391355            return ORIG(myfsetpos)(stream, pos); \
    392356        debug_stream("old", stream); \
     357        /* FIXME: ftell() will return -1 on a pipe such as stdin */ \
     358        oldpos = MYFTELL(stream); \
     359        oldoff = get_stream_off(stream); \
     360        oldcnt = get_stream_cnt(stream); \
    393361        _zz_lock(fd); \
    394362        ret = ORIG(myfsetpos)(stream, pos); \
    395363        _zz_unlock(fd); \
     364        newpos = MYFTELL(stream); \
     365        if (newpos > oldpos + oldcnt || newpos < oldpos - oldoff) \
     366        { \
     367            _zz_setpos(fd, newpos - get_stream_off(stream)); \
     368            _zz_fuzz(fd, get_stream_ptr(stream) - get_stream_off(stream), \
     369                         get_stream_cnt(stream) + get_stream_off(stream)); \
     370        } \
     371        _zz_setpos(fd, (int64_t)FPOS_CAST(*pos)); \
    396372        debug("%s([%i], %lli) = %i", __func__, \
    397373              fd, (long long int)FPOS_CAST(*pos), ret); \
    398         _zz_setpos(fd, (int64_t)FPOS_CAST(*pos)); \
    399374        debug_stream("new", stream); \
    400375    } \
    401376    while(0)
    402377
     378#define REWIND(myrewind) \
     379    do \
     380    { \
     381        int64_t oldpos, newpos; \
     382        int oldoff, oldcnt; \
     383        int fd; \
     384        LOADSYM(rewind); \
     385        fd = fileno(stream); \
     386        if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
     387            return ORIG(rewind)(stream); \
     388        debug_stream("old", stream); \
     389        /* FIXME: ftell() will return -1 on a pipe such as stdin */ \
     390        oldpos = MYFTELL(stream); \
     391        oldoff = get_stream_off(stream); \
     392        oldcnt = get_stream_cnt(stream); \
     393        _zz_lock(fd); \
     394        ORIG(rewind)(stream); \
     395        _zz_unlock(fd); \
     396        newpos = MYFTELL(stream); \
     397        if (newpos > oldpos + oldcnt || newpos < oldpos - oldoff) \
     398        { \
     399            _zz_setpos(fd, newpos - get_stream_off(stream)); \
     400            _zz_fuzz(fd, get_stream_ptr(stream) - get_stream_off(stream), \
     401                         get_stream_cnt(stream) + get_stream_off(stream)); \
     402        } \
     403        _zz_setpos(fd, newpos); \
     404        debug("%s([%i])", __func__, fd); \
     405        debug_stream("new", stream); \
     406    } while(0)
     407
     408int NEW(fseek)(FILE *stream, long offset, int whence)
     409{
     410    int ret; FSEEK(fseek); return ret;
     411}
     412
     413#if defined HAVE_FSEEKO
     414int NEW(fseeko)(FILE *stream, off_t offset, int whence)
     415{
     416    int ret; FSEEK(fseeko); return ret;
     417}
     418#endif
     419
     420#if defined HAVE_FSEEKO64
     421int NEW(fseeko64)(FILE *stream, off64_t offset, int whence)
     422{
     423    int ret; FSEEK(fseeko64); return ret;
     424}
     425#endif
     426
     427#if defined HAVE___FSEEKO64
     428int NEW(__fseeko64)(FILE *stream, off64_t offset, int whence)
     429{
     430    int ret; FSEEK(__fseeko64); return ret;
     431}
     432#endif
     433
    403434#if defined HAVE_FSETPOS64
    404435int NEW(fsetpos64)(FILE *stream, const fpos64_t *pos)
     
    415446#endif
    416447
    417 /*
    418  * rewind
    419  */
    420 
    421448void NEW(rewind)(FILE *stream)
    422449{
    423     int fd;
    424 
    425     LOADSYM(rewind);
    426     fd = fileno(stream);
    427     if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd))
    428     {
    429         ORIG(rewind)(stream);
    430         return;
    431     }
    432 
    433     _zz_lock(fd);
    434     ORIG(rewind)(stream);
    435     _zz_unlock(fd);
    436     debug("%s([%i])", __func__, fd);
    437 
    438 #if defined HAVE_DARWIN_STDIO /* Don't fuzz or seek if we have __srefill() */
    439 #else
    440     /* FIXME: check what happens when rewind()ing a pipe */
    441     _zz_setpos(fd, 0);
    442 #endif
     450    REWIND(rewind);
    443451}
    444452
    445453/*
    446454 * fread, fread_unlocked
    447  */
    448 
    449 /* Compute how many bytes from the stream were already fuzzed by __filbuf,
    450  * __srget or __uflow, and store it in already_fuzzed. If these functions
    451  * are not available, do nothing. */
    452 #if defined HAVE_BSD_STDIO
    453 #   define FREAD_PREFUZZ(fd, oldpos) \
     455 *
     456 * Strategy: we store the previous file position and internal buffer
     457 * status, then call the original function. If the new file position
     458 * lies outside the previous internal buffer, it means the buffer has
     459 * been invalidated, so we fuzz whatever's preloaded in it.
     460 */
     461
     462#define FREAD(myfread) /* NEW */ \
    454463    do \
    455464    { \
    456         int64_t tmp = _zz_getpos(fd); \
    457         _zz_setpos(fd, oldpos); \
    458         already_fuzzed = _zz_getfuzzed(fd); \
    459         _zz_setpos(fd, tmp); \
    460     } \
    461     while(0)
    462 #else
    463 #   define FREAD_PREFUZZ(fd, oldpos) do {} while(0)
    464 #endif
    465 
    466 /* Fuzz the data returned by fread(). If a __fillbuf mechanism already
    467  * fuzzed some of our data, we skip the relevant amount of bytes. If we
    468  * have __srefill, we just do nothing because that function is the only
    469  * one that actually fuzzes things. */
    470 #if defined HAVE_DARWIN_STDIO
    471 #   define FREAD_FUZZ(fd, oldpos) \
    472     do \
    473     { \
    474         debug("%s(%p, %li, %li, [%i]) = %li", __func__, ptr, \
    475               (long int)size, (long int)nmemb, fd, (long int)ret); \
    476     } while(0)
    477 #else
    478 #   define FREAD_FUZZ(fd, oldpos) \
    479     do \
    480     { \
    481         int64_t newpos = MYFTELL(stream); \
    482         /* XXX: the number of bytes read is not ret * size, because \
    483          * a partial read may have advanced the stream pointer. However, \
    484          * when reading from a pipe ftell() will return 0, and ret * size \
    485          * is then better than nothing. */ \
    486         if(newpos <= 0) \
    487         { \
    488             oldpos = _zz_getpos(fd); \
    489             newpos = oldpos + ret * size; \
    490         } \
    491         if(newpos != oldpos) \
    492         { \
    493             char *b = ptr; \
    494             /* Skip bytes that were already fuzzed by __filbuf or __srget */ \
    495             if(newpos > oldpos + already_fuzzed) \
    496             { \
    497                 _zz_setpos(fd, oldpos + already_fuzzed); \
    498                 _zz_fuzz(fd, ptr, newpos - oldpos - already_fuzzed); \
    499                 /* FIXME: we need to fuzz the extra bytes that may have been \
    500                  * read by the fread call we just made, or subsequent calls \
    501                  * to getc_unlocked may miss them. */ \
    502                 _zz_setpos(fd, newpos); \
    503                 _zz_fuzz(fd, get_stream_ptr(stream), get_stream_cnt(stream)); \
    504                 _zz_setfuzzed(fd, get_stream_cnt(stream)); \
    505                 /* FIXME: *AND* we need to fuzz the buffer before the current \
    506                  * position, in case fseek() causes us to rewind. */ \
    507             } \
    508             _zz_setpos(fd, newpos); \
    509             if(newpos >= oldpos + 4) \
    510                 debug("%s(%p, %li, %li, [%i]) = %li \"%c%c%c%c...", __func__, \
    511                       ptr, (long int)size, (long int)nmemb, fd, \
    512                       (long int)ret, b[0], b[1], b[2], b[3]); \
    513             else \
    514                 debug("%s(%p, %li, %li, [%i]) = %li \"%c...", __func__, ptr, \
    515                       (long int)size, (long int)nmemb, fd, \
    516                       (long int)ret, b[0]); \
    517         } \
    518         else \
    519             debug("%s(%p, %li, %li, [%i]) = %li", __func__, ptr, \
    520                   (long int)size, (long int)nmemb, fd, (long int)ret); \
    521     } while(0)
    522 #endif
    523 
    524 #define FREAD(myfread) \
    525     do \
    526     { \
    527         int64_t oldpos; \
    528         int fd, already_fuzzed = 0; \
     465        int64_t oldpos, newpos; \
     466        uint8_t *b = ptr;\
     467        int oldoff, oldcnt; \
     468        int fd; \
    529469        LOADSYM(myfread); \
    530470        fd = fileno(stream); \
     
    532472            return ORIG(myfread)(ptr, size, nmemb, stream); \
    533473        debug_stream("old", stream); \
     474        /* FIXME: ftell() will return -1 on a pipe such as stdin */ \
    534475        oldpos = MYFTELL(stream); \
    535         _zz_setpos(fd, oldpos); \
     476        oldoff = get_stream_off(stream); \
     477        oldcnt = get_stream_cnt(stream); \
    536478        _zz_lock(fd); \
    537479        ret = ORIG(myfread)(ptr, size, nmemb, stream); \
    538480        _zz_unlock(fd); \
    539         FREAD_PREFUZZ(fd, oldpos); \
    540         FREAD_FUZZ(fd, oldpos); \
     481        newpos = MYFTELL(stream); \
     482        if (newpos > oldpos + oldcnt) \
     483        { \
     484            /* Fuzz returned data that wasn't in the old internal buffer */ \
     485            _zz_setpos(fd, oldpos + oldcnt); \
     486            _zz_fuzz(fd, b + oldcnt, newpos - oldpos - oldcnt); \
     487            /* Fuzz the internal stream buffer */ \
     488            _zz_setpos(fd, newpos - get_stream_off(stream)); \
     489            _zz_fuzz(fd, get_stream_ptr(stream) - get_stream_off(stream), \
     490                         get_stream_cnt(stream) + get_stream_off(stream)); \
     491        } \
     492        _zz_setpos(fd, newpos); \
     493        if (newpos > oldpos + 4) \
     494            debug("%s(%p, %li, %li, [%i]) = %li \"%c%c%c%c...", __func__, \
     495                  ptr, (long int)size, (long int)nmemb, fd, \
     496                  (long int)ret, b[0], b[1], b[2], b[3]); \
     497        else if (newpos > oldpos) \
     498            debug("%s(%p, %li, %li, [%i]) = %li \"%c...", __func__, ptr, \
     499                  (long int)size, (long int)nmemb, fd, \
     500                  (long int)ret, b[0]); \
     501        else \
     502            debug("%s(%p, %li, %li, [%i]) = %li", __func__, ptr, \
     503                  (long int)size, (long int)nmemb, fd, (long int)ret); \
    541504        debug_stream("new", stream); \
    542505    } while(0)
     
    557520/*
    558521 * getc, getchar, fgetc etc.
    559  */
    560 
    561 #if defined HAVE_BSD_STDIO
    562 #   define FGETC_PREFUZZ already_fuzzed = _zz_getfuzzed(fd);
    563 #else
    564 #   define FGETC_PREFUZZ
    565 #endif
    566 
    567 #if defined HAVE_DARWIN_STDIO /* Don't fuzz or seek if we have __srefill() */
    568 #   define FGETC_FUZZ
    569 #else
    570 #   define FGETC_FUZZ \
    571         if(ret != EOF) \
    572         { \
    573             uint8_t ch = ret; \
    574             if(already_fuzzed <= 0) \
    575                _zz_fuzz(fd, &ch, 1); \
    576             _zz_addpos(fd, 1); \
    577             ret = ch; \
    578         }
    579 #endif
     522 *
     523 * Strategy: we store the previous file position and internal buffer
     524 * status, then call the original function. If the new file position
     525 * lies outside the previous internal buffer, it means the buffer has
     526 * been invalidated, so we fuzz whatever's preloaded in it.
     527 */
    580528
    581529#define FGETC(myfgetc, s, arg) \
    582530    do { \
    583         int fd, already_fuzzed = 0; \
     531        int64_t oldpos, newpos; \
     532        int oldoff, oldcnt; \
     533        int fd; \
    584534        LOADSYM(myfgetc); \
    585535        fd = fileno(s); \
     
    587537            return ORIG(myfgetc)(arg); \
    588538        debug_stream("old", s); \
    589         _zz_setpos(fd, MYFTELL(s)); \
     539        oldpos = MYFTELL(s); \
     540        oldoff = get_stream_off(s); \
     541        oldcnt = get_stream_cnt(s); \
    590542        _zz_lock(fd); \
    591543        ret = ORIG(myfgetc)(arg); \
    592544        _zz_unlock(fd); \
    593         FGETC_PREFUZZ \
    594         FGETC_FUZZ \
     545        newpos = MYFTELL(s); \
     546        if (oldcnt == 0 && ret != EOF) \
     547        { \
     548            /* Fuzz returned data that wasn't in the old internal buffer */ \
     549            uint8_t ch = ret; \
     550            _zz_setpos(fd, oldpos); \
     551            _zz_fuzz(fd, &ch, 1); \
     552            ret = ch; \
     553        } \
     554        if (newpos > oldpos + oldcnt) \
     555        { \
     556            /* Fuzz the internal stream buffer */ \
     557            _zz_setpos(fd, newpos - get_stream_off(s)); \
     558            _zz_fuzz(fd, get_stream_ptr(s) - get_stream_off(s), \
     559                         get_stream_cnt(s) + get_stream_off(s)); \
     560        } \
     561        _zz_setpos(fd, newpos); \
    595562        if(ret == EOF) \
    596563            debug("%s([%i]) = EOF", __func__, fd); \
     
    652619 */
    653620
    654 #if defined HAVE_DARWIN_STDIO /* Don't fuzz or seek if we have __srefill() */
    655 #   define FGETS_FUZZ(myfgets, myfgetc) \
    656         _zz_lock(fd); \
    657         ret = ORIG(myfgets)(s, size, stream); \
    658         _zz_unlock(fd);
    659 #else
    660 #   define FGETS_FUZZ(myfgets, myfgetc) \
    661         if(size <= 0) \
    662             ret = NULL; \
    663         else if(size == 1) \
    664             s[0] = '\0'; \
    665         else \
    666         { \
    667             int i; \
    668             for(i = 0; i < size - 1; i++) \
    669             { \
    670                 int ch; \
    671                 _zz_lock(fd); \
    672                 ch = ORIG(myfgetc)(stream); \
    673                 _zz_unlock(fd); \
    674                 if(ch == EOF) \
    675                 { \
    676                     s[i] = '\0'; \
    677                     if(!i) \
    678                         ret = NULL; \
    679                     break; \
    680                 } \
    681                 s[i] = (char)(unsigned char)ch; \
    682                 _zz_fuzz(fd, (uint8_t *)s + i, 1); /* rather inefficient */ \
    683                 _zz_addpos(fd, 1); \
    684                 if(s[i] == '\n') \
    685                 { \
    686                     s[i + 1] = '\0'; \
    687                     break; \
    688                 } \
    689             } \
    690         }
    691 #endif
    692 
    693621#define FGETS(myfgets, myfgetc) \
    694622    do \
    695623    { \
     624        int64_t oldpos, newpos; \
     625        int oldoff, oldcnt; \
    696626        int fd; \
    697627        ret = s; \
     
    701631        if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
    702632            return ORIG(myfgets)(s, size, stream); \
    703         debug_stream("old", s); \
    704         _zz_setpos(fd, MYFTELL(stream)); \
    705         FGETS_FUZZ(myfgets, myfgetc) \
     633        debug_stream("old", stream); \
     634        oldpos = MYFTELL(stream); \
     635        oldoff = get_stream_off(stream); \
     636        oldcnt = get_stream_cnt(stream); \
     637        newpos = oldpos; \
     638        if(size <= 0) \
     639            ret = NULL; \
     640        else if(size == 1) \
     641            s[0] = '\0'; \
     642        else \
     643        { \
     644            int i; \
     645            for(i = 0; i < size - 1; i++) \
     646            { \
     647                int chr; \
     648                _zz_lock(fd); \
     649                chr = ORIG(myfgetc)(stream); \
     650                _zz_unlock(fd); \
     651                newpos = oldpos + 1; \
     652                if (oldcnt == 0 && chr != EOF) \
     653                { \
     654                    /* Fuzz returned data that wasn't in the old buffer */ \
     655                    uint8_t ch = chr; \
     656                    _zz_setpos(fd, oldpos); \
     657                    _zz_fuzz(fd, &ch, 1); \
     658                    chr = ch; \
     659                } \
     660                if (newpos > oldpos + oldcnt) \
     661                { \
     662                    /* Fuzz the internal stream buffer, if necessary */ \
     663                    _zz_setpos(fd, newpos - get_stream_off(stream)); \
     664                    _zz_fuzz(fd, get_stream_ptr(stream) - get_stream_off(stream), \
     665                                 get_stream_cnt(stream) + get_stream_off(stream)); \
     666                } \
     667                oldpos = newpos; \
     668                oldoff = get_stream_off(stream); \
     669                oldcnt = get_stream_cnt(stream); \
     670                if(chr == EOF) \
     671                { \
     672                    s[i] = '\0'; \
     673                    if(!i) \
     674                        ret = NULL; \
     675                    break; \
     676                } \
     677                s[i] = (char)(unsigned char)chr; \
     678                if(s[i] == '\n') \
     679                { \
     680                    s[i + 1] = '\0'; \
     681                    break; \
     682                } \
     683            } \
     684        } \
     685        _zz_setpos(fd, newpos); \
    706686        debug("%s(%p, %i, [%i]) = %p", __func__, s, size, fd, ret); \
    707         debug_stream("new", s); \
     687        debug_stream("new", stream); \
    708688    } while(0)
    709689
     
    726706int NEW(ungetc)(int c, FILE *stream)
    727707{
    728     int ret, fd;
     708    int oldpos, ret, fd;
    729709
    730710    LOADSYM(ungetc);
     
    734714
    735715    debug_stream("old", stream);
    736     _zz_setpos(fd, MYFTELL(stream));
     716    oldpos = MYFTELL(stream);
    737717    _zz_lock(fd);
    738718    ret = ORIG(ungetc)(c, stream);
    739719    _zz_unlock(fd);
    740 
    741     if(ret != EOF)
    742     {
    743         struct fuzz *fuzz = _zz_getfuzz(fd);
    744         fuzz->uflag = 1;
    745         fuzz->upos = _zz_getpos(fd) - 1;
    746         fuzz->uchar = c;
    747 #if defined HAVE_DARWIN_STDIO /* Don't fuzz or seek if we have __srefill() */
    748 #else
    749         _zz_addpos(fd, -1);
    750 #endif
    751     }
     720    _zz_setpos(fd, oldpos - 1);
    752721
    753722    if(ret == EOF)
     
    788757#define GETDELIM(mygetdelim, delim, need_delim) \
    789758    do { \
     759        int64_t oldpos, newpos; \
    790760        char *line; \
    791761        ssize_t done, size; \
    792         int fd, already_fuzzed = 0, finished = 0; \
     762        int oldoff, oldcnt; \
     763        int fd, finished = 0; \
    793764        LOADSYM(mygetdelim); \
    794765        LOADSYM(getdelim); \
     
    796767        fd = fileno(stream); \
    797768        if(!_zz_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) \
    798         { \
    799             ret = ORIG(getdelim)(lineptr, n, delim, stream); \
    800             break; \
    801         } \
     769            return ORIG(getdelim)(lineptr, n, delim, stream); \
    802770        debug_stream("old", stream); \
    803         _zz_setpos(fd, MYFTELL(stream)); \
     771        oldpos = MYFTELL(stream); \
     772        oldoff = get_stream_off(stream); \
     773        oldcnt = get_stream_cnt(stream); \
     774        newpos = oldpos; \
    804775        line = *lineptr; \
    805776        size = line ? *n : 0; \
     
    807778        for(;;) \
    808779        { \
    809             int ch; \
     780            int chr; \
    810781            if(done >= size) /* highly inefficient but I don't care */ \
    811782                line = realloc(line, size = done + 1); \
     
    818789            } \
    819790            _zz_lock(fd); \
    820             ch = ORIG(fgetc)(stream); \
     791            chr = ORIG(fgetc)(stream); \
    821792            _zz_unlock(fd); \
    822             if(ch == EOF) \
     793            newpos = oldpos + 1; \
     794            if (oldcnt == 0 && chr != EOF) \
     795            { \
     796                /* Fuzz returned data that wasn't in the old buffer */ \
     797                uint8_t ch = chr; \
     798                _zz_setpos(fd, oldpos); \
     799                _zz_fuzz(fd, &ch, 1); \
     800                chr = ch; \
     801            } \
     802            if (newpos > oldpos + oldcnt) \
     803            { \
     804                /* Fuzz the internal stream buffer, if necessary */ \
     805                _zz_setpos(fd, newpos - get_stream_off(stream)); \
     806                _zz_fuzz(fd, get_stream_ptr(stream) - get_stream_off(stream), \
     807                             get_stream_cnt(stream) + get_stream_off(stream)); \
     808            } \
     809            oldpos = newpos; \
     810            oldoff = get_stream_off(stream); \
     811            oldcnt = get_stream_cnt(stream); \
     812            if(chr == EOF) \
    823813            { \
    824814                finished = 1; \
     
    827817            else \
    828818            { \
    829                 unsigned char c = ch; \
    830                 _zz_fuzz(fd, &c, 1); /* even more inefficient */ \
     819                unsigned char c = chr; \
    831820                line[done++] = c; \
    832                 _zz_addpos(fd, 1); \
    833821                if(c == delim) \
    834822                { \
     
    838826            } \
    839827        } \
     828        _zz_setpos(fd, newpos); \
    840829        if(need_delim) \
    841830            debug("%s(%p, %p, '%c', [%i]) = %li", __func__, \
     
    876865char *NEW(fgetln)(FILE *stream, size_t *len)
    877866{
     867    int64_t oldpos, newpos;
    878868    char *ret;
    879 #if defined HAVE_DARWIN_STDIO /* Don't fuzz or seek if we have __srefill() */
    880 #else
    881869    struct fuzz *fuzz;
    882870    size_t i, size;
    883 #endif
    884     int fd;
     871    int oldoff, oldcnt, fd;
    885872
    886873    LOADSYM(fgetln);
     
    891878
    892879    debug_stream("old", stream);
    893 #if defined HAVE_DARWIN_STDIO /* Don't fuzz or seek if we have __srefill() */
    894     _zz_lock(fd);
    895     ret = ORIG(fgetln)(stream, len);
    896     _zz_unlock(fd);
    897 #else
    898     _zz_setpos(fd, MYFTELL(stream));
     880    oldpos = MYFTELL(stream);
     881    oldoff = get_stream_off(stream);
     882    oldcnt = get_stream_cnt(stream);
     883    newpos = oldpos;
     884
    899885    fuzz = _zz_getfuzz(fd);
    900886
    901887    for(i = size = 0; ; /* i is incremented below */)
    902888    {
    903         int ch;
     889        int chr;
    904890
    905891        _zz_lock(fd);
    906         ch = ORIG(fgetc)(stream);
     892        chr = ORIG(fgetc)(stream);
    907893        _zz_unlock(fd);
    908894
    909         if(ch == EOF)
     895        newpos = oldpos + 1;
     896        if (oldcnt == 0 && chr != EOF)
     897        {
     898            /* Fuzz returned data that wasn't in the old buffer */
     899            uint8_t ch = chr;
     900            _zz_setpos(fd, oldpos);
     901            _zz_fuzz(fd, &ch, 1);
     902            chr = ch;
     903        }
     904        if (newpos > oldpos + oldcnt)
     905        {
     906            /* Fuzz the internal stream buffer, if necessary */
     907            _zz_setpos(fd, newpos - get_stream_off(stream));
     908            _zz_fuzz(fd, get_stream_ptr(stream) - get_stream_off(stream),
     909                         get_stream_cnt(stream) + get_stream_off(stream));
     910        }
     911        oldpos = newpos;
     912        oldoff = get_stream_off(stream);
     913        oldcnt = get_stream_cnt(stream);
     914
     915        if(chr == EOF)
    910916            break;
    911917
     
    913919            fuzz->tmp = realloc(fuzz->tmp, (size += 80));
    914920
    915         fuzz->tmp[i] = (char)(unsigned char)ch;
    916         _zz_fuzz(fd, (uint8_t *)fuzz->tmp + i, 1); /* rather inefficient */
    917         _zz_addpos(fd, 1);
     921        fuzz->tmp[i] = (char)(unsigned char)chr;
    918922
    919923        if(fuzz->tmp[i++] == '\n')
     
    923927    *len = i;
    924928    ret = fuzz->tmp;
    925 #endif
    926929
    927930    debug("%s([%i], &%li) = %p", __func__, fd, (long int)*len, ret);
     
    989992            debug("%s([%i]) = %i", __func__, fd, ret); \
    990993        else if (ret == EOF) \
    991             debug("%s([%i]) = EOF", __func__, fd, ret); \
     994            debug("%s([%i]) = EOF", __func__, fd); \
    992995        else \
    993996            debug("%s([%i]) = '%c'", __func__, fd, ret); \
Note: See TracChangeset for help on using the changeset viewer.