[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: