|Anonymous | Login||2021-11-29 10:52 UTC|
|Main | My View | View Issues | Change Log | Docs|
|Viewing Issue Simple Details|
|ID||Category||Severity||Type||Date Submitted||Last Update|
|0001406||[1003.1(2016/18)/Issue7+TC2] System Interfaces||Editorial||Clarification Requested||2020-09-28 21:26||2021-02-11 18:43|
|Organization||Red Hat Inc|
|Page Number||https://pubs.opengroup.org/onlinepubs/9699919799/functions/open_memstream.html [^]|
|Final Accepted Text|
|Summary||0001406: clarification of SEEK_END when current pointer doesn't match buffer size|
Consider a stream created by open_memstream(), where 16 bytes are written, fseek(0,SEEK_POS) to rewind, then write 4 bytes, and fflush(). At this point, the value pointed to by the sizep argument to open_memstream() should be 4 (please confirm).
At this point in the state of the stream, what are the semantics of SEEK_END? What will be the "file size" if you fclose() at this point?
The example explicitly SEEK_SETs to the buffer size before fclose(), eliding the issue.
Please clarify if SEEK_END is relative to the current position or the current buffer length, and if it's changed by a call to fflush() at that time.
Please clarify if a SEEK_SET to set the current pointer less than the current buffer size, itself (without read/write), changes the SEEK_END semantics, or the value stored in *sizep after fflush().
|Tags||No tags attached.|
|This isn't an idle request, we are actively trying to harmonize the behaviour of implementations, particularly glibc, musl and FreeBSD to name three. The current wording upstream seems underspecified. At least one Red Hat customer has argued that it should match the behaviour of a normal file-backed stream to avoid confusion. It is clear to me that the intent of open_memstream was *not* to follow the behaviour of file-backed streams because of the special language and programming models that would use the API. Thus this request for guidance and clarification.|
Don Cragun (manager)
edited on: 2020-09-29 20:55
This bug has been moved from "Base Definitions and Headers" to "System Interfaces".
Noting that the rationale for open_memstream() refers to fmemopen(), I assume that the description of what happens when you use one of the fseek() or fseeko() functions on a memory stream are as described in fmemopen(). Note that in the upcoming revision ot the standard, part of the description of this behavior is changed by the resolution of 0000456.
But, the first paragraph of the description of open_memstream() only says that the stream is opened for writing. It doesn't specify whether it is supposed to use byte mode or text mode (and I believe the mode affects whether of not a NUL byte is written and writing that NUL byte determines whether or not the stream size changes).
The reference to fmemopen() is noted, but as open_memstream() returns the *current* pointer in *sizep in the example, it clouds the issue of what the "end" of the data is - the API does not give the caller a way to determine the current buffer length if the current pointer is not coincident with it, and the NUL terminator is not specified, so having the "end of file" be somewhere undiscoverable seems problematic.
The example given by the standard explicltly uses ftell/fseek to position the current pointer at the "expected" end of data, implying that that would not otherwise be EOF had this not happened.
It is these differences in spec between open_memstream() and fmemopen() that confuse us, hence our request for clarification.
|This was discussed during today's telecon. If I understand correctly, the wording of open_memstream() was originally intended to match glibc's implementation, but it looks like we (the Austin Group) were not successful in crafting wording that unambiguously matches glibc's behavior. We are not very familiar with the various important use cases for this function, so we are not sure what the behavior should be. So, before we can resolve this bug, we need input from the implementors: What do you want the behavior to be?|
It looks to me the intent was that the interface shall track SEEK_END as the size of the buffer, ignoring the appended NUL byte. In the example code, the second seeko() should be equivalent to seeko(stream, 0, SEEK_END).
The wording appears to be as it is for the use case when an application does an initial write, then does a large single realloc() of the buffer in expectation of many more writes not needing to do a realloc per write. In this case an arbitrary seek past SEEK_END is permitted, but should not be reflected in len as current or final position on an immediately following flush or close respectively because nothing has been stored yet. The lesser SEEK_END value is the maximum known length so that gets stored. The parameter name probably should be sizeorposp to better reflect this, not sizep, but I don't see a rewind and rewrite affecting SEEK_END, only writes past the current SEEK_END.
|2020-09-28 21:26||djdelorie||New Issue|
|2020-09-28 21:26||djdelorie||Name||=> DJ Delorie|
|2020-09-28 21:26||djdelorie||Organization||=> Red Hat Inc|
|2020-09-28 21:26||djdelorie||Section||=> open_memstream|
|2020-09-28 21:26||djdelorie||Page Number||=> https://pubs.opengroup.org/onlinepubs/9699919799/functions/open_memstream.html [^]|
|2020-09-28 21:26||djdelorie||Line Number||=> n/a|
|2020-09-29 06:22||Florian Weimer||Issue Monitored: Florian Weimer|
|2020-09-29 17:53||carlos||Note Added: 0005011|
|2020-09-29 20:54||Don Cragun||Interp Status||=> ---|
|2020-09-29 20:54||Don Cragun||Note Added: 0005012|
|2020-09-29 20:54||Don Cragun||Category||Base Definitions and Headers => System Interfaces|
|2020-09-29 20:55||Don Cragun||Note Edited: 0005012|
|2020-09-29 20:55||Don Cragun||Relationship added||related to 0000456|
|2020-09-29 23:32||djdelorie||Note Added: 0005013|
|2021-02-11 17:40||rhansen||Note Added: 0005233|
|2021-02-11 18:43||shware_systems||Note Added: 0005234|
|2021-02-11 18:43||shware_systems||Note Added: 0005235|
|2021-02-11 18:43||shware_systems||Note Deleted: 0005235|
|Mantis 1.1.6[^] Copyright © 2000 - 2008 Mantis Group|