C++ Standard Library
  1. C++ Standard Library
  2. STDCXX-1058

std::basic_ios<>::copyfmt() with registered callback (via std::ios_base::register_callback()) run-time SIGABRT

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 4.2.1, 4.2.x, 4.3.x, 5.0.0
    • Fix Version/s: 4.2.x, 4.3.x
    • Component/s: 27. Input/Output
    • Environment:

      Solaris 10 and 11, Red Hat Linux, OpenSuSE Linux
      Sun C++ Compilers 12.1, 12.2, 12.3

      Defect is independent of platform or compiler.

    • Patch Info:
      Patch Available
    • Regression:
      Regression, Unit Test Broken
    • Severity:
      Runtime Error

      Description

      A stream with a registered callback via register_callback() SIGABRTs at run-time:

      #include <iostream>
      #include <fstream>
      
      int x;
      
      void testfun (std::ios_base::event ev, std::ios_base& iosobj, int index)
      {
        x = index;
      
        switch (ev)
        {
          case std::ios_base::copyfmt_event:
            std::cerr << "copyfmt_event" << std::endl; break;
          case std::ios_base::imbue_event:
            std::cerr << "imbue_event" << std::endl; break;
          case std::ios_base::erase_event:
            std::cerr << "erase_event" << std::endl; break;
          default:
            std::cerr << "unknown" << std::endl; break;
        }
      }
      
      int main ()
      {
        std::fstream f0;
        std::fstream f1;
        int i = 101;
      
        std::ios_base::event_callback e1 = &testfun;
        f0.register_callback (e1, i);
      
        x = 0;
        f0.imbue (std::cerr.getloc());
        if (x != i)
          std::cerr << "x: expected " << i << " got " << x << std::endl;
      
        x = 0;
        f0.copyfmt (f1);
        if (x != i)
          std::cerr << "x: expected " << i << " got " << x << std::endl;
      
        return 0;
      }
      

      Output from GCC 4.5.0:

      [steleman@darthvader][/src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt][02/05/2012 0:32:42][1340]>> ./test-gcc 
      imbue_event
      erase_event
      

      Output from Sun C++ 12.2 with stlport4:

      [steleman@darthvader][/src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt][02/05/2012 0:32:44][1341]>> ./test-ss12-stlport 
      imbue_event
      erase_event
      copyfmt_event
      erase_event
      

      Output from Sun C++ 12.2 with our stdcxx (patched):

      [steleman@darthvader][/src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt][02/05/2012 0:32:58][1342]>> ./test-ss12-stdcxx 
      imbue_event
      erase_event
      

      Output from Pathscale 4.0.12.1 (which didn't patch stdcxx):

      [steleman@darthvader][/src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt][02/05/2012 0:33:03][1343]>> ./test-pathscale 
      imbue_event
      erase_event
      *** glibc detected *** ./test-pathscale: double free or corruption (fasttop): 0x 000000000605480 ***
      ======= Backtrace: =========
      /lib64/libc.so.6(+0x73286)[0x7f78cbb7f286]
      /lib64/libc.so.6(cfree+0x6c)[0x7f78cbb8402c]
      /opt/pathscale/ekopath-4.0.12.1/lib/4.0.12.1/x8664/64/libcxxrt.so(_ZdlPv+0xd)[0x f78cc097d63]
      /opt/pathscale/ekopath-4.0.12.1/lib/4.0.12.1/x8664/64/libstl.so(_ZNSt8ios_base11 C_usr_data10_C_deallocEPS0_+0x2d)[0x7f78cc300b5b]
      ======= Memory map: ========
      00400000-00404000 r-xp 00000000 103:00 9582413                           /src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt/test-pathscale
      00603000-00604000 r--p 00003000 103:00 9582413                           /src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt/test-pathscale
      00604000-00605000 rw-p 00004000 103:00 9582413                           /src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt/test-pathscale
      00605000-00626000 rw-p 00000000 00:00 0                                  [heap]
      
      [ ... ]
      

      I no longer have an unpatched stdcxx handy for the Sun C++ compilers available
      to reproduce the defect with the Sun C++ compiler.

      Defect is in file src/iostore.cpp, starting at line 275:

      _C_usr->_C_iarray, _C_usr->_C_parray and _C_usr->_C_cbarray
      are not set to NULL after deletion:

          _TRY {
              if (_C_usr) {
                  // fire erase events (27.4.4.2, p17) - may throw
                  if (_C_usr->_C_fire)
                      (this->*_C_usr->_C_fire)(erase_event, true /* reentrant */);
      
                  // delete existing arrays, if any; _C_usr will only be deleted
                  // if `rhs' contains no user data (see below)
                  operator delete (_C_usr->_C_iarray);
                  _C_usr->_C_iarray = 0UL; // <----- !!
                  operator delete (_C_usr->_C_parray);
                  _C_usr->_C_parray = 0UL; // <----- !!
                  operator delete (_C_usr->_C_cbarray);
                  _C_usr->_C_cbarray = 0UL; // <----- !!
              }
      

      Patch for 4.2.1 to follow shortly.

      1. 27.basic_ios.copyfmt.stdcxx-1058.cpp
        3 kB
        Stefan Teleman
      2. stdcxx-1058.patch
        2 kB
        Stefan Teleman
      3. test.cc
        0.9 kB
        Stefan Teleman

        Activity

        Stefan Teleman made changes -
        Status Open [ 1 ] Resolved [ 5 ]
        Fix Version/s 5.0.0 [ 12312691 ]
        Resolution Fixed [ 1 ]
        Stefan Teleman made changes -
        Attachment 27.basic_ios.copyfmt.stdcxx-1058.cpp [ 12532002 ]
        Stefan Teleman made changes -
        Attachment 27.basic_ios.copyfmt.stdcxx-1058.cpp [ 12532000 ]
        Stefan Teleman made changes -
        Attachment 27.basic_ios.copyfmt.stdcxx-1058.cpp [ 12530391 ]
        Stefan Teleman made changes -
        Attachment 27.basic_ios.copyfmt.stdcxx-1058.cpp [ 12532000 ]
        Stefan Teleman made changes -
        Attachment 27.ios_base.event_callback.stdcxx-1058.cpp [ 12527770 ]
        Stefan Teleman made changes -
        Attachment 27.basic_ios.copyfmt.stdcxx-1058.cpp [ 12530391 ]
        Stefan Teleman made changes -
        Attachment 27.ios_base.event_callback.stdcxx-1058.cpp [ 12527770 ]
        Stefan Teleman made changes -
        Patch Info Patch Available [ 10042 ]
        Stefan Teleman made changes -
        Attachment stdcxx-1058.patch [ 12524022 ]
        Farid Zaripov made changes -
        Assignee Farid Zaripov [ farid ]
        Farid Zaripov made changes -
        Description A stream with a registered callback via register_callback() SIGABRTs at run-time:

        #include <iostream>
        #include <fstream>

        int x;

        void testfun (std::ios_base::event ev, std::ios_base& iosobj, int index)
        {
          x = index;

          switch (ev)
          {
            case std::ios_base::copyfmt_event:
              std::cerr << "copyfmt_event" << std::endl; break;
            case std::ios_base::imbue_event:
              std::cerr << "imbue_event" << std::endl; break;
            case std::ios_base::erase_event:
              std::cerr << "erase_event" << std::endl; break;
            default:
              std::cerr << "unknown" << std::endl; break;
          }
        }

        int main ()
        {
          std::fstream f0;
          std::fstream f1;
          int i = 101;

          std::ios_base::event_callback e1 = &testfun;
          f0.register_callback (e1, i);

          x = 0;
          f0.imbue (std::cerr.getloc());
          if (x != i)
            std::cerr << "x: expected " << i << " got " << x << std::endl;

          x = 0;
          f0.copyfmt (f1);
          if (x != i)
            std::cerr << "x: expected " << i << " got " << x << std::endl;

          return 0;
        }

        Output from GCC 4.5.0:
        [steleman@darthvader][/src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt][02/05/2012 0:32:42][1340]>> ./test-gcc
        imbue_event
        erase_event

        Output from Sun C++ 12.2 with stlport4:
        [steleman@darthvader][/src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt][02/05/2012 0:32:44][1341]>> ./test-ss12-stlport
        imbue_event
        erase_event
        copyfmt_event
        erase_event

        Output from Sun C++ 12.2 with our stdcxx (patched):
        [steleman@darthvader][/src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt][02/05/2012 0:32:58][1342]>> ./test-ss12-stdcxx
        imbue_event
        erase_event

        Output from Pathscale 4.0.12.1 (which didn't patch stdcxx):
        [steleman@darthvader][/src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt][02/05/2012 0:33:03][1343]>> ./test-pathscale
        imbue_event
        erase_event
        *** glibc detected *** ./test-pathscale: double free or corruption (fasttop): 0x 000000000605480 ***
        ======= Backtrace: =========
        /lib64/libc.so.6(+0x73286)[0x7f78cbb7f286]
        /lib64/libc.so.6(cfree+0x6c)[0x7f78cbb8402c]
        /opt/pathscale/ekopath-4.0.12.1/lib/4.0.12.1/x8664/64/libcxxrt.so(_ZdlPv+0xd)[0x f78cc097d63]
        /opt/pathscale/ekopath-4.0.12.1/lib/4.0.12.1/x8664/64/libstl.so(_ZNSt8ios_base11 C_usr_data10_C_deallocEPS0_+0x2d)[0x7f78cc300b5b]
        ======= Memory map: ========
        00400000-00404000 r-xp 00000000 103:00 9582413 /src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt/test-pathscale
        00603000-00604000 r--p 00003000 103:00 9582413 /src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt/test-pathscale
        00604000-00605000 rw-p 00004000 103:00 9582413 /src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt/test-pathscale
        00605000-00626000 rw-p 00000000 00:00 0 [heap]

        [ ... ]

        I no longer have an unpatched stdcxx handy for the Sun C++ compilers available
        to reproduce the defect with the Sun C++ compiler.

        Defect is in file src/iostore.cpp, starting at line 275:

        _C_usr->_C_iarray, _C_usr->_C_parray and _C_usr->_C_cbarray
        are not set to NULL after deletion:

            _TRY {
                if (_C_usr) {
                    // fire erase events (27.4.4.2, p17) - may throw
                    if (_C_usr->_C_fire)
                        (this->*_C_usr->_C_fire)(erase_event, true /* reentrant */);

                    // delete existing arrays, if any; _C_usr will only be deleted
                    // if `rhs' contains no user data (see below)
                    operator delete (_C_usr->_C_iarray);
                    _C_usr->_C_iarray = 0UL; // <----- !!
                    operator delete (_C_usr->_C_parray);
                    _C_usr->_C_parray = 0UL; // <----- !!
                    operator delete (_C_usr->_C_cbarray);
                    _C_usr->_C_cbarray = 0UL; // <----- !!
                }

        Patch for 4.2.1 to follow shortly.
        A stream with a registered callback via register_callback() SIGABRTs at run-time:

        {code}
        #include <iostream>
        #include <fstream>

        int x;

        void testfun (std::ios_base::event ev, std::ios_base& iosobj, int index)
        {
          x = index;

          switch (ev)
          {
            case std::ios_base::copyfmt_event:
              std::cerr << "copyfmt_event" << std::endl; break;
            case std::ios_base::imbue_event:
              std::cerr << "imbue_event" << std::endl; break;
            case std::ios_base::erase_event:
              std::cerr << "erase_event" << std::endl; break;
            default:
              std::cerr << "unknown" << std::endl; break;
          }
        }

        int main ()
        {
          std::fstream f0;
          std::fstream f1;
          int i = 101;

          std::ios_base::event_callback e1 = &testfun;
          f0.register_callback (e1, i);

          x = 0;
          f0.imbue (std::cerr.getloc());
          if (x != i)
            std::cerr << "x: expected " << i << " got " << x << std::endl;

          x = 0;
          f0.copyfmt (f1);
          if (x != i)
            std::cerr << "x: expected " << i << " got " << x << std::endl;

          return 0;
        }
        {code}

        Output from GCC 4.5.0:
        {noformat}
        [steleman@darthvader][/src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt][02/05/2012 0:32:42][1340]>> ./test-gcc
        imbue_event
        erase_event
        {noformat}

        Output from Sun C++ 12.2 with stlport4:
        {noformat}
        [steleman@darthvader][/src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt][02/05/2012 0:32:44][1341]>> ./test-ss12-stlport
        imbue_event
        erase_event
        copyfmt_event
        erase_event
        {noformat}

        Output from Sun C++ 12.2 with our stdcxx (patched):
        {noformat}
        [steleman@darthvader][/src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt][02/05/2012 0:32:58][1342]>> ./test-ss12-stdcxx
        imbue_event
        erase_event
        {noformat}

        Output from Pathscale 4.0.12.1 (which didn't patch stdcxx):
        {noformat}
        [steleman@darthvader][/src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt][02/05/2012 0:33:03][1343]>> ./test-pathscale
        imbue_event
        erase_event
        *** glibc detected *** ./test-pathscale: double free or corruption (fasttop): 0x 000000000605480 ***
        ======= Backtrace: =========
        /lib64/libc.so.6(+0x73286)[0x7f78cbb7f286]
        /lib64/libc.so.6(cfree+0x6c)[0x7f78cbb8402c]
        /opt/pathscale/ekopath-4.0.12.1/lib/4.0.12.1/x8664/64/libcxxrt.so(_ZdlPv+0xd)[0x f78cc097d63]
        /opt/pathscale/ekopath-4.0.12.1/lib/4.0.12.1/x8664/64/libstl.so(_ZNSt8ios_base11 C_usr_data10_C_deallocEPS0_+0x2d)[0x7f78cc300b5b]
        ======= Memory map: ========
        00400000-00404000 r-xp 00000000 103:00 9582413 /src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt/test-pathscale
        00603000-00604000 r--p 00003000 103:00 9582413 /src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt/test-pathscale
        00604000-00605000 rw-p 00004000 103:00 9582413 /src/steleman/programming/stdcxx-ss122/bugfixes-sunw/fstream.copyfmt/test-pathscale
        00605000-00626000 rw-p 00000000 00:00 0 [heap]

        [ ... ]
        {noformat}

        I no longer have an unpatched stdcxx handy for the Sun C++ compilers available
        to reproduce the defect with the Sun C++ compiler.

        Defect is in file src/iostore.cpp, starting at line 275:

        _C_usr->_C_iarray, _C_usr->_C_parray and _C_usr->_C_cbarray
        are not set to NULL after deletion:

        {code}
            _TRY {
                if (_C_usr) {
                    // fire erase events (27.4.4.2, p17) - may throw
                    if (_C_usr->_C_fire)
                        (this->*_C_usr->_C_fire)(erase_event, true /* reentrant */);

                    // delete existing arrays, if any; _C_usr will only be deleted
                    // if `rhs' contains no user data (see below)
                    operator delete (_C_usr->_C_iarray);
                    _C_usr->_C_iarray = 0UL; // <----- !!
                    operator delete (_C_usr->_C_parray);
                    _C_usr->_C_parray = 0UL; // <----- !!
                    operator delete (_C_usr->_C_cbarray);
                    _C_usr->_C_cbarray = 0UL; // <----- !!
                }
        {code}

        Patch for 4.2.1 to follow shortly.
        Stefan Teleman made changes -
        Field Original Value New Value
        Attachment test.cc [ 12513282 ]
        Stefan Teleman created issue -

          People

          • Assignee:
            Farid Zaripov
            Reporter:
            Stefan Teleman
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development