build: Upgrade phan-taint-check-plugin from 1.5.x to 2.0.1

The method ReplaceTextUtils::link (which is already complicated because
it tries to support ancient MediaWiki) can perform different levels of
escaping depending on whether the HtmlArmor class exists. This is confusing
for taint-check and for humans, and can inevitably lead to errors. Plus
it's bad practice to have a method returning something with a variable
level of taintedness, especially if that depends on something ephemeral
like if a class exists or not.

Thus, the HtmlArmor part is removed, the text is escaped for Linker::link,
and the method now requires non-escaped HTML to be passed in.

Change-Id: I6e2783827580e3d470d316f1d3879679eb67aeda
This commit is contained in:
James D. Forrester 2019-07-10 16:31:01 -07:00 committed by Daimona Eaytoy
parent dddb12e32a
commit 048be08fa5
4 changed files with 39 additions and 17 deletions

View file

@ -18,6 +18,6 @@
] ]
}, },
"extra": { "extra": {
"phan-taint-check-plugin": "1.5.0" "phan-taint-check-plugin": "2.0.1"
} }
} }

View file

@ -30,6 +30,10 @@ class ReplaceTextHooks {
*/ */
public static function addToAdminLinks( ALTree &$adminLinksTree ) { public static function addToAdminLinks( ALTree &$adminLinksTree ) {
$generalSection = $adminLinksTree->getSection( wfMessage( 'adminlinks_general' )->text() ); $generalSection = $adminLinksTree->getSection( wfMessage( 'adminlinks_general' )->text() );
if ( !$generalSection ) {
return true;
}
$extensionsRow = $generalSection->getRow( 'extensions' ); $extensionsRow = $generalSection->getRow( 'extensions' );
if ( is_null( $extensionsRow ) ) { if ( is_null( $extensionsRow ) ) {

View file

@ -25,17 +25,15 @@ class ReplaceTextUtils {
/** /**
* Shim for compatibility * Shim for compatibility
* @param Title $title to link to * @param Title $title to link to
* @param string|null $text to show * @param string|null $text to show, not escaped
* @return string HTML for link * @return string HTML for link
*/ */
public static function link( Title $title, $text = null ) { public static function link( Title $title, $text = null ) {
if ( method_exists( '\MediaWiki\MediaWikiServices', 'getLinkRenderer' ) ) { if ( method_exists( '\MediaWiki\MediaWikiServices', 'getLinkRenderer' ) ) {
$linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer(); $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
if ( class_exists( 'HtmlArmor' ) && !is_null( $text ) ) {
$text = new HtmlArmor( $text );
}
return $linkRenderer->makeLink( $title, $text ); return $linkRenderer->makeLink( $title, $text );
}; };
return Linker::link( $title, $text ); $escText = htmlspecialchars( $text );
return Linker::link( $title, $escText );
} }
} }

View file

@ -52,21 +52,31 @@ class SpecialReplaceText extends SpecialPage {
throw new PermissionsError( 'replacetext' ); throw new PermissionsError( 'replacetext' );
} }
$out = $this->getOutput();
// Replace Text can't be run with certain settings, due to the // Replace Text can't be run with certain settings, due to the
// changes they make to the DB storage setup. // changes they make to the DB storage setup.
if ( $wgCompressRevisions ) { if ( $wgCompressRevisions ) {
$errorMsg = "Error: text replacements cannot be run if \$wgCompressRevisions is set to true."; $errorMsg = "Error: text replacements cannot be run if \$wgCompressRevisions is set to true.";
$this->getOutput()->addWikiText( "<div class=\"errorbox\">$errorMsg</div>" ); if ( method_exists( $out, 'addWikiTextAsContent' ) ) {
$out->addWikiTextAsContent( "<div class=\"errorbox\">$errorMsg</div>" );
} else {
// @phan-suppress-next-line PhanUndeclaredMethod
$out->addWikiText( "<div class=\"errorbox\">$errorMsg</div>" );
}
return; return;
} }
if ( !empty( $wgExternalStores ) ) { if ( !empty( $wgExternalStores ) ) {
$errorMsg = "Error: text replacements cannot be run if \$wgExternalStores is non-empty."; $errorMsg = "Error: text replacements cannot be run if \$wgExternalStores is non-empty.";
$this->getOutput()->addWikiText( "<div class=\"errorbox\">$errorMsg</div>" ); if ( method_exists( $out, 'addWikiTextAsContent' ) ) {
$out->addWikiTextAsContent( "<div class=\"errorbox\">$errorMsg</div>" );
} else {
// @phan-suppress-next-line PhanUndeclaredMethod
$out->addWikiText( "<div class=\"errorbox\">$errorMsg</div>" );
}
return; return;
} }
$this->setHeaders(); $this->setHeaders();
$out = $this->getOutput();
if ( !is_null( $out->getResourceLoader()->getModule( 'mediawiki.special' ) ) ) { if ( !is_null( $out->getResourceLoader()->getModule( 'mediawiki.special' ) ) ) {
$out->addModuleStyles( 'mediawiki.special' ); $out->addModuleStyles( 'mediawiki.special' );
} }
@ -140,7 +150,7 @@ class SpecialReplaceText extends SpecialPage {
$out->addHTML( $out->addHTML(
ReplaceTextUtils::link( ReplaceTextUtils::link(
$this->getPageTitle(), $this->getPageTitle(),
$this->msg( 'replacetext_return' )->escaped() $this->msg( 'replacetext_return' )->text()
) )
); );
return; return;
@ -188,8 +198,10 @@ class SpecialReplaceText extends SpecialPage {
} }
if ( $bad_cat_name ) { if ( $bad_cat_name ) {
$link = ReplaceTextUtils::link( $category_title, $link = ReplaceTextUtils::link(
htmlspecialchars( ucfirst( $this->category ) ) ); $category_title,
ucfirst( $this->category )
);
$out->addHTML( $out->addHTML(
$this->msg( 'replacetext_nosuchcategory' )->rawParams( $link )->escaped() $this->msg( 'replacetext_nosuchcategory' )->rawParams( $link )->escaped()
); );
@ -208,14 +220,22 @@ class SpecialReplaceText extends SpecialPage {
$out->addHTML( $out->addHTML(
'<p>' . '<p>' .
ReplaceTextUtils::link( ReplaceTextUtils::link(
$this->getPageTitle(), $this->getPageTitle(),
$this->msg( 'replacetext_return' )->escaped() ) $this->msg( 'replacetext_return' )->text()
)
. '</p>' . '</p>'
); );
} else { } else {
$warning_msg = $this->getAnyWarningMessageBeforeReplace( $titles_for_edit, $titles_for_move ); $warning_msg = $this->getAnyWarningMessageBeforeReplace( $titles_for_edit, $titles_for_move );
if ( !is_null( $warning_msg ) ) { if ( !is_null( $warning_msg ) ) {
$out->addWikiText( "<div class=\"errorbox\">$warning_msg</div><br clear=\"both\" />" ); if ( method_exists( $out, 'addWikiTextAsContent' ) ) {
$out->addWikiTextAsContent(
"<div class=\"errorbox\">$warning_msg</div><br clear=\"both\" />"
);
} else {
// @phan-suppress-next-line PhanUndeclaredMethod
$out->addWikiText( "<div class=\"errorbox\">$warning_msg</div><br clear=\"both\" />" );
}
} }
$this->pageListForm( $titles_for_edit, $titles_for_move, $unmoveable_titles ); $this->pageListForm( $titles_for_edit, $titles_for_move, $unmoveable_titles );
@ -775,8 +795,8 @@ class SpecialReplaceText extends SpecialPage {
return $context; return $context;
} }
private function convertWhiteSpaceToHTML( $msg ) { private function convertWhiteSpaceToHTML( $message ) {
$msg = htmlspecialchars( $msg ); $msg = htmlspecialchars( $message );
$msg = preg_replace( '/^ /m', '&#160; ', $msg ); $msg = preg_replace( '/^ /m', '&#160; ', $msg );
$msg = preg_replace( '/ $/m', ' &#160;', $msg ); $msg = preg_replace( '/ $/m', ' &#160;', $msg );
$msg = preg_replace( '/ /', '&#160; ', $msg ); $msg = preg_replace( '/ /', '&#160; ', $msg );