Skip to content

Commit 71e7eb2

Browse files
committed
Allow terminating chunk to has variable number of zeros
1 parent 9a89475 commit 71e7eb2

File tree

2 files changed

+26
-14
lines changed

2 files changed

+26
-14
lines changed

src/ChunkedStreamDecoder.php

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,6 @@ 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-
9890
$crlfPosition = strpos($this->buffer, static::CRLF);
9991
if ($crlfPosition === false && strlen($this->buffer) > 1024) {
10092
$this->emit('error', [
@@ -106,17 +98,21 @@ protected function iterateBuffer()
10698
if ($crlfPosition === false) {
10799
return false; // Chunk header hasn't completely come in yet
108100
}
109-
$this->nextChunkIsLength = false;
110101
$lengthChunk = substr($this->buffer, 0, $crlfPosition);
111102
if (strpos($lengthChunk, ';') !== false) {
112103
list($lengthChunk) = explode(';', $lengthChunk, 2);
113104
}
114105
if ($lengthChunk !== '') {
115106
$lengthChunk = ltrim($lengthChunk, "0");
116107
if ($lengthChunk === '') {
117-
$lengthChunk = "0";
108+
// We've reached the end of the stream
109+
$this->reachedEnd = true;
110+
$this->emit('end');
111+
$this->close();
112+
return false;
118113
}
119114
}
115+
$this->nextChunkIsLength = false;
120116
if (dechex(hexdec($lengthChunk)) !== strtolower($lengthChunk)) {
121117
$this->emit('error', [
122118
new Exception('Unable to validate "' . $lengthChunk . '" as chunk length header'),

tests/DecodeChunkedStreamTest.php

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,19 @@ public function testInvalidChunkedEncoding(array $strings)
133133
}
134134
}
135135

136-
public function testHandleEnd()
136+
public function provideZeroChunk()
137+
{
138+
return [
139+
['1-zero' => "0\r\n\r\n"],
140+
['random-zero' => str_repeat("0", rand(2, 10))."\r\n\r\n"]
141+
];
142+
}
143+
144+
/**
145+
* @test
146+
* @dataProvider provideZeroChunk
147+
*/
148+
public function testHandleEnd($zeroChunk)
137149
{
138150
$ended = false;
139151
$stream = new ThroughStream();
@@ -145,7 +157,7 @@ public function testHandleEnd()
145157
$ended = true;
146158
});
147159

148-
$stream->write("4\r\nWiki\r\n0\r\n\r\n");
160+
$stream->write("4\r\nWiki\r\n".$zeroChunk);
149161

150162
$this->assertTrue($ended);
151163
}
@@ -181,7 +193,11 @@ public function testHandleEndTrailers()
181193
$this->assertTrue($ended);
182194
}
183195

184-
public function testHandleEndEnsureNoError()
196+
/**
197+
* @test
198+
* @dataProvider provideZeroChunk
199+
*/
200+
public function testHandleEndEnsureNoError($zeroChunk)
185201
{
186202
$ended = false;
187203
$stream = new ThroughStream();
@@ -194,7 +210,7 @@ public function testHandleEndEnsureNoError()
194210
});
195211

196212
$stream->write("4\r\nWiki\r\n");
197-
$stream->write("0\r\n\r\n");
213+
$stream->write($zeroChunk);
198214
$stream->end();
199215

200216
$this->assertTrue($ended);

0 commit comments

Comments
 (0)