From 2d1728ef050527952278cb1f0e690987176d6205 Mon Sep 17 00:00:00 2001
From: Max Semenik <maxsem.wiki@gmail.com>
Date: Fri, 4 Mar 2016 14:41:50 -0800
Subject: [PATCH] SECURITY: Wrap diff generation in PoolCounter

Bug: T130947
---
 includes/diff/DifferenceEngine.php | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/includes/diff/DifferenceEngine.php b/includes/diff/DifferenceEngine.php
index c138eec..1fd0c9f 100644
--- a/includes/diff/DifferenceEngine.php
+++ b/includes/diff/DifferenceEngine.php
@@ -823,6 +823,34 @@ class DifferenceEngine extends ContextSource {
 	 * @return bool|string
 	 */
 	public function generateTextDiffBody( $otext, $ntext ) {
+		$diff = function() use ( $otext, $ntext ) {
+			return $this->textDiff( $otext, $ntext );
+		};
+
+		$error = function( $status ) {
+			throw new FatalError( $status->getWikiText() );
+		};
+
+		// Use PoolCounter if the diff looks like it can be expensive
+		if ( strlen( $otext ) + strlen( $ntext ) > 20000 ) {
+			$work = new PoolCounterWorkViaCallback( 'diff',
+				md5( $otext ) . md5( $ntext ),
+				[ 'doWork' => $diff, 'error' => $error ]
+			);
+			return $work->execute();
+		}
+
+		return $diff();
+	}
+
+	/**
+	 * Generates diff, to be wrapped internally in a logging/instrumentation
+	 *
+	 * @param string $otext Old text, must be already segmented
+	 * @param string $ntext New text, must be already segmented
+	 * @return bool|string
+	 */
+	protected function textDiff( $otext, $ntext ) {
 		global $wgExternalDiffEngine, $wgContLang;
 
 		$otext = str_replace( "\r\n", "\n", $otext );
-- 
2.7.2

