diff --git a/core/modules/page_cache/src/StackMiddleware/PageCache.php b/core/modules/page_cache/src/StackMiddleware/PageCache.php
index 51c2ae4..82456b1 100644
--- a/core/modules/page_cache/src/StackMiddleware/PageCache.php
+++ b/core/modules/page_cache/src/StackMiddleware/PageCache.php
@@ -260,10 +260,15 @@ protected function storeResponse(Request $request, Response $response) {
         $expire = $request_time + $cache_ttl_4xx;
       }
     }
-    else {
-      $date = $response->getExpires()->getTimestamp();
+    // The getExpires method could return NULL if Expires header is not set, so
+    // the returned value needs to be checked before calling getTimestamp.
+    elseif ($expires = $response->getExpires()) {
+      $date = $expires->getTimestamp();
       $expire = ($date > $request_time) ? $date : Cache::PERMANENT;
     }
+    else {
+      $expire = Cache::PERMANENT;
+    }
 
     if ($expire === Cache::PERMANENT || $expire > $request_time) {
       $tags = $response->getCacheableMetadata()->getCacheTags();
diff --git a/core/modules/page_cache/src/Tests/PageCacheTest.php b/core/modules/page_cache/src/Tests/PageCacheTest.php
index cb00cb6..179bba1 100644
--- a/core/modules/page_cache/src/Tests/PageCacheTest.php
+++ b/core/modules/page_cache/src/Tests/PageCacheTest.php
@@ -539,6 +539,19 @@ public function testHead() {
   }
 
   /**
+   * Test a cacheable response with custom cache control.
+   */
+  public function testCacheableWithCustomCacheControl() {
+    $config = $this->config('system.performance');
+    $config->set('cache.page.max_age', 300);
+    $config->save();
+
+    $this->drupalGet('/system-test/custom-cache-control');
+    $this->assertResponse(200);
+    $this->assertHeader('Cache-Control', 'bar, private');
+  }
+
+  /**
    * Test that URLs are cached in a not normalized form.
    */
   public function testNoUrlNormalization() {
diff --git a/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php b/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php
index 5e49c24..7f32ef3 100644
--- a/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php
+++ b/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php
@@ -375,4 +375,11 @@ public function getTestHeader(Request $request) {
     return $response;
   }
 
+  /**
+   * Returns a cacheable response with a custom cache control.
+   */
+  public function getCacheableWithCustomCacheControl() {
+    return new CacheableResponse('Foo', 200, ['Cache-Control' => 'bar']);
+  }
+
 }
diff --git a/core/modules/system/tests/modules/system_test/system_test.routing.yml b/core/modules/system/tests/modules/system_test/system_test.routing.yml
index 579b511..2b55df8 100644
--- a/core/modules/system/tests/modules/system_test/system_test.routing.yml
+++ b/core/modules/system/tests/modules/system_test/system_test.routing.yml
@@ -196,3 +196,11 @@ system_test.echo_utf8:
     _controller: '\Drupal\system_test\Controller\SystemTestController::simpleEcho'
   requirements:
     _access: 'TRUE'
+
+system_test.custom_cache_control:
+  path: '/system-test/custom-cache-control'
+  defaults:
+    _title: 'Cacheable response custom cache control'
+    _controller: '\Drupal\system_test\Controller\SystemTestController::getCacheableWithCustomCacheControl'
+  requirements:
+    _access: 'TRUE'
