On Thu, Dec 13, 2018 at 11:01:10AM -0700, Todd C. Miller wrote:
> Here's a diff that fakes up a FILE like we do in other parts of
> stdio for unbuffered I/O.  This lets us call __srefill() normally.
> If __srefill() returns an error, copy the flags back to the real
> FILE *.

Your patch fixes the mercurial crashes. Many thanks.


> 
>  - todd
> 
> Index: lib/libc/stdio/fread.c
> ===================================================================
> RCS file: /cvs/src/lib/libc/stdio/fread.c,v
> retrieving revision 1.15
> diff -u -p -u -r1.15 fread.c
> --- lib/libc/stdio/fread.c    21 Sep 2016 04:38:56 -0000      1.15
> +++ lib/libc/stdio/fread.c    13 Dec 2018 17:24:34 -0000
> @@ -69,18 +69,39 @@ fread(void *buf, size_t size, size_t cou
>       total = resid;
>       p = buf;
>  
> +     /*
> +      * If we're unbuffered we know that the buffer in fp is empty so
> +      * we can read directly into buf.  This is much faster than a
> +      * series of one byte reads into fp->_nbuf.
> +      */
>       if ((fp->_flags & __SNBF) != 0) {
> -             /*
> -              * We know if we're unbuffered that our buffer is empty, so
> -              * we can just read directly. This is much faster than the
> -              * loop below which will perform a series of one byte reads.
> -              */
> -             while (resid > 0 && (r = (*fp->_read)(fp->_cookie, p, resid)) > 
> 0) {
> -                     p += r;
> -                     resid -= r;
> +             FILE fake;
> +             struct __sfileext fakeext;
> +
> +             _FILEEXT_SETUP(&fake, &fakeext);
> +             /* copy the important variables */
> +             fake._flags = fp->_flags;
> +             fake._file = fp->_file;
> +             fake._cookie = fp->_cookie;
> +             fake._read = fp->_read;
> +
> +             /* set up the buffer */
> +             fake._bf._base = buf;
> +             fake._bf._size = total;
> +             fake._lbfsize = 0;      /* not line buffered */
> +
> +             while (resid > 0) {
> +                     if (__srefill(&fake)) {
> +                             /* no more input: return partial result */
> +                             count = (total - resid) / size;
> +                             fp->_flags |= (fake._flags & (__SERR|__SEOF));
> +                             break;
> +                     }
> +                     fake._p += fake._r;
> +                     resid -= fake._r;
>               }
>               FUNLOCKFILE(fp);
> -             return ((total - resid) / size);
> +             return (count);
>       }
>  
>       while (resid > (r = fp->_r)) {
> 

-- 
Juan Francisco Cantero Hurtado http://juanfra.info

Reply via email to