Skip to content

<fstream>: seeking 0 with std::ios::cur ignored with bidirectional streams #3572

@Bo98

Description

@Bo98

Describe the bug
C++ Standard, [filebuf], paragraph 2 states that:

The restrictions on reading and writing a sequence controlled by an object of class basic_filebuf<charT, traits> are the same as for reading and writing with the C standard library FILEs

So when referring to C standard §7.19.5.3, paragraph 6 states that:

However, output shall not be directly followed by input without an intervening call to the fflush function or to a file positioning function (fseek, fsetpos, or rewind), and 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

One could therefore expect that for a bidirectional std::fstream you could perform stream.seekp(0, std::ios::cur) to satisfy this. In libstdc++ and libc++, this works but this does not work with MSVC STL.

Note that stream.seekp(stream.tellp()) works. So does a +1 and -1 on std::ios:cur.

Command-line test case

#include <fstream>
#include <iostream>

int main() {
	std::ofstream init("test.txt");
	init << "abcd";
	init.close();

	char buffer[5] = {};

	std::fstream inout("test.txt");
	inout.read(buffer, 2);
	inout.seekp(0, std::ios::cur); // Should allow switch to write.
	inout << "ba";
	inout.close();

	std::ifstream out("test.txt");
	out.read(buffer, 4);
	std::cout << buffer << std::endl;
	out.close();
}

Expected behavior
The output is "abba".

MSVC STL outputs "abcd" - the write operation is completely ignored.

STL version

Microsoft Visual Studio Enterprise 2022
Version 17.5.2

Additional context

C++ standard, [filebuf.virtuals], paragraph 13 states:

Let width denote a_codecvt.encoding(). If is_open() == false, or off != 0 && width <= 0, then the positioning operation fails. Otherwise, if way != basic_ios::cur or off != 0, and if the last operation was output, then update the output sequence and write any unshift sequence. Next, seek to the new position: if width > 0, call fseek(file, width * off, whence), otherwise call fseek(file, 0, whence)

If I've not misread this: although stream.seekp(0, std::ios::cur) should not touch the output/unshift sequence, it still should call fseek to my understanding.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions