From 647914ccf82801081d959959449c0b3df21dc784 Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Fri, 18 Oct 2024 14:56:15 +0200 Subject: [PATCH] Improve the script tag relocation for extremely large payloads The previous approach would hit backtracking limits when dealing with excessively large payloads. This could happen with extreme numbers of smileys that are all handled through a single script tag. See https://www.woltlab.com/community/thread/308944-fehlermeldung-unterhalb-des-footers/ --- .../files/lib/util/HeaderUtil.class.php | 47 ++++++++++++++----- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/wcfsetup/install/files/lib/util/HeaderUtil.class.php b/wcfsetup/install/files/lib/util/HeaderUtil.class.php index bd249efef6..4d2f97f404 100644 --- a/wcfsetup/install/files/lib/util/HeaderUtil.class.php +++ b/wcfsetup/install/files/lib/util/HeaderUtil.class.php @@ -165,21 +165,42 @@ final class HeaderUtil }, self::$output); } - // move script tags to the bottom of the page + // Move script tags to the bottom of the page. This splits up the output + // into chunks that effectively end with ``. This allows us to + // use a simple regex to find the start of the script tag and treating + // everything inbetween as the content of the script. + // + // The previous approach used a lazy match for the script content which + // could hit the backtracking limit for extremely large payloads. $javascript = []; - self::$output = \preg_replace_callback( - '~\s*~s', - static function ($matches) use (&$javascript) { - // Add an attribute to disable Cloudflare's Rocket Loader - if (!\str_contains($matches['attributes'], 'data-cfasync="false"')) { - $matches['attributes'] = ' data-cfasync="false"' . $matches['attributes']; - } + $segments = \preg_split('~~s', self::$output, flags: \PREG_SPLIT_NO_EMPTY); - $javascript[] = '' . $matches['script'] . ''; - return ''; - }, - self::$output - ); + self::$output = ''; + foreach ($segments as $segment) { + $hasMatch = false; + + self::$output .= \preg_replace_callback( + '~'; + + $hasMatch = true; + + return ''; + }, + $segment, + limit: 1 + ); + + if (!$hasMatch) { + self::$output .= ''; + } + } $placeholder = ''; if (($placeholderPosition = \strrpos(self::$output, $placeholder)) !== false) { -- 2.20.1