https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81395
Bug ID: 81395
Summary: basic_filebuf::overflow recurses and overflows stack
Product: gcc
Version: 8.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: redi at gcc dot gnu.org
Target Milestone: ---
This program goes into an infinite recursion in basic_filebuf::overflow:
#include <fstream>
#include <cstring>
using std::memset;
int main()
{
{
std::ofstream s("test.txt");
char data[BUFSIZ];
memset(data, 'A', sizeof(data));
s.write(data, sizeof(data));
}
std::fstream s("test.txt");
char buf[BUFSIZ];
memset(buf, 0, sizeof(buf));
s.read(buf, sizeof(buf));
#ifdef FIX
s.seekg(sizeof(buf));
#endif
s << 'B';
}
The standard requires the seek performed when FIX is defined, so we're allowed
to give unexpected results. Even so, it would be preferable to not crash when
that's missing.
The problem is that the write calls overflow which starts with:
if (__testout)
{
if (_M_reading)
{
_M_destroy_pback();
const int __gptr_off = _M_get_ext_pos(_M_state_last);
if (_M_seek(__gptr_off, ios_base::cur, _M_state_last)
== pos_type(off_type(-1)))
return __ret;
}
That call to _M_seek calls _M_terminate_output which starts with:
// Part one: update the output sequence.
bool __testvalid = true;
if (this->pbase() < this->pptr())
{
const int_type __tmp = this->overflow();
if (traits_type::eq_int_type(__tmp, traits_type::eof()))
__testvalid = false;
}
So we go back to overflow() and then recurse.