public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug libstdc++/114879] New: std::ios::sync_with_stdio(false) triggers undefined behaviour of fflush(stdin)
@ 2024-04-28 17:37 campbell+gcc-bugzilla at mumble dot net
  0 siblings, 0 replies; only message in thread
From: campbell+gcc-bugzilla at mumble dot net @ 2024-04-28 17:37 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114879

            Bug ID: 114879
           Summary: std::ios::sync_with_stdio(false) triggers undefined
                    behaviour of fflush(stdin)
           Product: gcc
           Version: 13.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: campbell+gcc-bugzilla at mumble dot net
  Target Milestone: ---

std::ios::sync_with_stdio(false) creates a stdio_filebuf over stdin with mode
in:

 182         new (&buf_cin) stdio_filebuf<char>(stdin, ios_base::in);

https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libstdc%2B%2B-v3/src/c%2B%2B98/ios_init.cc;h=ace94b992b5ac7559352f5e7e94c67f64317bd9d;hb=c891d8dc23e1a46ad9f3e757d09e57b500d40044#l182

The stdio_filebuf constructor for these parameter types passes the arguments on
to __basic_file<char>::sys_open:

 158       this->_M_file.sys_open(__f, __mode);

https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libstdc%2B%2B-v3/include/ext/stdio_filebuf.h;h=98b8fa2a095acf190237887d4e21394212d1f38a;hb=c891d8dc23e1a46ad9f3e757d09e57b500d40044#l158

With these parameter types, __basic_file<char>::sys_open will, in turn, pass
stdin to fflush in this case, and will only actually open the file if fflush
succeeds:

 216         do
 217           __err = fflush(__file);
 218         while (__err && errno == EINTR);
 219         errno = __save_errno;
 220         if (!__err)
 221           {
 222             _M_cfile = __file;
 223             _M_cfile_created = false;
 224             __ret = this;
 225           }

https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libstdc%2B%2B-v3/config/io/basic_file_stdio.cc;h=27c2ad2afe3ade7284ec9d487b74d3d04dd756f4;hb=c891d8dc23e1a46ad9f3e757d09e57b500d40044#l216

But stdin is an input stream, not an output or update stream.  And calling
fflush on an input stream is undefined behaviour in standard C:

> If stream points to an output stream or an update stream in which
> the most recent operation was not input, the fflush function causes
> any unwritten data for that stream to be delivered to the host
> environment to be written to the file; otherwise, the behavior is
> undefined.
> 
> (ISO C11 and ISO C17, Sec. 7.21.5.2 `The fflush function')

On NetBSD 9, what fflush(stdin) does depends on whether fd 0 is open for
writing or not:

- If fd 0 is open for writing (unlikely but possible), it will write a buffer's
worth of heap garbage to fd 0.
- If fd 0 is not open for writing (more likely), fflush will fail with EBADF,
causing __basic_file<char>::sys_open to fail, after which although
std::cin.good() will initially return true, std::cin will otherwise be
nonfunctional (https://gnats.NetBSD.org/58206).

Fix: Don't call fflush if the mode is input.

(This bug first appeared no later than GCC 7, which NetBSD 9 ships with and
where I found the bug, and still appears in GCC 13.2.0, as quoted in the code
above.)

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-04-28 17:37 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-28 17:37 [Bug libstdc++/114879] New: std::ios::sync_with_stdio(false) triggers undefined behaviour of fflush(stdin) campbell+gcc-bugzilla at mumble dot net

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).