From: Alexander Ebert Date: Fri, 18 Oct 2024 12:56:15 +0000 (+0200) Subject: Improve the script tag relocation for extremely large payloads X-Git-Tag: 6.1.0~10 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=647914ccf82801081d959959449c0b3df21dc784;p=GitHub%2FWoltLab%2FWCF.git 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/ --- 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) {