1.3.3-2: fseek fails on multiples of 1024 (binary mode)

J. Johnston jjohnstn@cygnus.com
Tue Oct 23 15:55:00 GMT 2001

Christopher Faylor wrote:
> Again, these observations should go to the mailing list which is
> responsible for maintaining the code that you've analyzed:
> newlib@sources.redhat.com .
> I've redirected this discussion there.
> Thanks for your in-depth analysis of the problem.
> cgf
> On Tue, Oct 23, 2001 at 06:21:40PM +0200, Pavel Tsekov wrote:
> >Upon further investigation this problem seems to be much bigger than
> >I've initially thought and there is no easy patch to it (at least I
> >think so) so I'll describe what've found about it.  I started a patch
> >though and will would like to know if you like my approach or will
> >suggest another one.
> >
> >
> >Let me show you with some digits whats going on:
> >
> >We have 2048 bytes file.  We have bufsize 1024.  We fread 1024 bytes -
> >this fills exactly the internal buffer thus 'n' will become 1024,
> >fp->_r will become 0.  We request then file position 0 from the end of
> >file.  ftell reports 2048.  Now we want to go back to 1024 and read 8
> >bytes.  fseek tries to optiomize since we are in read only mode ...  it
> >does this

I believe the problem lies with the seek to end.  In particular:

  curoff = target & ~(fp->_blksize - 1);
  if ((*seekfn) (fp->_cookie, curoff, SEEK_SET) == POS_ERR)
    goto dumb;
  fp->_r = 0;
  if (HASUB (fp))
    FREEUB (fp);
  fp->_flags &= ~__SEOF;
  n = target - curoff;
  if (n)
      if (__srefill (fp) || fp->_r < n)
        goto dumb;
      fp->_p += n;
      fp->_r -= n;

Notice the check for if (n) to do the refill.  We have already determined that
the offset is not in the current block.  The fact that we are seeking to a block
boundary causes curoff = target.  Thus, n ends up being 0.  We don't do the refill
and the fp->p value is pointing to the end.  Hence the problems afterwards.
If we always do the __srefill I think this cures the problem.  Offhand, I cannot
think of any scenario where we don't want the refill to occur.

-- Jeff J.

More information about the Newlib mailing list