This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug optimization/12301] New: corruption in exception path, exception in returned expression (g++ 3.3, 3.3.1 and 3.3.2 snapshot)
- From: "gcc at cohi dot at" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 16 Sep 2003 13:57:55 -0000
- Subject: [Bug optimization/12301] New: corruption in exception path, exception in returned expression (g++ 3.3, 3.3.1 and 3.3.2 snapshot)
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
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;
}
- Follow-Ups:
- [Bug optimization/12301] corruption in exception path, exception in returned expression (g++ 3.3, 3.3.1 and 3.3.2 snapshot)
- [Bug optimization/12301] corruption in exception path, exception in returned expression (g++ 3.3, 3.3.1 and 3.3.2 snapshot)
- From: bangerth at dealii dot org
- [Bug optimization/12301] corruption in exception path, exception in returned expression (g++ 3.3, 3.3.1 and 3.3.2 snapshot)
- From: ehrhardt at mathematik dot uni-ulm dot de
- [Bug optimization/12301] [3.3/3.4 regression] corruption in exception path, exception in returned expression
- From: ebotcazou at gcc dot gnu dot org
- [Bug optimization/12301] [3.3/3.4 regression] corruption in exception path, exception in returned expression
- From: ebotcazou at gcc dot gnu dot org
- [Bug target/12301] [3.3/3.4 regression] corruption in exception path, exception in returned expression
- From: cvs-commit at gcc dot gnu dot org
- [Bug target/12301] [3.3/3.4 regression] corruption in exception path, exception in returned expression
- From: cvs-commit at gcc dot gnu dot org
- [Bug target/12301] [3.3/3.4 regression] corruption in exception path, exception in returned expression
- From: ebotcazou at gcc dot gnu dot org