string::reserve method broken when shrinking
>Submitter-Id: net
>Originator: bert hubert (ahu@ds9a.nl)
>Organization: PowerDNS
>Confidential: no
>Synopsis: When reserving a string to become smaller, program crashes
>Severity: serious
>Priority: medium
>Category: libstdc++
>Class: wrong-code
>Release: 3.0.2 20010922 (Debian prerelease) (Debian testing/unstable)
>Environment:
System: Linux hubert 2.4.10 #1 Sun Sep 23 21:14:45 CEST 2001 i686 unknown
Architecture: i686
host: i386-pc-linux-gnu
build: i386-pc-linux-gnu
target: i386-pc-linux-gnu
configured with: ../src/configure -v --enable-languages=c,c++,java,f77,proto,objc --prefix=/usr --infodir=/share/info --mandir=/share/man --enable-shared --with-gnu-as --with-gnu-ld --with-system-zlib --enable-long-long --enable-nls --without-included-gettext --disable-checking --enable-threads=posix --enable-java-gc=boehm --with-cpp-install-dir=bin --enable-objc-gc i386-linux
>Description:
Snippet of code:
/** convenience function for creating a reply packet from a question packet.
Do not forget to delete it after use! */
DNSPacket *DNSPacket::replyPacket() const
{
DNSPacket *r=new DNSPacket;
r->setRemote(&remote);
r->setAnswer(true); // this implies the allocation of the header
r->setA(true); // and we are authoritative
r->setRA(0); // no recursion available
r->setRD(d.rd); // if you wanted to recurse, answer will say you wanted it
(we don't do it)
r->setID(d.id);
r->setOpcode(0);
// reserve some space
r->stringbuffer.reserve(d_qlen+12);
// copy the question in
r->setQ(r->stringbuffer.c_str()+12,d_qlen);
r->d.qdcount=1;
r->d_dt=d_dt;
return r;
}
I accidentally forgot the r-> before stringbuffer.reserve(d_qlen+12), which
caused a request to reserve a smaller space then currently used by
stringbuffer. The method was not const, which caused gcc not to notice the
error.
Backtrace of the coredump, somewhat incorrect:
#0 0x08075887 in std::__default_alloc_template<true, 0>::allocate(unsigned)
()
at eval.c:41
#1 0x080747d6 in std::string::_Rep::_S_create(unsigned,
std::allocator<char>
+const&) () at eval.c:41
#2 0x08073535 in std::string::_Rep::_M_clone(std::allocator<char> const&,
+unsigned) () at eval.c:41
#3 0x080737d5 in std::string::reserve(unsigned) () at eval.c:41
#4 0x0805cf17 in DNSPacket::replyPacket() () at eval.c:41
#5 0x0806aee7 in PacketHandler::question(DNSPacket*) () at eval.c:41
#6 0x080739e0 in Distributor<DNSPacket, DNSPacket,
+PacketHandler>::makeThread(void*) () at eval.c:41
#7 0x40020efa in pthread_detach () from /lib/libpthread.so.0
I think the problem is due to this line in basic_string.tcc:
if (__res > this->capacity() || _M_rep()->_M_is_shared())
and then this one:
_CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
This probably leads to a negative clone() request.
>How-To-Repeat:
>Fix:
Reply to: