From a511e3511cace405dab7589a3406a0858cb6edf2 Mon Sep 17 00:00:00 2001 From: Patrick Nelson Date: Fri, 28 Apr 2017 01:32:18 -0700 Subject: [PATCH] FIX #6855: Mangled JS in Requirements, escaping replacement values prior to passing to preg_replace(). --- view/Requirements.php | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/view/Requirements.php b/view/Requirements.php index 4b1bd7b33..971b943e4 100644 --- a/view/Requirements.php +++ b/view/Requirements.php @@ -869,10 +869,10 @@ class Requirements_Backend { // Forcefully put the scripts at the bottom of the body instead of before the first // script tag. - $replacements["/(<\/body[^>]*>)/i"] = $jsRequirements . "\\1"; + $replacements["/(<\/body[^>]*>)/i"] = $this->escapeReplacement($jsRequirements) . "\\1"; // Put CSS at the bottom of the head - $replacements["/(<\/head>)/i"] = $requirements . "\\1"; + $replacements["/(<\/head>)/i"] = $this->escapeReplacement($requirements) . "\\1"; } elseif ($this->write_js_to_body) { $jsRequirements = $this->removeNewlinesFromCode($jsRequirements); @@ -894,14 +894,14 @@ class Requirements_Backend { if ($canWriteToBody) { $content = substr($content, 0, $p1) . $jsRequirements . substr($content, $p1); } else { - $replacements["/(<\/body[^>]*>)/i"] = $jsRequirements . "\\1"; + $replacements["/(<\/body[^>]*>)/i"] = $this->escapeReplacement($jsRequirements) . "\\1"; } // Put CSS at the bottom of the head - $replacements["/(<\/head>)/i"] = $requirements . "\\1"; + $replacements["/(<\/head>)/i"] = $this->escapeReplacement($requirements) . "\\1"; } else { // Put CSS and Javascript together before the closing head tag - $replacements["/(<\/head>)/i"] = $requirements . $jsRequirements. "\\1"; + $replacements["/(<\/head>)/i"] = $this->escapeReplacement($requirements . $jsRequirements) . "\\1"; } if (!empty($replacements)) { @@ -923,6 +923,16 @@ class Requirements_Backend { return preg_replace('/>\n*/', '>', $code); } + /** + * Safely escape a literal string for use in preg_replace replacement + * + * @param string $replacement + * @return string + */ + protected function escapeReplacement($replacement) { + return addcslashes($replacement, '\\$'); + } + /** * Attach requirements inclusion to X-Include-JS and X-Include-CSS headers on the given * HTTP Response