From ceaca43705cec58ddb6a240d2e4437e2ddaadae1 Mon Sep 17 00:00:00 2001
From: Brad Jorsch <bjorsch@wikimedia.org>
Date: Mon, 18 Jan 2016 12:00:41 -0500
Subject: [PATCH] SECURITY: Improve cross-domain-policy mangling

Take into account that the tag might have parameters.

Bug: T123653
Change-Id: Ie9799f5ea45badfb4e7b4be7e7fbc1c35cc86f26
---
 includes/OutputHandler.php                              | 4 ++--
 includes/api/ApiFormatJson.php                          | 4 ++--
 includes/api/ApiFormatPhp.php                           | 2 +-
 tests/phpunit/includes/api/format/ApiFormatJsonTest.php | 4 ++--
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/includes/OutputHandler.php b/includes/OutputHandler.php
index c9c326b..2f47006 100644
--- a/includes/OutputHandler.php
+++ b/includes/OutputHandler.php
@@ -154,8 +154,8 @@ function wfGzipHandler( $s ) {
  */
 function wfMangleFlashPolicy( $s ) {
 	# Avoid weird excessive memory usage in PCRE on big articles
-	if ( preg_match( '/\<\s*cross-domain-policy\s*\>/i', $s ) ) {
-		return preg_replace( '/\<\s*cross-domain-policy\s*\>/i', '<NOT-cross-domain-policy>', $s );
+	if ( preg_match( '/\<\s*cross-domain-policy(?=\s|\>)/i', $s ) ) {
+		return preg_replace( '/\<(\s*)(cross-domain-policy(?=\s|\>))/i', '<$1NOT-$2', $s );
 	} else {
 		return $s;
 	}
diff --git a/includes/api/ApiFormatJson.php b/includes/api/ApiFormatJson.php
index 36cbbd9..d2eebb1 100644
--- a/includes/api/ApiFormatJson.php
+++ b/includes/api/ApiFormatJson.php
@@ -103,9 +103,9 @@ class ApiFormatJson extends ApiFormatBase {
 		// Bug 66776: wfMangleFlashPolicy() is needed to avoid a nasty bug in
 		// Flash, but what it does isn't friendly for the API, so we need to
 		// work around it.
-		if ( preg_match( '/\<\s*cross-domain-policy\s*\>/i', $json ) ) {
+		if ( preg_match( '/\<\s*cross-domain-policy(?=\s|\>)/i', $json ) ) {
 			$json = preg_replace(
-				'/\<(\s*cross-domain-policy\s*)\>/i', '\\u003C$1\\u003E', $json
+				'/\<(\s*cross-domain-policy(?=\s|\>))/i', '\\u003C$1', $json
 			);
 		}
 
diff --git a/includes/api/ApiFormatPhp.php b/includes/api/ApiFormatPhp.php
index d111af5..fc25f47 100644
--- a/includes/api/ApiFormatPhp.php
+++ b/includes/api/ApiFormatPhp.php
@@ -65,7 +65,7 @@ class ApiFormatPhp extends ApiFormatBase {
 		// just be broken in a useful manner.
 		if ( $this->getConfig()->get( 'MangleFlashPolicy' ) &&
 			in_array( 'wfOutputHandler', ob_list_handlers(), true ) &&
-			preg_match( '/\<\s*cross-domain-policy\s*\>/i', $text )
+			preg_match( '/\<\s*cross-domain-policy(?=\s|\>)/i', $text )
 		) {
 			$this->dieUsage(
 				'This response cannot be represented using format=php. ' .
diff --git a/tests/phpunit/includes/api/format/ApiFormatJsonTest.php b/tests/phpunit/includes/api/format/ApiFormatJsonTest.php
index 8437228..7eb2a35 100644
--- a/tests/phpunit/includes/api/format/ApiFormatJsonTest.php
+++ b/tests/phpunit/includes/api/format/ApiFormatJsonTest.php
@@ -67,7 +67,7 @@ class ApiFormatJsonTest extends ApiFormatTestBase {
 				[ [ 1 ], '/**/myCallback([1])', [ 'callback' => 'myCallback' ] ],
 
 				// Cross-domain mangling
-				[ [ '< Cross-Domain-Policy >' ], '["\u003C Cross-Domain-Policy \u003E"]' ],
+				[ [ '< Cross-Domain-Policy >' ], '["\u003C Cross-Domain-Policy >"]' ],
 			] ),
 			self::addFormatVersion( 2, [
 				// Basic types
@@ -121,7 +121,7 @@ class ApiFormatJsonTest extends ApiFormatTestBase {
 				[ [ 1 ], '/**/myCallback([1])', [ 'callback' => 'myCallback' ] ],
 
 				// Cross-domain mangling
-				[ [ '< Cross-Domain-Policy >' ], '["\u003C Cross-Domain-Policy \u003E"]' ],
+				[ [ '< Cross-Domain-Policy >' ], '["\u003C Cross-Domain-Policy >"]' ],
 			] )
 		);
 	}
-- 
2.8.1

