Skip to content

Commit 26f43a2

Browse files
committed
Check if body end has reach when it is time for a length chunk and before attempting to extract the length. As the final one will always be zero. Also force one final iteration over the buffer when handling end
1 parent 07fa19d commit 26f43a2

2 files changed

Lines changed: 37 additions & 9 deletions

File tree

src/ChunkedStreamDecoder.php

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,14 @@ protected function iterateBuffer()
8787
}
8888

8989
if ($this->nextChunkIsLength) {
90+
if (substr($this->buffer, 0, 3) === "0\r\n") {
91+
// We've reached the end of the stream
92+
$this->reachedEnd = true;
93+
$this->emit('end');
94+
$this->close();
95+
return false;
96+
}
97+
9098
$crlfPosition = strpos($this->buffer, static::CRLF);
9199
if ($crlfPosition === false && strlen($this->buffer) > 1024) {
92100
$this->emit('error', [
@@ -131,13 +139,6 @@ protected function iterateBuffer()
131139

132140
$this->nextChunkIsLength = true;
133141
$this->buffer = substr($this->buffer, 2);
134-
135-
if (substr($this->buffer, 0, 3) === "0\r\n") {
136-
$this->reachedEnd = true;
137-
$this->emit('end');
138-
$this->close();
139-
return false;
140-
}
141142
return true;
142143
}
143144

@@ -183,6 +184,8 @@ public function close()
183184
/** @internal */
184185
public function handleEnd()
185186
{
187+
$this->handleData('');
188+
186189
if ($this->closed) {
187190
return;
188191
}

tests/DecodeChunkedStreamTest.php

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ public function testChunkedEncoding(array $strings, $expected = "Wikipedia in\r\
5858
$response->on('data', function ($data) use (&$buffer) {
5959
$buffer .= $data;
6060
});
61-
$response->on('error', function (Exception $exception) {
62-
throw $exception;
61+
$response->on('error', function ($error) {
62+
$this->fail((string)$error);
6363
});
6464
foreach ($strings as $string) {
6565
$stream->write($string);
@@ -104,6 +104,9 @@ public function testHandleEnd()
104104
$ended = false;
105105
$stream = new ThroughStream();
106106
$response = new ChunkedStreamDecoder($stream);
107+
$response->on('error', function ($error) {
108+
$this->fail((string)$error);
109+
});
107110
$response->on('end', function () use (&$ended) {
108111
$ended = true;
109112
});
@@ -132,6 +135,9 @@ public function testHandleEndTrailers()
132135
$ended = false;
133136
$stream = new ThroughStream();
134137
$response = new ChunkedStreamDecoder($stream);
138+
$response->on('error', function ($error) {
139+
$this->fail((string)$error);
140+
});
135141
$response->on('end', function () use (&$ended) {
136142
$ended = true;
137143
});
@@ -140,4 +146,23 @@ public function testHandleEndTrailers()
140146

141147
$this->assertTrue($ended);
142148
}
149+
150+
public function testHandleEndEnsureNoError()
151+
{
152+
$ended = false;
153+
$stream = new ThroughStream();
154+
$response = new ChunkedStreamDecoder($stream);
155+
$response->on('error', function ($error) {
156+
$this->fail((string)$error);
157+
});
158+
$response->on('end', function () use (&$ended) {
159+
$ended = true;
160+
});
161+
162+
$stream->write("4\r\nWiki\r\n");
163+
$stream->write("0\r\n\r\n");
164+
$stream->end();
165+
166+
$this->assertTrue($ended);
167+
}
143168
}

0 commit comments

Comments
 (0)