Skip to content

Commit cb20945

Browse files
committed
Fix infinite loop when transmission cuts mid-chunk
Fixes #37
1 parent f9a88c3 commit cb20945

File tree

3 files changed

+32
-7
lines changed

3 files changed

+32
-7
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
StreamUtils - Change log
22
========================
33

4+
HEAD
5+
----
6+
7+
* Fix infinite loop in `ChunkDecodingPolicy` when transmission cuts mid-chunk (issue #37)
8+
49
1.9.0 (2024/07/10)
510
-----
611

extras/test/ChunkDecodingStreamTest.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ TEST_CASE("ChunkDecodingStream") {
298298
}
299299

300300
#if STREAMUTILS_STREAM_READBYTES_IS_VIRTUAL
301-
SUBCASE("readBytes() waits timeout") {
301+
SUBCASE("readBytes() waits timeout if transmission cuts before final chunk") {
302302
char buffer[32];
303303

304304
upstream.print(
@@ -308,7 +308,7 @@ TEST_CASE("ChunkDecodingStream") {
308308
REQUIRE(buffer[0] == 'X');
309309

310310
REQUIRE(log.str() ==
311-
"readBytes(1) -> 1" // 1
311+
"readBytes(1) -> 1" // 4
312312
"readBytes(1) -> 1" // \r
313313
"readBytes(1) -> 1" // \n
314314
"readBytes(4) -> 4" // XXXX
@@ -317,6 +317,23 @@ TEST_CASE("ChunkDecodingStream") {
317317
"readBytes(1) -> 0 [timeout]");
318318
}
319319

320+
// Issue #37
321+
SUBCASE("readBytes() waits timeout if transmission cuts mid-chunk") {
322+
char buffer[32];
323+
324+
upstream.print(
325+
"4\r\n"
326+
"XX");
327+
REQUIRE(stream.readBytes(buffer, 32) == 2);
328+
REQUIRE(buffer[0] == 'X');
329+
330+
REQUIRE(log.str() ==
331+
"readBytes(1) -> 1" // 4
332+
"readBytes(1) -> 1" // \r
333+
"readBytes(1) -> 1" // \n
334+
"readBytes(4) -> 2 [timeout]");
335+
}
336+
320337
SUBCASE("readBytes() doen't wait if final chunk received") {
321338
char buffer[32];
322339

src/StreamUtils/Policies/ChunkDecodingPolicy.hpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,14 @@ class ChunkDecodingPolicy {
7070
size_t doReadBytes(TTarget &target, char *buffer, size_t size) {
7171
size_t result = 0;
7272
while (size > 0 && !error() && !ended() && goToChunkBody(target, true)) {
73-
size_t n = readOrReadBytes(target, buffer, min_(size, remaining_));
74-
decreaseRemaining(n);
75-
result += n;
76-
size -= n;
77-
buffer += n;
73+
size_t requestedBytes = min_(size, remaining_);
74+
size_t returnedBytes = readOrReadBytes(target, buffer, requestedBytes);
75+
decreaseRemaining(returnedBytes);
76+
result += returnedBytes;
77+
size -= returnedBytes;
78+
buffer += returnedBytes;
79+
if (returnedBytes < requestedBytes)
80+
break; // no more data available right now
7881
}
7982
return result;
8083
}

0 commit comments

Comments
 (0)