From 24c3ef2474c6daa20ed48168d46196a55346dfd8 Mon Sep 17 00:00:00 2001 From: xiplus Date: Sat, 25 Mar 2023 22:00:34 +0800 Subject: [PATCH] Fix infinite loop for self-redirects with variants conversion The redirect targets another variant, but the target does not exist. It causes infinite loop when querying the page with the redirect and converttitles flags are both set. Check the mConvertTitles to stop re-resolving the same title. Bug: T333050 Change-Id: I64c5886dbd0a9148eeff033ba56306bcb7f2eb8c --- includes/api/ApiPageSet.php | 4 +- tests/phpunit/includes/api/ApiPageSetTest.php | 59 +++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/includes/api/ApiPageSet.php b/includes/api/ApiPageSet.php index 1f5bd6c6c6922..39611d1b62d4a 100644 --- a/includes/api/ApiPageSet.php +++ b/includes/api/ApiPageSet.php @@ -1281,7 +1281,9 @@ private function loadRedirectTargets() { unset( $this->mPendingRedirectIDs[$rdfrom] ); if ( $to->isExternal() ) { $this->mInterwikiTitles[$to->getPrefixedText()] = $to->getInterwiki(); - } elseif ( !isset( $this->mAllPages[$to->getNamespace()][$to->getDBkey()] ) ) { + } elseif ( !isset( $this->mAllPages[$to->getNamespace()][$to->getDBkey()] ) + && !( $this->mConvertTitles && isset( $this->mConvertedTitles[$to->getPrefixedText()] ) ) + ) { $titlesToResolve[] = $to; } $this->mRedirectTitles[$from] = $to; diff --git a/tests/phpunit/includes/api/ApiPageSetTest.php b/tests/phpunit/includes/api/ApiPageSetTest.php index 0154994e10ad9..1498f0144fe3a 100644 --- a/tests/phpunit/includes/api/ApiPageSetTest.php +++ b/tests/phpunit/includes/api/ApiPageSetTest.php @@ -139,6 +139,65 @@ public function testHandleNormalization() { ); } + public static function provideConversionWithRedirects() { + return [ + 'convert, redirect, convert' => [ + [ + [ '維基百科1', '#REDIRECT [[维基百科2]]' ], + [ '維基百科2', '' ], + ], + [ 'titles' => '维基百科1', 'converttitles' => 1, 'redirects' => 1 ], + [ [ 'from' => '维基百科1', 'to' => '維基百科1' ], [ 'from' => '维基百科2', 'to' => '維基百科2' ] ], + [ [ 'from' => '維基百科1', 'to' => '维基百科2' ] ], + ], + + 'redirect, convert, redirect' => [ + [ + [ '維基百科3', '#REDIRECT [[维基百科4]]' ], + [ '維基百科4', '#REDIRECT [[維基百科5]]' ], + ], + [ 'titles' => '維基百科3', 'converttitles' => 1, 'redirects' => 1 ], + [ [ 'from' => '维基百科4', 'to' => '維基百科4' ] ], + [ [ 'from' => '維基百科3', 'to' => '维基百科4' ], [ 'from' => '維基百科4', 'to' => '維基百科5' ] ], + ], + + 'hans redirects to hant with converttitles' => [ + [ + [ '维基百科6', '#REDIRECT [[維基百科6]]' ], + ], + [ 'titles' => '维基百科6', 'converttitles' => 1, 'redirects' => 1 ], + [ [ 'from' => '維基百科6', 'to' => '维基百科6' ] ], + [ [ 'from' => '维基百科6', 'to' => '維基百科6' ] ], + ], + + 'hans redirects to hant without converttitles' => [ + [ + [ '维基百科6', '#REDIRECT [[維基百科6]]' ], + ], + [ 'titles' => '维基百科6', 'redirects' => 1 ], + [], + [ [ 'from' => '维基百科6', 'to' => '維基百科6' ] ], + ], + ]; + } + + /** + * @dataProvider provideConversionWithRedirects + */ + public function testHandleConversionWithRedirects( $pages, $params, $expectConversion, $exceptRedirects ) { + $this->overrideConfigValue( MainConfigNames::LanguageCode, 'zh' ); + + foreach ( $pages as $page ) { + $this->editPage( $page[0], $page[1] ); + } + + $pageSet = $this->newApiPageSet( $params ); + $pageSet->execute(); + + $this->assertSame( $expectConversion, $pageSet->getConvertedTitlesAsResult() ); + $this->assertSame( $exceptRedirects, $pageSet->getRedirectTitlesAsResult() ); + } + public function testSpecialRedirects() { $id1 = $this->editPage( 'UTApiPageSet', 'UTApiPageSet in the default language' ) ->getNewRevision()->getPageId();