From dcde0d4b75a8196c6e6ab8f894a3b217d86fd3b0 Mon Sep 17 00:00:00 2001 From: "Nathan J. Brauer" Date: Sat, 14 Oct 2023 15:15:36 -0700 Subject: [PATCH] Infinite recursion protections Fixes internal infinite recursion on Nginx/PHP-FPM builds and implements some protections against unanticipated infinite recursions (previously timed out or hit memory limits) --- src/Controllers/ShareDraftController.php | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/Controllers/ShareDraftController.php b/src/Controllers/ShareDraftController.php index 3ea1914..8b22327 100644 --- a/src/Controllers/ShareDraftController.php +++ b/src/Controllers/ShareDraftController.php @@ -52,6 +52,11 @@ class ShareDraftController extends Controller */ protected static $isViewingPreview = false; + /** + * @var array + */ + private $redirectRecursionIterations = []; + /** * @return bool */ @@ -172,8 +177,11 @@ private function getRenderedPageByURL(string $url): HTTPResponse $variables['_SERVER']['HTTP_USER_AGENT'] = isset($variables['_SERVER']['HTTP_USER_AGENT']) && $variables['_SERVER']['HTTP_USER_AGENT'] - ? $variables['_SERVER']['HTTP_USER_AGENT'] - : 'CLI'; + ? $variables['_SERVER']['HTTP_USER_AGENT'] + : 'CLI'; + + // This extra step required for PHP-FPM/Nginx implementations + $variables['env'] = $variables['_SERVER']; Environment::setVariables($variables); @@ -183,6 +191,15 @@ private function getRenderedPageByURL(string $url): HTTPResponse $response = Director::singleton()->handleRequest($pageRequest); if ($response->isRedirect()) { + if (in_array($url, $this->redirectRecursionIterations)) { + throw new \Exception("Infinite recursion detected. \n\nRedirected URLs stack: \n" . implode("\n", $this->redirectRecursionIterations) . "\n$url"); + } + + $this->redirectRecursionIterations[] = $url; + if (count($this->redirectRecursionIterations) >= 30) { + throw new \Exception("Max redirect recursions reached. \n\nRedirected URLs stack: \n" . implode("\n", $this->redirectRecursionIterations)); + } + // The redirect will probably be Absolute URL so just want the path $newUrl = parse_url($response->getHeader('location') ?? '', PHP_URL_PATH);