From 13a1d8957b9d639c69cef251b831ed03319182b1 Mon Sep 17 00:00:00 2001 From: Roan Kattouw Date: Wed, 24 Oct 2018 17:09:59 -0700 Subject: [PATCH] WikiPage: Truncate redirect fragments before inserting them into the DB The rd_fragment field is 255 bytes wide, but there is no limit on how long title fragments can be. We don't want to let the database silently truncate the fragment for us, because that can result in invalid UTF-8. Instead, truncate it before insertion in a UTF-8-aware way. Bug: T207876 Change-Id: I12745f3f4c174eaced56d80f3661a71d0e5637e6 --- includes/page/WikiPage.php | 6 ++++-- tests/phpunit/includes/page/WikiPageDbTestBase.php | 11 ++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/includes/page/WikiPage.php b/includes/page/WikiPage.php index 18797d9443..d03d317043 100644 --- a/includes/page/WikiPage.php +++ b/includes/page/WikiPage.php @@ -1045,20 +1045,22 @@ class WikiPage implements Page, IDBAccessObject { $dbw->startAtomic( __METHOD__ ); if ( !$oldLatest || $oldLatest == $this->lockAndGetLatest() ) { + $contLang = MediaWikiServices::getInstance()->getContentLanguage(); + $truncatedFragment = $contLang->truncateForDatabase( $rt->getFragment(), 255 ); $dbw->upsert( 'redirect', [ 'rd_from' => $this->getId(), 'rd_namespace' => $rt->getNamespace(), 'rd_title' => $rt->getDBkey(), - 'rd_fragment' => $rt->getFragment(), + 'rd_fragment' => $truncatedFragment, 'rd_interwiki' => $rt->getInterwiki(), ], [ 'rd_from' ], [ 'rd_namespace' => $rt->getNamespace(), 'rd_title' => $rt->getDBkey(), - 'rd_fragment' => $rt->getFragment(), + 'rd_fragment' => $truncatedFragment, 'rd_interwiki' => $rt->getInterwiki(), ], __METHOD__ diff --git a/tests/phpunit/includes/page/WikiPageDbTestBase.php b/tests/phpunit/includes/page/WikiPageDbTestBase.php index d9c92f540a..fee45838b5 100644 --- a/tests/phpunit/includes/page/WikiPageDbTestBase.php +++ b/tests/phpunit/includes/page/WikiPageDbTestBase.php @@ -816,6 +816,15 @@ abstract class WikiPageDbTestBase extends MediaWikiLangTestCase { "#REDIRECT [[Media:hello_world]]", "File:Hello world" ], + // Test fragments longer than 255 bytes (T207876) + [ + 'WikiPageTest_testGetRedirectTarget_4', + CONTENT_MODEL_WIKITEXT, + // phpcs:ignore Generic.Files.LineLength + '#REDIRECT [[Foobar#🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿]]', + // phpcs:ignore Generic.Files.LineLength + 'Foobar#🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬󠁦󠁲󠁿🏴󠁮󠁬...' + ] ]; } @@ -836,7 +845,7 @@ abstract class WikiPageDbTestBase extends MediaWikiLangTestCase { # now, test the actual redirect $t = $page->getRedirectTarget(); - $this->assertEquals( $target, is_null( $t ) ? null : $t->getPrefixedText() ); + $this->assertEquals( $target, is_null( $t ) ? null : $t->getFullText() ); } /** -- 2.20.1