Use pool counter for generating large diffs to prevent DoS.
[lhc/web/wiklou.git] / includes / diff / DifferenceEngine.php
index 4fdacc5..8985d51 100644 (file)
@@ -474,7 +474,7 @@ class DifferenceEngine extends ContextSource {
                        if ( !$linkInfo ) {
                                $this->mMarkPatrolledLink = '';
                        } else {
-                               $this->mMarkPatrolledLink = ' <span class="patrollink">[' . Linker::linkKnown(
+                               $this->mMarkPatrolledLink = ' <span class="patrollink" data-mw="interface">[' . Linker::linkKnown(
                                        $this->mNewPage,
                                        $this->msg( 'markaspatrolleddiff' )->escaped(),
                                        [],
@@ -842,19 +842,36 @@ class DifferenceEngine extends ContextSource {
         * @return bool|string
         */
        public function generateTextDiffBody( $otext, $ntext ) {
-               $time = microtime( true );
+               $diff = function() use ( $otext, $ntext ) {
+                       $time = microtime( true );
 
-               $result = $this->textDiff( $otext, $ntext );
+                       $result = $this->textDiff( $otext, $ntext );
 
-               $time = intval( ( microtime( true ) - $time ) * 1000 );
-               $this->getStats()->timing( 'diff_time', $time );
-               // Log requests slower than 99th percentile
-               if ( $time > 100 && $this->mOldPage && $this->mNewPage ) {
-                       wfDebugLog( 'diff',
-                               "$time ms diff: {$this->mOldid} -> {$this->mNewid} {$this->mNewPage}" );
+                       $time = intval( ( microtime( true ) - $time ) * 1000 );
+                       $this->getStats()->timing( 'diff_time', $time );
+                       // Log requests slower than 99th percentile
+                       if ( $time > 100 && $this->mOldPage && $this->mNewPage ) {
+                               wfDebugLog( 'diff',
+                                       "$time ms diff: {$this->mOldid} -> {$this->mNewid} {$this->mNewPage}" );
+                       }
+
+                       return $result;
+               };
+
+               $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 $result;
+               return $diff();
        }
 
        /**
@@ -870,8 +887,8 @@ class DifferenceEngine extends ContextSource {
                $otext = str_replace( "\r\n", "\n", $otext );
                $ntext = str_replace( "\r\n", "\n", $ntext );
 
-               if ( $wgExternalDiffEngine == 'wikidiff' ) {
-                       wfDeprecated( 'wikidiff support', '1.27' );
+               if ( $wgExternalDiffEngine == 'wikidiff' || $wgExternalDiffEngine == 'wikidiff3' ) {
+                       wfDeprecated( "\$wgExternalDiffEngine = '{$wgExternalDiffEngine}'", '1.27' );
                        $wgExternalDiffEngine = false;
                }
 
@@ -884,7 +901,7 @@ class DifferenceEngine extends ContextSource {
 
                                return $text;
                        }
-               } elseif ( $wgExternalDiffEngine != 'wikidiff3' && $wgExternalDiffEngine !== false ) {
+               } elseif ( $wgExternalDiffEngine !== false ) {
                        # Diff via the shell
                        $tmpDir = wfTempDir();
                        $tempName1 = tempnam( $tmpDir, 'diff_' );
@@ -1152,19 +1169,6 @@ class DifferenceEngine extends ContextSource {
                return $header . $diff . "</table>";
        }
 
-       /**
-        * Use specified text instead of loading from the database
-        * @deprecated since 1.21, use setContent() instead.
-        */
-       public function setText( $oldText, $newText ) {
-               ContentHandler::deprecated( __METHOD__, "1.21" );
-
-               $oldContent = ContentHandler::makeContent( $oldText, $this->getTitle() );
-               $newContent = ContentHandler::makeContent( $newText, $this->getTitle() );
-
-               $this->setContent( $oldContent, $newContent );
-       }
-
        /**
         * Use specified text instead of loading from the database
         * @param Content $oldContent