Skip to content

Commit

Permalink
Chunk extension names cannot contain CTLs, spaces or (){}|<>@,;:\"/[]…
Browse files Browse the repository at this point in the history
…?=. Chunk extension values can, provided they are quoted.

Ref #236
  • Loading branch information
stephenharris committed Aug 30, 2016
1 parent 4041e0a commit 2f1b5dc
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 4 deletions.
6 changes: 4 additions & 2 deletions library/Requests.php
Original file line number Diff line number Diff line change
Expand Up @@ -749,15 +749,17 @@ public static function parse_multiple(&$response, $request) {
* @return string Decoded body
*/
protected static function decode_chunked($data) {
if (!preg_match('/^([0-9a-f]+)(?:;[^\r\n]*)*\r\n/i', trim($data))) {
if (!preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', trim($data))) {
return $data;
}



$decoded = '';
$encoded = $data;

while (true) {
$is_chunked = (bool) preg_match('/^([0-9a-f]+)(?:;[^\r\n]*)*\r\n/i', $encoded, $matches);
$is_chunked = (bool) preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', $encoded, $matches);
if (!$is_chunked) {
// Looks like it's not chunked after all
return $data;
Expand Down
24 changes: 22 additions & 2 deletions tests/ChunkedEncoding.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ public static function chunkedProvider() {
"02;foo=bar;hello=world\r\nab\r\n04;foo=baz\r\nra\nc\r\n06;justfoo\r\nadabra\r\n0c\r\n\nall we got\n",
"abra\ncadabra\nall we got\n"
),
array(
"02;foo=\"quoted value\"\r\nab\r\n04\r\nra\nc\r\n06\r\nadabra\r\n0c\r\n\nall we got\n",
"abra\ncadabra\nall we got\n"
),
array(
"02;foo-bar=baz\r\nab\r\n04\r\nra\nc\r\n06\r\nadabra\r\n0c\r\n\nall we got\n",
"abra\ncadabra\nall we got\n"
),
);
}

Expand All @@ -38,12 +46,24 @@ public function testChunked($body, $expected){
$this->assertEquals($expected, $response->body);
}

public static function notChunkedProvider() {
return array(
'invalid chunk size' => array( 'Hello! This is a non-chunked response!' ),
'invalid chunk extension' => array( '1BNot chunked\r\nLooks chunked but it is not\r\n' ),
'unquoted chunk-ext-val with space' => array( "02;foo=unquoted with space\r\nab\r\n04\r\nra\nc\r\n06\r\nadabra\r\n0c\r\n\nall we got\n" ),
'unquoted chunk-ext-val with forbidden character' => array( "02;foo={unquoted}\r\nab\r\n04\r\nra\nc\r\n06\r\nadabra\r\n0c\r\n\nall we got\n" ),
'invalid chunk-ext-name' => array( "02;{foo}=bar\r\nab\r\n04\r\nra\nc\r\n06\r\nadabra\r\n0c\r\n\nall we got\n" ),
'incomplete quote for chunk-ext-value' => array( "02;foo=\"no end quote\r\nab\r\n04\r\nra\nc\r\n06\r\nadabra\r\n0c\r\n\nall we got\n" ),
);
}

/**
* Response says it's chunked, but actually isn't
* @dataProvider notChunkedProvider
*/
public function testNotActuallyChunked() {
public function testNotActuallyChunked($body) {
$transport = new MockTransport();
$transport->body = "Believe me\r\nthis looks chunked, but it isn't.";
$transport->body = $body;
$transport->chunked = true;

$options = array(
Expand Down

0 comments on commit 2f1b5dc

Please sign in to comment.