@@ -50,18 +50,34 @@ class AwsChunkedStreamBuf : public std::streambuf {
5050 return traits_type::to_int_type (*gptr ());
5151 }
5252
53+ // Compact buffer when consumed data exceeds half buffer size
54+ if (m_chunkingBufferPos > m_chunkingBuffer.GetLength () / 2 ) {
55+ size_t remaining = m_chunkingBufferSize - m_chunkingBufferPos;
56+ if (remaining > 0 ) {
57+ std::memmove (m_chunkingBuffer.GetUnderlyingData (),
58+ m_chunkingBuffer.GetUnderlyingData () + m_chunkingBufferPos,
59+ remaining);
60+ }
61+ m_chunkingBufferSize = remaining;
62+ m_chunkingBufferPos = 0 ;
63+ }
64+
5365 // only read and write to chunked stream if the underlying stream
54- // is still in a valid state
66+ // is still in a valid state and we have buffer space
5567 if (m_stream->good ()) {
56- // Try to read in a 64K chunk, if we cant we know the stream is over
57- m_stream->read (m_data.GetUnderlyingData (), m_data.GetLength ());
58- size_t bytesRead = static_cast <size_t >(m_stream->gcount ());
59- writeChunk (bytesRead);
60-
61- // if we've read everything from the stream, we want to add the trailer
62- // to the underlying stream
63- if ((m_stream->peek () == EOF || m_stream->eof ()) && !m_stream->bad ()) {
64- writeTrailerToUnderlyingStream ();
68+ // Check if we have enough space for worst-case chunk (data + header + footer)
69+ size_t maxChunkSize = m_data.GetLength () + 20 ; // data + hex header + CRLF
70+ if (m_chunkingBufferSize + maxChunkSize <= m_chunkingBuffer.GetLength ()) {
71+ // Try to read in a 64K chunk, if we cant we know the stream is over
72+ m_stream->read (m_data.GetUnderlyingData (), m_data.GetLength ());
73+ size_t bytesRead = static_cast <size_t >(m_stream->gcount ());
74+ writeChunk (bytesRead);
75+
76+ // if we've read everything from the stream, we want to add the trailer
77+ // to the underlying stream
78+ if ((m_stream->peek () == EOF || m_stream->eof ()) && !m_stream->bad ()) {
79+ writeTrailerToUnderlyingStream ();
80+ }
6581 }
6682 }
6783
@@ -80,18 +96,6 @@ class AwsChunkedStreamBuf : public std::streambuf {
8096
8197 m_chunkingBufferPos += bytesToRead;
8298
83- // Compact buffer when consumed data exceeds half buffer size
84- if (m_chunkingBufferPos > m_chunkingBuffer.GetLength () / 2 ) {
85- size_t remaining = m_chunkingBufferSize - m_chunkingBufferPos;
86- if (remaining > 0 ) {
87- std::memmove (m_chunkingBuffer.GetUnderlyingData (),
88- m_chunkingBuffer.GetUnderlyingData () + m_chunkingBufferPos,
89- remaining);
90- }
91- m_chunkingBufferSize = remaining;
92- m_chunkingBufferPos = 0 ;
93- }
94-
9599 return traits_type::to_int_type (*gptr ());
96100 }
97101
@@ -116,12 +120,15 @@ class AwsChunkedStreamBuf : public std::streambuf {
116120
117121 if (bytesRead > 0 ) {
118122 Aws::String chunkHeader = Aws::Utils::StringUtils::ToHexString (bytesRead) + " \r\n " ;
119- std::memcpy (m_chunkingBuffer.GetUnderlyingData () + m_chunkingBufferSize, chunkHeader.c_str (), chunkHeader.length ());
120- m_chunkingBufferSize += chunkHeader.length ();
121- std::memcpy (m_chunkingBuffer.GetUnderlyingData () + m_chunkingBufferSize, m_data.GetUnderlyingData (), bytesRead);
122- m_chunkingBufferSize += bytesRead;
123- std::memcpy (m_chunkingBuffer.GetUnderlyingData () + m_chunkingBufferSize, " \r\n " , 2 );
124- m_chunkingBufferSize += 2 ;
123+ size_t totalSize = chunkHeader.length () + bytesRead + 2 ;
124+ if (m_chunkingBufferSize + totalSize <= m_chunkingBuffer.GetLength ()) {
125+ std::memcpy (m_chunkingBuffer.GetUnderlyingData () + m_chunkingBufferSize, chunkHeader.c_str (), chunkHeader.length ());
126+ m_chunkingBufferSize += chunkHeader.length ();
127+ std::memcpy (m_chunkingBuffer.GetUnderlyingData () + m_chunkingBufferSize, m_data.GetUnderlyingData (), bytesRead);
128+ m_chunkingBufferSize += bytesRead;
129+ std::memcpy (m_chunkingBuffer.GetUnderlyingData () + m_chunkingBufferSize, " \r\n " , 2 );
130+ m_chunkingBufferSize += 2 ;
131+ }
125132 }
126133 }
127134
0 commit comments