From e4e4ed6c008c983645b4eee6b67d8f258cde54df Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 31 May 2020 07:14:17 +0200 Subject: [PATCH 1/9] updated VERSION for 3.4.41 --- Kernel.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Kernel.php b/Kernel.php index dc9cc048eb..00382a95c1 100644 --- a/Kernel.php +++ b/Kernel.php @@ -67,11 +67,11 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private $requestStackSize = 0; private $resetServices = false; - const VERSION = '3.4.40'; - const VERSION_ID = 30440; + const VERSION = '3.4.41'; + const VERSION_ID = 30441; const MAJOR_VERSION = 3; const MINOR_VERSION = 4; - const RELEASE_VERSION = 40; + const RELEASE_VERSION = 41; const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2020'; From 05ff4a5cc1f1d3e24c93e2a19d55288eb306dbcb Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 31 May 2020 07:24:17 +0200 Subject: [PATCH 2/9] bumped Symfony version to 3.4.42 --- Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Kernel.php b/Kernel.php index 00382a95c1..a0eb026f60 100644 --- a/Kernel.php +++ b/Kernel.php @@ -67,12 +67,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private $requestStackSize = 0; private $resetServices = false; - const VERSION = '3.4.41'; - const VERSION_ID = 30441; + const VERSION = '3.4.42-DEV'; + const VERSION_ID = 30442; const MAJOR_VERSION = 3; const MINOR_VERSION = 4; - const RELEASE_VERSION = 41; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 42; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2020'; const END_OF_LIFE = '11/2021'; From 54526b598d7fc86a67850488b194a88a79ab8467 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 31 May 2020 07:25:51 +0200 Subject: [PATCH 3/9] updated VERSION for 4.4.9 --- Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Kernel.php b/Kernel.php index 438ef37f34..49c7ab594a 100644 --- a/Kernel.php +++ b/Kernel.php @@ -76,12 +76,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private static $freshCache = []; - const VERSION = '4.4.9-DEV'; + const VERSION = '4.4.9'; const VERSION_ID = 40409; const MAJOR_VERSION = 4; const MINOR_VERSION = 4; const RELEASE_VERSION = 9; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2022'; const END_OF_LIFE = '11/2023'; From 9b5f471bbbaf8645a863e79b1ae50752ee5340c6 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 31 May 2020 07:29:28 +0200 Subject: [PATCH 4/9] bumped Symfony version to 4.4.10 --- Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Kernel.php b/Kernel.php index 49c7ab594a..f0a2ee8d29 100644 --- a/Kernel.php +++ b/Kernel.php @@ -76,12 +76,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private static $freshCache = []; - const VERSION = '4.4.9'; - const VERSION_ID = 40409; + const VERSION = '4.4.10-DEV'; + const VERSION_ID = 40410; const MAJOR_VERSION = 4; const MINOR_VERSION = 4; - const RELEASE_VERSION = 9; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 10; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2022'; const END_OF_LIFE = '11/2023'; From 265ded949f51fc573376d47265e0003af765053b Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 31 May 2020 08:13:19 +0200 Subject: [PATCH 5/9] bumped Symfony version to 5.0.10 --- Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Kernel.php b/Kernel.php index 25111f3bc4..7ed8adc6b6 100644 --- a/Kernel.php +++ b/Kernel.php @@ -68,12 +68,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private static $freshCache = []; - const VERSION = '5.0.9'; - const VERSION_ID = 50009; + const VERSION = '5.0.10-DEV'; + const VERSION_ID = 50010; const MAJOR_VERSION = 5; const MINOR_VERSION = 0; - const RELEASE_VERSION = 9; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 10; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '07/2020'; const END_OF_LIFE = '07/2020'; From f972768badff84285bbf15ec5a92fbeff4e813d4 Mon Sep 17 00:00:00 2001 From: Thomas Landauer Date: Sun, 7 Jun 2020 21:29:41 +0200 Subject: [PATCH 6/9] Update welcome.html.php --- Resources/welcome.html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/welcome.html.php b/Resources/welcome.html.php index e1c0ff1192..b8337dc737 100644 --- a/Resources/welcome.html.php +++ b/Resources/welcome.html.php @@ -65,7 +65,7 @@
- You're seeing this page because you haven't configured any homepage URL. + You're seeing this page because you haven't configured any homepage URL and debug mode is enabled.
From 746fd7ae6330c57da3dd454b979bc9f9fd3410e1 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Wed, 10 Jun 2020 08:28:31 +0000 Subject: [PATCH 7/9] [HttpKernel] Fix regression where Store does not return response body correctly --- HttpCache/Store.php | 41 +++++++++++++++++++++++------------ Tests/HttpCache/StoreTest.php | 33 ++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 14 deletions(-) diff --git a/HttpCache/Store.php b/HttpCache/Store.php index fd04a7b23d..72793f582d 100644 --- a/HttpCache/Store.php +++ b/HttpCache/Store.php @@ -152,8 +152,8 @@ public function lookup(Request $request) } $headers = $match[1]; - if (file_exists($body = $this->getPath($headers['x-content-digest'][0]))) { - return $this->restoreResponse($headers, $body); + if (file_exists($path = $this->getPath($headers['x-content-digest'][0]))) { + return $this->restoreResponse($headers, $path); } // TODO the metaStore referenced an entity that doesn't exist in @@ -177,15 +177,28 @@ public function write(Request $request, Response $response) $key = $this->getCacheKey($request); $storedEnv = $this->persistRequest($request); - $digest = $this->generateContentDigest($response); - $response->headers->set('X-Content-Digest', $digest); + if ($response->headers->has('X-Body-File')) { + // Assume the response came from disk, but at least perform some safeguard checks + if (!$response->headers->has('X-Content-Digest')) { + throw new \RuntimeException('A restored response must have the X-Content-Digest header.'); + } - if (!$this->save($digest, $response->getContent(), false)) { - throw new \RuntimeException('Unable to store the entity.'); - } + $digest = $response->headers->get('X-Content-Digest'); + if ($this->getPath($digest) !== $response->headers->get('X-Body-File')) { + throw new \RuntimeException('X-Body-File and X-Content-Digest do not match.'); + } + // Everything seems ok, omit writing content to disk + } else { + $digest = $this->generateContentDigest($response); + $response->headers->set('X-Content-Digest', $digest); - if (!$response->headers->has('Transfer-Encoding')) { - $response->headers->set('Content-Length', \strlen($response->getContent())); + if (!$this->save($digest, $response->getContent(), false)) { + throw new \RuntimeException('Unable to store the entity.'); + } + + if (!$response->headers->has('Transfer-Encoding')) { + $response->headers->set('Content-Length', \strlen($response->getContent())); + } } // read existing cache entries, remove non-varying, and add this one to the list @@ -477,19 +490,19 @@ private function persistResponse(Response $response) * Restores a Response from the HTTP headers and body. * * @param array $headers An array of HTTP headers for the Response - * @param string $body The Response body + * @param string $path Path to the Response body * * @return Response */ - private function restoreResponse($headers, $body = null) + private function restoreResponse($headers, $path = null) { $status = $headers['X-Status'][0]; unset($headers['X-Status']); - if (null !== $body) { - $headers['X-Body-File'] = [$body]; + if (null !== $path) { + $headers['X-Body-File'] = [$path]; } - return new Response($body, $status, $headers); + return new Response($path, $status, $headers); } } diff --git a/Tests/HttpCache/StoreTest.php b/Tests/HttpCache/StoreTest.php index 07c4154269..6754be45a1 100644 --- a/Tests/HttpCache/StoreTest.php +++ b/Tests/HttpCache/StoreTest.php @@ -118,6 +118,39 @@ public function testWritesResponseEvenIfXContentDigestIsPresent() $this->assertNotNull($response); } + public function testWritingARestoredResponseDoesNotCorruptCache() + { + /* + * This covers the regression reported in https://github.com/symfony/symfony/issues/37174. + * + * A restored response does *not* load the body, but only keep the file path in a special X-Body-File + * header. For reasons (?), the file path was also used as the restored response body. + * It would be up to others (HttpCache...?) to hohor this header and actually load the response content + * from there. + * + * When a restored response was stored again, the Store itself would ignore the header. In the first + * step, this would compute a new Content Digest based on the file path in the restored response body; + * this is covered by "Checkpoint 1" below. But, since the X-Body-File header was left untouched (Checkpoint 2), downstream + * code (HttpCache...) would not immediately notice. + * + * Only upon performing the lookup for a second time, we'd get a Response where the (wrong) Content Digest + * is also reflected in the X-Body-File header, this time also producing wrong content when the downstream + * evaluates it. + */ + $this->store->write($this->request, $this->response); + $digest = $this->response->headers->get('X-Content-Digest'); + $path = $this->getStorePath($digest); + + $response = $this->store->lookup($this->request); + $this->store->write($this->request, $response); + $this->assertEquals($digest, $response->headers->get('X-Content-Digest')); // Checkpoint 1 + $this->assertEquals($path, $response->headers->get('X-Body-File')); // Checkpoint 2 + + $response = $this->store->lookup($this->request); + $this->assertEquals($digest, $response->headers->get('X-Content-Digest')); + $this->assertEquals($path, $response->headers->get('X-Body-File')); + } + public function testFindsAStoredEntryWithLookup() { $this->storeSimpleEntry(); From 350cc5379a80cce3ac6ebf987b354361a12f80be Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 11 Jun 2020 15:00:25 +0200 Subject: [PATCH 8/9] Fix typo --- Tests/HttpCache/StoreTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/HttpCache/StoreTest.php b/Tests/HttpCache/StoreTest.php index 6754be45a1..eee8970b96 100644 --- a/Tests/HttpCache/StoreTest.php +++ b/Tests/HttpCache/StoreTest.php @@ -125,7 +125,7 @@ public function testWritingARestoredResponseDoesNotCorruptCache() * * A restored response does *not* load the body, but only keep the file path in a special X-Body-File * header. For reasons (?), the file path was also used as the restored response body. - * It would be up to others (HttpCache...?) to hohor this header and actually load the response content + * It would be up to others (HttpCache...?) to honor this header and actually load the response content * from there. * * When a restored response was stored again, the Store itself would ignore the header. In the first From 03b0be19b9b9df26e72713c3b8ce9e6ba8a259ff Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 12 Jun 2020 13:20:19 +0200 Subject: [PATCH 9/9] updated VERSION for 5.0.10 --- Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Kernel.php b/Kernel.php index 7ed8adc6b6..a43aa286e5 100644 --- a/Kernel.php +++ b/Kernel.php @@ -68,12 +68,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private static $freshCache = []; - const VERSION = '5.0.10-DEV'; + const VERSION = '5.0.10'; const VERSION_ID = 50010; const MAJOR_VERSION = 5; const MINOR_VERSION = 0; const RELEASE_VERSION = 10; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '07/2020'; const END_OF_LIFE = '07/2020';