From 8cbf9759435a0715e0695cc0f7f0a08fd7955997 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 16 Nov 2014 23:34:34 -0500 Subject: [PATCH] Gracefully handle invalid chunks in HttpSocket When invalid chunks are detected we should assume the server is incorrect and handle the remaining content as a single large chunk. Refs #5140 --- lib/Cake/Network/Http/HttpSocketResponse.php | 23 ++++++++++--------- .../Case/Network/Http/HttpResponseTest.php | 6 ++--- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/lib/Cake/Network/Http/HttpSocketResponse.php b/lib/Cake/Network/Http/HttpSocketResponse.php index 03474f385..99d875c31 100644 --- a/lib/Cake/Network/Http/HttpSocketResponse.php +++ b/lib/Cake/Network/Http/HttpSocketResponse.php @@ -221,28 +221,29 @@ class HttpSocketResponse implements ArrayAccess { $chunkLength = null; while ($chunkLength !== 0) { - if (!preg_match('/^([0-9a-f]+) *(?:;(.+)=(.+))?(?:\r\n|\n)/iU', $body, $match)) { - throw new SocketException(__d('cake_dev', 'HttpSocket::_decodeChunkedBody - Could not parse malformed chunk.')); + if (!preg_match('/^([0-9a-f]+)[ ]*(?:;(.+)=(.+))?(?:\r\n|\n)/iU', $body, $match)) { + // Handle remaining invalid data as one big chunk. + preg_match('/^(.*?)\r\n/', $body, $invalidMatch); + $length = isset($invalidMatch[1]) ? strlen($invalidMatch[1]) : 0; + $match = array( + 0 => '', + 1 => dechex($length) + ); } - $chunkSize = 0; $hexLength = 0; - $chunkExtensionValue = ''; if (isset($match[0])) { $chunkSize = $match[0]; } if (isset($match[1])) { $hexLength = $match[1]; } - if (isset($match[3])) { - $chunkExtensionValue = $match[3]; - } - $body = substr($body, strlen($chunkSize)); $chunkLength = hexdec($hexLength); - $chunk = substr($body, 0, $chunkLength); - $decodedBody .= $chunk; - if ($chunkLength !== 0) { + $body = substr($body, strlen($chunkSize)); + + $decodedBody .= substr($body, 0, $chunkLength); + if ($chunkLength) { $body = substr($body, $chunkLength + strlen("\r\n")); } } diff --git a/lib/Cake/Test/Case/Network/Http/HttpResponseTest.php b/lib/Cake/Test/Case/Network/Http/HttpResponseTest.php index 54493a6b8..502340094 100644 --- a/lib/Cake/Test/Case/Network/Http/HttpResponseTest.php +++ b/lib/Cake/Test/Case/Network/Http/HttpResponseTest.php @@ -15,7 +15,6 @@ * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ - App::uses('HttpResponse', 'Network/Http'); /** @@ -453,12 +452,13 @@ class HttpResponseTest extends CakeTestCase { /** * testDecodeChunkedBodyError method * - * @expectedException SocketException * @return void */ public function testDecodeChunkedBodyError() { $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n"; - $this->HttpResponse->decodeChunkedBody($encoded); + $result = $this->HttpResponse->decodeChunkedBody($encoded); + $expected = "This is a chunked message\nThat is cool\n"; + $this->assertEquals($expected, $result['body']); } /**