basic_istream constructor dereferences unitialized streambuf
Sun Studio C++ 11, Solaris 10 SPARC.
The Rogue Wave C++ standard library documentation describes how
to connect iostream and streambuf objects:
http://www.roguewave.com/support/docs/sourcepro/edition9/html/stdlibug/39-3.htm l
So I make a little program out of the example from the
Rogue Wave documentation:
#include <iostream>
class DerivedStreamBuf : public std::streambuf {
// ...
};
class DerivedOutputStream : public std::ostream {
public:
DerivedOutputStream():
std::ios(0), std::ostream(&dsb) {}//1
// ...
private:
DerivedStreamBuf dsb;
// ...
};
int main(int argc, char *argv[])
{
DerivedOutputStream derivedOutputStream;
std::cout << (derivedOutputStream.fail() ? "fail" : "ok" ) << std::endl;
std::streambuf* buf = derivedOutputStream.rdbuf();
buf->sputc('X');
return 0;
}
Compile and run it with Sun Studio C++ 11:
% CC -g -o buf buf.cpp
% buf
fail
zsh: segmentation fault (core dumped) buf
% dbx buf core
Reading buf
core file header read successfully
Reading ld.so.1
Reading libCstd.so.1
Reading libCrun.so.1
Reading libm.so.2
Reading libc.so.1
Reading libCstd_isa.so.1
Reading libc_psr.so.1
program terminated by signal SEGV (no mapping at the fault address)
0xefa7b06c: sputc+0x0004:ld[%o0 + 52], %o1
Current function is main
22buf->sputc('X');
(dbx) print buf
buf = (nil)
(dbx) where
[1] std::basic_streambuf<char,std::char_traits><char> >::sputc(0x0, 0x58,
0xefb7c064,
0x22a48, 0x0, 0x58000000), at 0xefa7b06c
=>[2] main(argc = 1, argv = 0xffbfe674), line 22 in "buf.cpp"
(dbx) quit
% CC -V
CC: Sun C++ 5.8 Patch 121017-10 2007/02/21
%
I think this is a bug in the Rogue Wave C++ standard library
that is included with Sun Studio 11 C++. The problem is the
basic_istream constructor dereferences the unitialized
streambuf object, from /opt/SC11.0/SUNWspro/prod/include/CC/Cstd/istream.cc:
template<class charT, class traits>
basic_istream<charT, traits>::
basic_istream(basic_streambuf<charT, traits> *sb)
: __chcount(0)
{
if ( sb )
{
if ( sb->which_open_mode() & ios_base::in ) // <=== dereferences streambuf!!!
this->init(sb);
else
this->init(0);
}
else
this->init(0);
}
From the link given above:
In the first case where the stream object does not contain a buffer object,
the C++ standard mandates that no parent class constructors or destructors
(ios, istream, or ostream) access the stream buffer. This restriction is
important, since a derivation such as the following is otherwise unsafe:
class DerivedStreamBuf : public std::streambuf {
// ...
};
class DerivedOutputStream : public std::ostream {
public:
DerivedOutputStream():
std::ios(0), std::ostream(&dsb) {}//1
// ...
private:
DerivedStreamBuf dsb;
// ...
};
Thanks, Mark

