microsoft / microsoft/STL

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

Open
#3,572 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
C++
Stars
11.1k
Forks
1.7k
Avg merge
4d 15h
Merged PRs (30d)
22

Description

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the provided command-line test case and inspect the std::fstream seekp and basic_filebuf positioning behavior for bidirectional streams. Compare seekp(0, std::ios::cur) with seekp(stream.tellp()) and nonzero relative seeks; done means the sample produces "abba" and the positioning operation correctly permits the following write.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.