Skip to content

Commit ea359d3

Browse files
authored
Merge pull request #236 from stephenharris/bugfix/rfc2616-chunk-decoding-bug
Fixes bug in rfc2616 #3.6.1 implementation.
2 parents 1c39a78 + 2f1b5dc commit ea359d3

2 files changed

Lines changed: 31 additions & 4 deletions

File tree

library/Requests.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -749,15 +749,17 @@ public static function parse_multiple(&$response, $request) {
749749
* @return string Decoded body
750750
*/
751751
protected static function decode_chunked($data) {
752-
if (!preg_match('/^([0-9a-f]+)[^\r\n]*\r\n/i', trim($data))) {
752+
if (!preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', trim($data))) {
753753
return $data;
754754
}
755755

756+
757+
756758
$decoded = '';
757759
$encoded = $data;
758760

759761
while (true) {
760-
$is_chunked = (bool) preg_match('/^([0-9a-f]+)[^\r\n]*\r\n/i', $encoded, $matches);
762+
$is_chunked = (bool) preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', $encoded, $matches);
761763
if (!$is_chunked) {
762764
// Looks like it's not chunked after all
763765
return $data;

tests/ChunkedEncoding.php

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,18 @@ public static function chunkedProvider() {
1515
"02\r\nab\r\n04\r\nra\nc\r\n06\r\nadabra\r\n0c\r\n\nall we got\n",
1616
"abra\ncadabra\nall we got\n"
1717
),
18+
array(
19+
"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",
20+
"abra\ncadabra\nall we got\n"
21+
),
22+
array(
23+
"02;foo=\"quoted value\"\r\nab\r\n04\r\nra\nc\r\n06\r\nadabra\r\n0c\r\n\nall we got\n",
24+
"abra\ncadabra\nall we got\n"
25+
),
26+
array(
27+
"02;foo-bar=baz\r\nab\r\n04\r\nra\nc\r\n06\r\nadabra\r\n0c\r\n\nall we got\n",
28+
"abra\ncadabra\nall we got\n"
29+
),
1830
);
1931
}
2032

@@ -34,12 +46,24 @@ public function testChunked($body, $expected){
3446
$this->assertEquals($expected, $response->body);
3547
}
3648

49+
public static function notChunkedProvider() {
50+
return array(
51+
'invalid chunk size' => array( 'Hello! This is a non-chunked response!' ),
52+
'invalid chunk extension' => array( '1BNot chunked\r\nLooks chunked but it is not\r\n' ),
53+
'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" ),
54+
'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" ),
55+
'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" ),
56+
'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" ),
57+
);
58+
}
59+
3760
/**
3861
* Response says it's chunked, but actually isn't
62+
* @dataProvider notChunkedProvider
3963
*/
40-
public function testNotActuallyChunked() {
64+
public function testNotActuallyChunked($body) {
4165
$transport = new MockTransport();
42-
$transport->body = 'Hello! This is a non-chunked response!';
66+
$transport->body = $body;
4367
$transport->chunked = true;
4468

4569
$options = array(
@@ -50,6 +74,7 @@ public function testNotActuallyChunked() {
5074
$this->assertEquals($transport->body, $response->body);
5175
}
5276

77+
5378
/**
5479
* Response says it's chunked and starts looking like it is, but turns out
5580
* that they're lying to us

0 commit comments

Comments
 (0)