From: David Reiss Date: Wed, 6 Oct 2010 17:10:46 +0000 (+0000) Subject: THRIFT-926. cpp: TMemoryBuffer: Uphold the strong exception safety guarantee X-Git-Tag: 0.6.0~95 X-Git-Url: https://source.supwisdom.com/gerrit/gitweb?a=commitdiff_plain;h=ece1a089eccad21f093de72b5fe6d730d132812c;p=common%2Fthrift.git THRIFT-926. cpp: TMemoryBuffer: Uphold the strong exception safety guarantee Previously, if we had a realloc failure when growing a TMemoryBuffer, we would leave the buffer in an invalid state (bufferSize_ would reflect the desired size, rather than the actual size). Now, we make no change to any member variables if realloc fails. git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@1005165 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/lib/cpp/src/transport/TBufferTransports.cpp b/lib/cpp/src/transport/TBufferTransports.cpp index 6ba70e2b..45913f4d 100644 --- a/lib/cpp/src/transport/TBufferTransports.cpp +++ b/lib/cpp/src/transport/TBufferTransports.cpp @@ -324,24 +324,25 @@ void TMemoryBuffer::ensureCanWrite(uint32_t len) { } // Grow the buffer as necessary. + uint32_t new_size = bufferSize_; while (len > avail) { - bufferSize_ *= 2; - wBound_ = buffer_ + bufferSize_; - avail = available_write(); + new_size = new_size > 0 ? new_size * 2 : 1; + avail = available_write() + (new_size - bufferSize_); } // Allocate into a new pointer so we don't bork ours if it fails. - void* new_buffer = std::realloc(buffer_, bufferSize_); + void* new_buffer = std::realloc(buffer_, new_size); if (new_buffer == NULL) { throw TTransportException("Out of memory."); } + bufferSize_ = new_size; ptrdiff_t offset = (uint8_t*)new_buffer - buffer_; buffer_ += offset; rBase_ += offset; rBound_ += offset; wBase_ += offset; - wBound_ += offset; + wBound_ = buffer_ + bufferSize_; } void TMemoryBuffer::writeSlow(const uint8_t* buf, uint32_t len) {