Merge pull request #2401 from aaronmjones/THRIFT-3840

THRIFT-3840: C++ TJSONProtocol still using locale dependent formatting
diff --git a/bootstrap.sh b/bootstrap.sh
index 1989437..d699909 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -61,4 +61,4 @@
 sed '/undef VERSION/d' config.hin > config.hin2
 mv config.hin2 config.hin
 autoconf
-automake --copy --add-missing --foreign
+automake --copy --add-missing
diff --git a/configure.ac b/configure.ac
index 5abfe49..93d761d 100755
--- a/configure.ac
+++ b/configure.ac
@@ -24,7 +24,7 @@
 
 AC_CONFIG_AUX_DIR([.])
 
-AM_INIT_AUTOMAKE([1.13 subdir-objects tar-ustar])
+AM_INIT_AUTOMAKE([1.13 subdir-objects tar-ustar foreign])
 PKG_PROG_PKG_CONFIG
 
 AC_ARG_VAR([PY_PREFIX], [Prefix for installing Python modules.
diff --git a/lib/c_glib/test/CMakeLists.txt b/lib/c_glib/test/CMakeLists.txt
index 94c87e2..c46014d 100644
--- a/lib/c_glib/test/CMakeLists.txt
+++ b/lib/c_glib/test/CMakeLists.txt
@@ -20,9 +20,7 @@
 
 set(TEST_PREFIX "c_glib")
 
-# include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
-
-#Make sure gen-cpp and gen-c_glib files can be included
+# Make sure gen-cpp and gen-c_glib files can be included
 include_directories("${CMAKE_CURRENT_BINARY_DIR}")
 
 # Create the thrift C test library
@@ -151,7 +149,6 @@
 
 
 if(BUILD_CPP)
-
     include_directories("${PROJECT_SOURCE_DIR}/lib/cpp/src")
 
     # Create the thrift C++ test library
diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.cpp b/lib/cpp/src/thrift/transport/TSSLSocket.cpp
index 9efc5fc..665f8f6 100644
--- a/lib/cpp/src/thrift/transport/TSSLSocket.cpp
+++ b/lib/cpp/src/thrift/transport/TSSLSocket.cpp
@@ -489,7 +489,7 @@
               && (errno_copy != THRIFT_EAGAIN)) {
             break;
           }
-        // fallthrough        
+        // fallthrough
         case SSL_ERROR_WANT_READ:
         case SSL_ERROR_WANT_WRITE:
           if (isLibeventSafe()) {
@@ -970,10 +970,12 @@
   if (strcmp(format, "PEM") == 0) {
     BIO* mem = BIO_new(BIO_s_mem());
     BIO_puts(mem, aCertificate);
-    X509* cert = PEM_read_bio_X509(mem, nullptr, 0, nullptr);
+    X509* cert = PEM_read_bio_X509(mem, nullptr, nullptr, nullptr);
     BIO_free(mem);
+    const int status = SSL_CTX_use_certificate(ctx_->get(), cert);
+    X509_free(cert);
 
-    if (SSL_CTX_use_certificate(ctx_->get(), cert) == 0) {
+    if (status != 1) {
       int errno_copy = THRIFT_GET_SOCKET_ERROR;
       string errors;
       buildErrors(errors, errno_copy);
@@ -1005,12 +1007,18 @@
                               "loadPrivateKey: either <path> or <format> is nullptr");
   }
   if (strcmp(format, "PEM") == 0) {
-    BIO* mem = BIO_new(BIO_s_mem());
+    EVP_PKEY* cert;
+    BIO* mem;
+
+    mem = BIO_new(BIO_s_mem());
     BIO_puts(mem, aPrivateKey);
-    EVP_PKEY* cert = PEM_read_bio_PrivateKey(mem, nullptr, nullptr, nullptr);
+    cert = PEM_read_bio_PrivateKey(mem, nullptr, nullptr, nullptr);
 
     BIO_free(mem);
-    if (SSL_CTX_use_PrivateKey(ctx_->get(), cert) == 0) {
+    const int status = SSL_CTX_use_PrivateKey(ctx_->get(), cert);
+    EVP_PKEY_free(cert);
+
+    if (status == 0) {
       int errno_copy = THRIFT_GET_SOCKET_ERROR;
       string errors;
       buildErrors(errors, errno_copy);
@@ -1040,12 +1048,15 @@
                               "loadTrustedCertificates: aCertificate is empty");
   }
   X509_STORE* vX509Store = SSL_CTX_get_cert_store(ctx_->get());
+
   BIO* mem = BIO_new(BIO_s_mem());
   BIO_puts(mem, aCertificate);
-  X509* cert = PEM_read_bio_X509(mem, nullptr, 0, nullptr);
+  X509* cert = PEM_read_bio_X509(mem, nullptr, nullptr, nullptr);
   BIO_free(mem);
+  const int status = X509_STORE_add_cert(vX509Store, cert);
+  X509_free(cert);
 
-  if (X509_STORE_add_cert(vX509Store, cert) == 0) {
+  if (status != 1) {
     int errno_copy = THRIFT_GET_SOCKET_ERROR;
     string errors;
     buildErrors(errors, errno_copy);
@@ -1055,10 +1066,14 @@
   if (aChain) {
     mem = BIO_new(BIO_s_mem());
     BIO_puts(mem, aChain);
-    cert = PEM_read_bio_X509(mem, nullptr, 0, nullptr);
+    cert = PEM_read_bio_X509(mem, nullptr, nullptr, nullptr);
     BIO_free(mem);
 
+    // NOTE: The x509 certificate provided to SSL_CTX_add_extra_chain_cert()
+    // will be freed by the library when the SSL_CTX is destroyed. Do not free
+    // the x509 object manually here.
     if (SSL_CTX_add_extra_chain_cert(ctx_->get(), cert) == 0) {
+      X509_free(cert);
       int errno_copy = THRIFT_GET_SOCKET_ERROR;
       string errors;
       buildErrors(errors, errno_copy);
diff --git a/lib/cpp/test/CMakeLists.txt b/lib/cpp/test/CMakeLists.txt
index 3263b66..07c178d 100644
--- a/lib/cpp/test/CMakeLists.txt
+++ b/lib/cpp/test/CMakeLists.txt
@@ -20,7 +20,7 @@
 # Unit tests still require boost
 include(BoostMacros)
 REQUIRE_BOOST_HEADERS()
-set(BOOST_COMPONENTS chrono date_time filesystem random thread unit_test_framework)
+set(BOOST_COMPONENTS filesystem thread unit_test_framework)
 REQUIRE_BOOST_LIBRARIES(BOOST_COMPONENTS)
 
 include(ThriftMacros)
@@ -88,11 +88,11 @@
 target_link_libraries(UnitTests testgencpp ${Boost_LIBRARIES})
 LINK_AGAINST_THRIFT_LIBRARY(UnitTests thrift)
 add_test(NAME UnitTests COMMAND UnitTests)
-if ( MSVC )
+if(MSVC)
     # Disable C4503: decorated name length exceeded, name was truncated
     # 'insanity' results in very long decorated names
     set_property( TARGET UnitTests APPEND_STRING PROPERTY COMPILE_FLAGS /wd4503 )
-endif ( MSVC )
+endif()
 
 
 set( TInterruptTest_SOURCES
@@ -111,7 +111,7 @@
 )
 LINK_AGAINST_THRIFT_LIBRARY(TInterruptTest thrift)
 if (NOT MSVC AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT MINGW)
-target_link_libraries(TInterruptTest -lrt)
+    target_link_libraries(TInterruptTest -lrt)
 endif ()
 add_test(NAME TInterruptTest COMMAND TInterruptTest -- "${CMAKE_CURRENT_SOURCE_DIR}/../../../test/keys")
 
@@ -122,7 +122,7 @@
 )
 LINK_AGAINST_THRIFT_LIBRARY(TServerIntegrationTest thrift)
 if (NOT MSVC AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT MINGW)
-target_link_libraries(TServerIntegrationTest -lrt)
+    target_link_libraries(TServerIntegrationTest -lrt)
 endif ()
 add_test(NAME TServerIntegrationTest COMMAND TServerIntegrationTest)
 
@@ -205,13 +205,13 @@
 
 # The debug run-time in Windows asserts on isprint() with negative inputs
 if (NOT MSVC OR (MSVC AND CMAKE_BUILD_TYPE EQUAL "DEBUG"))
-add_executable(DebugProtoTest DebugProtoTest.cpp)
-target_link_libraries(DebugProtoTest
-    testgencpp
-    ${Boost_LIBRARIES}
-)
-LINK_AGAINST_THRIFT_LIBRARY(DebugProtoTest thrift)
-add_test(NAME DebugProtoTest COMMAND DebugProtoTest)
+    add_executable(DebugProtoTest DebugProtoTest.cpp)
+    target_link_libraries(DebugProtoTest
+        testgencpp
+        ${Boost_LIBRARIES}
+    )
+    LINK_AGAINST_THRIFT_LIBRARY(DebugProtoTest thrift)
+    add_test(NAME DebugProtoTest COMMAND DebugProtoTest)
 endif()
 
 add_executable(JSONProtoTest JSONProtoTest.cpp)
@@ -270,44 +270,44 @@
 add_test(NAME link_test COMMAND link_test)
 
 if(WITH_LIBEVENT)
-set(processor_test_SOURCES
-    processor/ProcessorTest.cpp
-    processor/EventLog.cpp
-    processor/ServerThread.cpp
-    processor/EventLog.h
-    processor/Handlers.h
-    processor/ServerThread.h
-)
-add_executable(processor_test ${processor_test_SOURCES})
-target_link_libraries(processor_test
-    testgencpp_cob
-    ${Boost_LIBRARIES}
-)
-LINK_AGAINST_THRIFT_LIBRARY(processor_test thriftnb)
-add_test(NAME processor_test COMMAND processor_test)
+    set(processor_test_SOURCES
+        processor/ProcessorTest.cpp
+        processor/EventLog.cpp
+        processor/ServerThread.cpp
+        processor/EventLog.h
+        processor/Handlers.h
+        processor/ServerThread.h
+    )
+    add_executable(processor_test ${processor_test_SOURCES})
+    target_link_libraries(processor_test
+        testgencpp_cob
+        ${Boost_LIBRARIES}
+    )
+    LINK_AGAINST_THRIFT_LIBRARY(processor_test thriftnb)
+    add_test(NAME processor_test COMMAND processor_test)
 
-set(TNonblockingServerTest_SOURCES TNonblockingServerTest.cpp)
-add_executable(TNonblockingServerTest ${TNonblockingServerTest_SOURCES})
-include_directories(${LIBEVENT_INCLUDE_DIRS})
-target_link_libraries(TNonblockingServerTest
-    testgencpp_cob
-    ${Boost_LIBRARIES}
-)
-LINK_AGAINST_THRIFT_LIBRARY(TNonblockingServerTest thriftnb)
-add_test(NAME TNonblockingServerTest COMMAND TNonblockingServerTest)
+    set(TNonblockingServerTest_SOURCES TNonblockingServerTest.cpp)
+    add_executable(TNonblockingServerTest ${TNonblockingServerTest_SOURCES})
+    include_directories(${LIBEVENT_INCLUDE_DIRS})
+    target_link_libraries(TNonblockingServerTest
+        testgencpp_cob
+        ${Boost_LIBRARIES}
+    )
+    LINK_AGAINST_THRIFT_LIBRARY(TNonblockingServerTest thriftnb)
+    add_test(NAME TNonblockingServerTest COMMAND TNonblockingServerTest)
 
-if(OPENSSL_FOUND AND WITH_OPENSSL)
-  set(TNonblockingSSLServerTest_SOURCES TNonblockingSSLServerTest.cpp)
-  add_executable(TNonblockingSSLServerTest ${TNonblockingSSLServerTest_SOURCES})
-  include_directories(${LIBEVENT_INCLUDE_DIRS})
-  target_link_libraries(TNonblockingSSLServerTest
-    testgencpp_cob
-    ${Boost_LIBRARIES}
-  )
-  LINK_AGAINST_THRIFT_LIBRARY(TNonblockingSSLServerTest thriftnb)
-  add_test(NAME TNonblockingSSLServerTest COMMAND TNonblockingSSLServerTest -- "${CMAKE_CURRENT_SOURCE_DIR}/../../../test/keys")
-endif(OPENSSL_FOUND AND WITH_OPENSSL)
-endif(WITH_LIBEVENT)
+    if(OPENSSL_FOUND AND WITH_OPENSSL)
+      set(TNonblockingSSLServerTest_SOURCES TNonblockingSSLServerTest.cpp)
+      add_executable(TNonblockingSSLServerTest ${TNonblockingSSLServerTest_SOURCES})
+      include_directories(${LIBEVENT_INCLUDE_DIRS})
+      target_link_libraries(TNonblockingSSLServerTest
+        testgencpp_cob
+        ${Boost_LIBRARIES}
+      )
+      LINK_AGAINST_THRIFT_LIBRARY(TNonblockingSSLServerTest thriftnb)
+      add_test(NAME TNonblockingSSLServerTest COMMAND TNonblockingSSLServerTest -- "${CMAKE_CURRENT_SOURCE_DIR}/../../../test/keys")
+    endif(OPENSSL_FOUND AND WITH_OPENSSL)
+endif()
 
 if(OPENSSL_FOUND AND WITH_OPENSSL)
 add_executable(OpenSSLManualInitTest OpenSSLManualInitTest.cpp)
@@ -325,7 +325,7 @@
 )
 LINK_AGAINST_THRIFT_LIBRARY(SecurityTest thrift)
 if (NOT MSVC AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT MINGW)
-target_link_libraries(SecurityTest -lrt)
+    target_link_libraries(SecurityTest -lrt)
 endif ()
 add_test(NAME SecurityTest COMMAND SecurityTest -- "${CMAKE_CURRENT_SOURCE_DIR}/../../../test/keys")
 
@@ -336,14 +336,14 @@
 )
 LINK_AGAINST_THRIFT_LIBRARY(SecurityFromBufferTest thrift)
 if (NOT MSVC AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT MINGW)
-target_link_libraries(SecurityFromBufferTest -lrt)
+    target_link_libraries(SecurityFromBufferTest -lrt)
 endif ()
 add_test(NAME SecurityFromBufferTest COMMAND SecurityFromBufferTest -- "${CMAKE_CURRENT_SOURCE_DIR}/../../../test/keys")
 
 endif()
 
 if(WITH_QT5)
-add_subdirectory(qt)
+    add_subdirectory(qt)
 endif()
 
 #
diff --git a/lib/cpp/test/SecurityTest.cpp b/lib/cpp/test/SecurityTest.cpp
index 982a4f3..b70729c 100644
--- a/lib/cpp/test/SecurityTest.cpp
+++ b/lib/cpp/test/SecurityTest.cpp
@@ -219,6 +219,7 @@
     try
     {
         // matrix of connection success between client and server with different SSLProtocol selections
+        static_assert(apache::thrift::transport::LATEST == 5, "Mismatch in assumed number of ssl protocols");
         bool matrix[apache::thrift::transport::LATEST + 1][apache::thrift::transport::LATEST + 1] =
         {
     //   server    = SSLTLS   SSLv2    SSLv3    TLSv1_0  TLSv1_1  TLSv1_2
diff --git a/lib/delphi/src/Thrift.Protocol.Compact.pas b/lib/delphi/src/Thrift.Protocol.Compact.pas
index 665cfc4..424b267 100644
--- a/lib/delphi/src/Thrift.Protocol.Compact.pas
+++ b/lib/delphi/src/Thrift.Protocol.Compact.pas
@@ -80,6 +80,9 @@
       STRUCT        = $0C
     );
 
+  private type
+    TEightBytesArray = packed array[0..7] of Byte;
+
   strict private const
     ttypeToCompactType : array[TType] of Types = (
       Types.STOP,           // Stop    = 0,
@@ -190,7 +193,7 @@
     class function intToZigZag( const n : Integer) : Cardinal;
 
     //Convert a Int64 into little-endian bytes in buf starting at off and going until off+7.
-    class procedure fixedLongToBytes( const n : Int64; var buf : TBytes);
+    class procedure fixedLongToBytes( const n : Int64; var buf : TEightBytesArray); inline;
 
   strict protected
     function GetMinSerializedSize( const aType : TType) : Integer;  override;
@@ -240,7 +243,7 @@
     // Note that it's important that the mask bytes are Int64 literals,
     // otherwise they'll default to ints, and when you shift an Integer left 56 bits,
     // you just get a messed up Integer.
-    class function bytesToLong( const bytes : TBytes) : Int64;
+    class function bytesToLong( const bytes : TEightBytesArray) : Int64; inline;
 
     // type testing and converting
     class function isBoolType( const b : byte) : Boolean;
@@ -319,10 +322,9 @@
 
 // Write an i32 as a varint. Results in 1-5 bytes on the wire.
 procedure TCompactProtocolImpl.WriteVarint32( n : Cardinal);
-var i32buf : TBytes;
-    idx : Integer;
+var idx : Integer;
+    i32buf : packed array[0..4] of Byte;
 begin
-  SetLength( i32buf, 5);
   idx := 0;
   while TRUE do begin
     ASSERT( idx < Length(i32buf));
@@ -339,7 +341,7 @@
     n := n shr 7;
   end;
 
-  Transport.Write( i32buf, 0, idx);
+  Transport.Write( @i32buf[0], 0, idx);
 end;
 
 
@@ -521,10 +523,10 @@
 
 // Write a double to the wire as 8 bytes.
 procedure TCompactProtocolImpl.WriteDouble( const dub: Double);
-var data : TBytes;
+var data : TEightBytesArray;
 begin
   fixedLongToBytes( DoubleToInt64Bits(dub), data);
-  Transport.Write( data);
+  Transport.Write( @data[0], 0, SizeOf(data));
 end;
 
 
@@ -580,10 +582,9 @@
 
 // Write an i64 as a varint. Results in 1-10 bytes on the wire.
 procedure TCompactProtocolImpl.WriteVarint64( n : UInt64);
-var varint64out : TBytes;
-    idx : Integer;
+var idx : Integer;
+    varint64out : packed array[0..9] of Byte;
 begin
-  SetLength( varint64out, 10);
   idx := 0;
   while TRUE do begin
     ASSERT( idx < Length(varint64out));
@@ -600,7 +601,7 @@
     n := n shr 7;
   end;
 
-  Transport.Write( varint64out, 0, idx);
+  Transport.Write( @varint64out[0], 0, idx);
 end;
 
 
@@ -627,9 +628,9 @@
 
 
 // Convert a Int64 into 8 little-endian bytes in buf
-class procedure TCompactProtocolImpl.fixedLongToBytes( const n : Int64; var buf : TBytes);
+class procedure TCompactProtocolImpl.fixedLongToBytes( const n : Int64; var buf : TEightBytesArray);
 begin
-  SetLength( buf, 8);
+  ASSERT( Length(buf) >= 8);
   buf[0] := Byte( n         and $FF);
   buf[1] := Byte((n shr 8)  and $FF);
   buf[2] := Byte((n shr 16) and $FF);
@@ -829,11 +830,11 @@
 
 
 // No magic here - just Read a double off the wire.
-function TCompactProtocolImpl.ReadDouble:Double;
-var longBits : TBytes;
+function TCompactProtocolImpl.ReadDouble : Double;
+var longBits : TEightBytesArray;
 begin
-  SetLength( longBits, 8);
-  Transport.ReadAll( longBits, 0, 8);
+  ASSERT( SizeOf(longBits) = SizeOf(result));
+  Transport.ReadAll( @longBits[0], SizeOf(longBits), 0, SizeOf(longBits));
   result := Int64BitsToDouble( bytesToLong( longBits));
 end;
 
@@ -934,7 +935,7 @@
 // Note that it's important that the mask bytes are Int64 literals,
 // otherwise they'll default to ints, and when you shift an Integer left 56 bits,
 // you just get a messed up Integer.
-class function TCompactProtocolImpl.bytesToLong( const bytes : TBytes) : Int64;
+class function TCompactProtocolImpl.bytesToLong( const bytes : TEightBytesArray) : Int64;
 begin
   ASSERT( Length(bytes) >= 8);
   result := (Int64(bytes[7] and $FF) shl 56) or
@@ -1104,7 +1105,7 @@
 procedure TestLongBytes;
 
   procedure Test( const test : Int64);
-  var buf : TBytes;
+  var buf : TCompactProtocolImpl.TEightBytesArray;
   begin
     TCompactProtocolImpl.fixedLongToBytes( test, buf);
     ASSERT( TCompactProtocolImpl.bytesToLong( buf) = test, IntToStr(test));
diff --git a/lib/delphi/src/Thrift.Protocol.JSON.pas b/lib/delphi/src/Thrift.Protocol.JSON.pas
index 61cad8b..515d85c 100644
--- a/lib/delphi/src/Thrift.Protocol.JSON.pas
+++ b/lib/delphi/src/Thrift.Protocol.JSON.pas
@@ -32,6 +32,7 @@
   Thrift.Configuration,
   Thrift.Transport,
   Thrift.Protocol,
+  Thrift.Stream,
   Thrift.Utils;
 
 type
@@ -832,7 +833,7 @@
 
 
 function TJSONProtocolImpl.ReadJSONString( skipContext : Boolean) : TBytes;
-var buffer : TMemoryStream;
+var buffer : TThriftMemoryStream;
     ch  : Byte;
     wch : Word;
     highSurogate: Char;
@@ -841,7 +842,7 @@
     tmp : TBytes;
 begin
   highSurogate := #0;
-  buffer := TMemoryStream.Create;
+  buffer := TThriftMemoryStream.Create;
   try
     if not skipContext
     then FContext.Read;
diff --git a/lib/delphi/src/Thrift.Serializer.pas b/lib/delphi/src/Thrift.Serializer.pas
index cb62603..8ee8a35 100644
--- a/lib/delphi/src/Thrift.Serializer.pas
+++ b/lib/delphi/src/Thrift.Serializer.pas
@@ -38,7 +38,7 @@
   // Generic utility for easily serializing objects into a byte array or Stream.
   TSerializer = class
   strict private
-    FStream    : TMemoryStream;
+    FStream    : TThriftMemoryStream;
     FTransport : ITransport;
     FProtocol  : IProtocol;
 
@@ -59,7 +59,7 @@
   // Generic utility for easily deserializing objects from byte array or Stream.
   TDeserializer = class
   strict private
-    FStream    : TMemoryStream;
+    FStream    : TThriftMemoryStream;
     FTransport : ITransport;
     FProtocol  : IProtocol;
 
@@ -92,7 +92,7 @@
 begin
   inherited Create;
 
-  FStream    := TMemoryStream.Create;
+  FStream    := TThriftMemoryStream.Create;
   adapter    := TThriftStreamAdapterDelphi.Create( FStream, FALSE);
 
   FTransport := TStreamTransportImpl.Create( nil, adapter, aConfig);
@@ -170,7 +170,7 @@
 begin
   inherited Create;
 
-  FStream    := TMemoryStream.Create;
+  FStream    := TThriftMemoryStream.Create;
   adapter    := TThriftStreamAdapterDelphi.Create( FStream, FALSE);
 
   FTransport := TStreamTransportImpl.Create( adapter, nil, aConfig);
diff --git a/lib/delphi/src/Thrift.Stream.pas b/lib/delphi/src/Thrift.Stream.pas
index 1668059..6c1320d 100644
--- a/lib/delphi/src/Thrift.Stream.pas
+++ b/lib/delphi/src/Thrift.Stream.pas
@@ -108,10 +108,52 @@
     constructor Create( const aStream: IStream);
   end;
 
+
+  TThriftMemoryStream = class(TMemoryStream)
+  strict protected
+    FInitialCapacity : NativeInt;
+  public
+    constructor Create( const aInitialCapacity : NativeInt = 4096);
+
+    // reimplemented
+    procedure Clear;
+
+    // make it publicly visible
+    property Capacity;
+  end;
+
+
+
 implementation
 
 uses Thrift.Transport;
 
+
+{ TThriftMemoryStream }
+
+constructor TThriftMemoryStream.Create( const aInitialCapacity : NativeInt);
+begin
+  inherited Create;
+  FInitialCapacity := aInitialCapacity;
+  Clear;
+end;
+
+
+procedure TThriftMemoryStream.Clear;
+// reimplemented to keep initial capacity
+begin
+  Position := 0;
+  Size     := 0;
+
+  // primary goal: minimize costly reallocations (performance!)
+  // secondary goal: prevent costly ressource over-allocations
+  if (FInitialCapacity >= 1024*1024)        // if we are talking about MB
+  or ((Capacity div 2) > FInitialCapacity)  // or the allocated buffer is really large
+  or (Capacity < FInitialCapacity)          // or we are actually below the limit
+  then Capacity := FInitialCapacity;
+end;
+
+
 { TThriftStreamAdapterCOM }
 
 procedure TThriftStreamAdapterCOM.Close;
diff --git a/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas b/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas
index 6704c12..398e275 100644
--- a/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas
+++ b/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas
@@ -106,7 +106,7 @@
   FReadTimeout       := XMLHTTP_SENDRECV_TIMEOUT;
 
   FCustomHeaders := TThriftDictionaryImpl<string,string>.Create;
-  FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
+  FOutputStream := TThriftStreamAdapterDelphi.Create( TThriftMemoryStream.Create, True);
 end;
 
 function TMsxmlHTTPClientImpl.CreateRequest: IXMLHTTPRequest;
@@ -202,7 +202,7 @@
 
 procedure TMsxmlHTTPClientImpl.Open;
 begin
-  FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
+  FOutputStream := TThriftStreamAdapterDelphi.Create( TThriftMemoryStream.Create, True);
 end;
 
 procedure TMsxmlHTTPClientImpl.Close;
@@ -217,7 +217,7 @@
     SendRequest;
   finally
     FOutputStream := nil;
-    FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
+    FOutputStream := TThriftStreamAdapterDelphi.Create( TThriftMemoryStream.Create, True);
     ASSERT( FOutputStream <> nil);
   end;
 end;
@@ -239,13 +239,13 @@
 procedure TMsxmlHTTPClientImpl.SendRequest;
 var
   xmlhttp : IXMLHTTPRequest;
-  ms : TMemoryStream;
+  ms : TThriftMemoryStream;
   a : TBytes;
   len : Integer;
 begin
   xmlhttp := CreateRequest;
 
-  ms := TMemoryStream.Create;
+  ms := TThriftMemoryStream.Create;
   try
     a := FOutputStream.ToArray;
     len := Length(a);
diff --git a/lib/delphi/src/Thrift.Transport.WinHTTP.pas b/lib/delphi/src/Thrift.Transport.WinHTTP.pas
index b0f32ef..746611d 100644
--- a/lib/delphi/src/Thrift.Transport.WinHTTP.pas
+++ b/lib/delphi/src/Thrift.Transport.WinHTTP.pas
@@ -41,7 +41,7 @@
   strict private
     FUri : string;
     FInputStream : IThriftStream;
-    FOutputMemoryStream : TMemoryStream;
+    FOutputMemoryStream : TThriftMemoryStream;
     FDnsResolveTimeout : Integer;
     FConnectionTimeout : Integer;
     FSendTimeout : Integer;
@@ -127,7 +127,7 @@
   FSecureProtocols := DEFAULT_THRIFT_SECUREPROTOCOLS;
 
   FCustomHeaders := TThriftDictionaryImpl<string,string>.Create;
-  FOutputMemoryStream := TMemoryStream.Create;
+  FOutputMemoryStream := TThriftMemoryStream.Create;
 end;
 
 destructor TWinHTTPClientImpl.Destroy;
@@ -269,7 +269,7 @@
 procedure TWinHTTPClientImpl.Open;
 begin
   FreeAndNil( FOutputMemoryStream);
-  FOutputMemoryStream := TMemoryStream.Create;
+  FOutputMemoryStream := TThriftMemoryStream.Create;
 end;
 
 procedure TWinHTTPClientImpl.Close;
@@ -284,7 +284,7 @@
     SendRequest;
   finally
     FreeAndNil( FOutputMemoryStream);
-    FOutputMemoryStream := TMemoryStream.Create;
+    FOutputMemoryStream := TThriftMemoryStream.Create;
     ASSERT( FOutputMemoryStream <> nil);
   end;
 end;
diff --git a/lib/delphi/src/Thrift.Transport.pas b/lib/delphi/src/Thrift.Transport.pas
index 79fc977..558b65e 100644
--- a/lib/delphi/src/Thrift.Transport.pas
+++ b/lib/delphi/src/Thrift.Transport.pas
@@ -334,8 +334,8 @@
   strict private
     FStream : IThriftStream;
     FBufSize : Integer;
-    FReadBuffer : TMemoryStream;
-    FWriteBuffer : TMemoryStream;
+    FReadBuffer : TThriftMemoryStream;
+    FWriteBuffer : TThriftMemoryStream;
   strict protected
     procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override;
     function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override;
@@ -450,8 +450,8 @@
   strict protected type
     TFramedHeader = Int32;
   strict protected
-    FWriteBuffer : TMemoryStream;
-    FReadBuffer : TMemoryStream;
+    FWriteBuffer : TThriftMemoryStream;
+    FReadBuffer : TThriftMemoryStream;
 
     procedure InitWriteBuffer;
     procedure ReadFrame;
@@ -1053,8 +1053,8 @@
   inherited Create;
   FStream := aStream;
   FBufSize := aBufSize;
-  FReadBuffer := TMemoryStream.Create;
-  FWriteBuffer := TMemoryStream.Create;
+  FReadBuffer := TThriftMemoryStream.Create(FBufSize);
+  FWriteBuffer := TThriftMemoryStream.Create(FBufSize);
 end;
 
 destructor TBufferedStreamImpl.Destroy;
@@ -1379,16 +1379,11 @@
   Result := InnerTransport.IsOpen;
 end;
 
-type
-  TAccessMemoryStream = class(TMemoryStream)
-  end;
-
 procedure TFramedTransportImpl.InitWriteBuffer;
 const DUMMY_HEADER : TFramedHeader = 0;
 begin
   FreeAndNil( FWriteBuffer);
-  FWriteBuffer := TMemoryStream.Create;
-  TAccessMemoryStream(FWriteBuffer).Capacity := 1024;
+  FWriteBuffer := TThriftMemoryStream.Create(1024);
   FWriteBuffer.Write( DUMMY_HEADER, SizeOf(DUMMY_HEADER));
 end;
 
@@ -1448,7 +1443,7 @@
   InnerTransport.ReadAll( buff, 0, size );
 
   FreeAndNil( FReadBuffer);
-  FReadBuffer := TMemoryStream.Create;
+  FReadBuffer := TThriftMemoryStream.Create(1024);
   if Length(buff) > 0
   then FReadBuffer.Write( Pointer(@buff[0])^, size );
   FReadBuffer.Position := 0;
diff --git a/lib/java/src/org/apache/thrift/transport/TIOStreamTransport.java b/lib/java/src/org/apache/thrift/transport/TIOStreamTransport.java
index 763e66a..d5b459c 100644
--- a/lib/java/src/org/apache/thrift/transport/TIOStreamTransport.java
+++ b/lib/java/src/org/apache/thrift/transport/TIOStreamTransport.java
@@ -26,6 +26,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.net.SocketTimeoutException;
 
 /**
  * This is the most commonly used base transport. It takes an InputStream or
@@ -174,6 +175,8 @@
     int bytesRead;
     try {
       bytesRead = inputStream_.read(buf, off, len);
+    } catch (SocketTimeoutException ste) {
+      throw new TTransportException(TTransportException.TIMED_OUT, ste);
     } catch (IOException iox) {
       throw new TTransportException(TTransportException.UNKNOWN, iox);
     }