Bug 12527 - Off by one bug with ftell() with fmemopen()
Summary: Off by one bug with ftell() with fmemopen()
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.12
: P2 normal
Target Milestone: ---
Assignee: Ulrich Drepper
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-03-01 19:59 UTC by Per Inge Mathisen
Modified: 2014-06-27 13:48 UTC (History)
1 user (show)

See Also:
Host: x86_64
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments
Program that fails (465 bytes, application/text)
2011-03-01 19:59 UTC, Per Inge Mathisen
Details
Remove erroneous text from the documentation (527 bytes, patch)
2011-03-07 21:04 UTC, Per Inge Mathisen
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Per Inge Mathisen 2011-03-01 19:59:18 UTC
Created attachment 5269 [details]
Program that fails

The attached tiny program assert fails on ftell(fp) == ftell(fp), which it seems to me should always work. I only get this problem with file pointers created with fmemopen and the "r+" mode, and only with sequences of events similar to those in the attached file. The ftell() seems to always returns 1 less than the actual size when it fails.

There also seems to be an issue with fmemopen() when used with the "r+" mode if the input buffer is not zero cleared. See comment in attachment.
Comment 1 Per Inge Mathisen 2011-03-01 20:08:56 UTC
Tested on Fedora 13 glibc 2.12.2 (gcc-4.4.5) and Debian eglibc 2.11.2-13. Both fail.
Comment 2 Andreas Schwab 2011-03-03 11:57:54 UTC
7.19.5.3 The fopen function
6 When a file is opened with update mode ... input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file.
Comment 3 Dave Flaherty 2011-03-03 20:16:45 UTC
The ftell() Open Group Base Specifications Issue 7 doc states ‘ftell() shall return the current value of the file-position indicator for the stream.’  The file position indicator is not updated without an intervening call to the fflush function or to a file positioning function (fseek, fsetpos, or rewind), or until the buffer is full.
Comment 4 Per Inge Mathisen 2011-03-03 21:27:53 UTC
The glibc documentation says: "As you can see, ‘+’ requests a stream that can do both input and output. The ISO standard says that when using such a stream, you must call fflush (see Stream Buffering) or a file positioning function such as fseek (see File Positioning) when switching from reading to writing or vice versa. Otherwise, internal buffers might not be emptied properly. The GNU C library does not have this limitation; you can do arbitrary reading and writing operations on a stream in whatever order." (12.3 Opening Streams)

So either the documentation or the code is in error here.

(http://www.gnu.org/s/libc/manual/html_node/Opening-Streams.html#Opening-Streams)

About ftell(), it also says: "each time a character is read or written, the file position is incremented" (11.1.2 File Position), which makes a lot of sense. Otherwise you have to implement your own code layer above streams just to count bytes in many cases. Thankfully this does seem to be working fine in glibc.
Comment 5 Ulrich Drepper 2011-03-06 04:13:36 UTC
(In reply to comment #4)
> So either the documentation or the code is in error here.

If you want to see the documentation changed send a patch.  The code is what determines the semantics.  That text is for a different implementation.  Your program is just plain wrong and if you add the fseek in the appropriate place everything works find.

Suspended until a doc patch is received.
Comment 6 Per Inge Mathisen 2011-03-07 21:04:01 UTC
Created attachment 5279 [details]
Remove erroneous text from the documentation
Comment 7 Ulrich Drepper 2011-05-12 03:44:38 UTC
I've added the change.