Skip to content

Commit 58bc906

Browse files
committed
Limit ChunkedDecoder trailer size to avoid unbounded buffering
1 parent b6d4688 commit 58bc906

2 files changed

Lines changed: 20 additions & 0 deletions

File tree

‎src/Io/ChunkedDecoder.php‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ public function handleData($data)
158158
} elseif ($this->chunkSize === 0) {
159159
if ($positionCrlf === false) {
160160
// end chunk received, but trailer is incomplete
161+
// trailer shouldn't be bigger than 1024 bytes
162+
if (isset($this->buffer[static::MAX_CHUNK_HEADER_SIZE])) {
163+
$this->handleError(new Exception('Trailer size bigger than ' . static::MAX_CHUNK_HEADER_SIZE . ' bytes'));
164+
}
161165
return;
162166
}
163167
// end chunk received, skip all trailer data

‎tests/Io/ChunkedDecoderTest.php‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,22 @@ public function testEndChunkWithIncompleteTrailerWillEndOnceTrailerIsCompleted()
523523
$this->input->emit('data', array("\r\n\r\n"));
524524
}
525525

526+
public function testEndChunkWithIncompleteTrailerIsTooBig()
527+
{
528+
$this->parser->on('data', $this->expectCallableNever());
529+
$this->parser->on('close', $this->expectCallableOnce());
530+
$this->parser->on('end', $this->expectCallableNever());
531+
$this->parser->on('error', $this->expectCallableOnce());
532+
533+
$data = '';
534+
for ($i = 0; $i < 1025; $i++) {
535+
$data .= 'a';
536+
}
537+
538+
// incomplete trailer must not be buffered without any limit
539+
$this->input->emit('data', array("0\r\n" . $data));
540+
}
541+
526542
public function testChunkFollowedByExactlyTwoNonCrlfBytesWillErrorAndNotCauseInfiniteLoop()
527543
{
528544
$this->parser->on('data', $this->expectCallableOnceWith('ab'));

0 commit comments

Comments
 (0)