bug in gmp_fprintf?

Vincent Lefevre vincent at vinc17.net
Tue Nov 24 15:01:21 UTC 2015

On 2015-11-23 23:35:28 +0100, Torbjörn Granlund wrote:
> Clearly, the code should be replaced to something along these lines:
>       blk_size = 4;       // initial input block size
>       cnt = 10;           // count to next block size increase
>       while (...)
>         {
>           nread = fread (bp, 1, blk_size, fp);
>           if (nread != blk_size)
>             {
>               TODO: This does not mean we're hit the end of things; if we're
>               reading from a pipe we can get partial block reads.  We should
>               probably simply loop around read, or fall back to getc.  Note
>               that the code below expects an even # of bytes, padding/sentinel
>               would be needed for odd sizes.
>             }

The C standard says:

  The fread function returns the number of elements successfully
  read, which may be less than nmemb if a read error or end-of-file
  is encountered.

So, getting nread less than blk_size seems to be a read error or an
end-of-file (I think the "if" here is meant to be a equivalence),
though what is an end-of-file exactly is out of the scope of the C
standard, I suppose.

In case of a pipe, this means that the fread may block if you try
to read more than available (in POSIX, I suppose that this depends
on whether O_NONBLOCK was used internally).

The other problem is with ungetc at the end. Even if you are on a
system where it is guaranteed to succeed, this can break relative
file positioning (which could be done by the user after the GMP
function returns), as the C standard says about ungetc:

  A successful intervening call (with the stream pointed to by stream)
  to a file positioning function (fseek, fsetpos, or rewind) discards
  any pushed-back characters for the stream.


  The value of the file position indicator for the stream after
  reading or discarding all pushed-back characters shall be the
  same as it was before the characters were pushed back. For a
  text stream, the value of its file position indicator after a
  successful call to the ungetc function is unspecified until
  all pushed-back characters are read or discarded.

The C rationale has a discussion of the two different models of
ungetc: one model replaces characters in the buffer, while the
other model pushes characters between the current character and
the previous one.

So, in practice, the file position is indeterminate, and reading
N characters and putting them back successfully with ungetc is not
equivalent to a no-op.

Vincent Lefèvre <vincent at vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

More information about the gmp-bugs mailing list