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.

Reply via email to