This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug optimization/12301] New: corruption in exception path, exception in returned expression (g++ 3.3, 3.3.1 and 3.3.2 snapshot)


PLEASE REPLY TO gcc-bugzilla@gcc.gnu.org ONLY, *NOT* gcc-bugs@gcc.gnu.org.

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12301

           Summary: corruption in exception path, exception in returned
                    expression (g++ 3.3, 3.3.1 and 3.3.2 snapshot)
           Product: gcc
           Version: 3.3.2
            Status: UNCONFIRMED
          Severity: critical
          Priority: P1
         Component: optimization
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: gcc at cohi dot at
                CC: gcc-bugs at gcc dot gnu dot org,gcc at cohi dot at
 GCC build triplet: sparc-sun-solaris2.8
  GCC host triplet: sparc-sun-solaris2.8
GCC target triplet: sparc-sun-solaris2.8

SYMPTOM:

If evaluating the expression in a return statement in a try-block throws an
exception, the program crashes with a segfault or uses random data at the point
mentioned in the code snippet below.

Compiled with g++ -W -Wall -O.


CODE SNIPPET:
(full example code below)

template<> std::string real_cast ( const std::string & value )
{
   try {
      return mk( value );  // bug triggered by mk throwing a std::string
   }
   catch ( std::string & s ) {
      throw s + value;  // segfaults in std::string::operator+
   }
}


WORKAROUND:

The problem goes away by either of
(1) not compiling with -O
(2) using an explicit temporary for the return value:

std::string nrv;
try {
  nrv = ...
}
catch ... {
}
return nrv;


ADDITIONAL ANALYSIS:

While debugging with gdb, it seemed that the stack got corrupted, i.e. while the
value of "note" was ok before the return statement, it was mangled when
execution reached the catch block; similar for the "this" pointer in case of
"foo" being a member function.

The full code below shows that the corruption cannot be a side-effect of "somefunc".


OS VERSION:

uname -a
SunOS xxxxxx 5.8 Generic_108528-20 sun4u sparc SUNW,Sun-Fire-880 Solaris


COMPILER VERSIONS:

Reading specs from /opt/local.source/lib/gcc-lib/sparc-sun-solaris2.8/3.3.2/specs
Configured with: ./configure --prefix=/opt/local.source --enable-shared
--enable-threads --with-cpu=v9 --enable-languages=c,c++ --disable-libgcj
--disable-multilib --with-gnu-as
--with-as=/opt/global/gcc-3.3-32-solaris8-108528-20/bin/as --with-gnu-ld
--with-ld=/opt/global/gcc-3.3-32-solaris8-108528-20/bin/ld
Thread model: posix
gcc version 3.3.2 20030908 (prerelease)

Reading specs from
/opt/global/gcc-3.3-32-solaris8-108528-20/lib/gcc-lib/sparc-sun-solaris2.8/3.3/specs
Configured with: ../gcc-3.3/configure
--prefix=/opt/global/gcc-3.3-32-solaris8-108528-20 --enable-shared
--enable-threads --with-cpu=v9 --with-gnu-as
--with-as=/opt/global/gcc-3.3-32-solaris8-108528-20/bin/as --with-gnu-ld
--with-ld=/opt/global/gcc-3.3-32-solaris8-108528-20/bin/ld --disable-multilib
Thread model: posix
gcc version 3.3


SOURCE CODE:

#include <string>
#include <iostream>

// Program to trigger a bug in GCC 3.3* / Sparc / Solaris 2.8
// compile with "g++ -O -W -Wall" to trigger bug
// compile without optimisation produces non-crashing version

template< class T > T real_cast( const std::string & );

template< class T > T cast_helper( const std::string & value, const std::string
& debug )
{
   try {
      return real_cast< T >( value );
   }
   catch ( std::string & e ) {
      throw e + debug;
   }
}

struct Value
{
   Value( const std::string & value ) : m_value( value ) {}

   template< class T > T get( const std::string & debug ) const
   {
      if ( m_value.empty() )
         throw std::string( "empty" );
      else
         return cast_helper< T >( m_value, debug );
   }

   const std::string m_value;
};

std::string mk( const std::string & value )
{
   if ( value.length() < 4 )
      return value + value;
   else
      throw value + value;
}

template<> std::string real_cast ( const std::string & value )
{
   try {
      return mk( value );
   }
   catch ( std::string & s ) {
      throw s + value;  // segfaults in std::string::operator+
   }
}

int main( int, char ** )
{
   try {
      Value error( "error" );
      const std::string error_s = error.get< std::string >( "error string" );
      std::cerr << error_s << '\n';
   }                                        
   catch ( std::string & e ) {
      std::cerr << "exception [ " << e << " ]\n";
   }
   return 0;
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]