PHP 8.1: add ENT_COMPAT to some htmlspecialchars() calls

In PHP 8.1 the default $flags argument to htmlspecialchars() has changed
from ENT_COMPAT to ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401. This
breaks some tests.

I changed all the calls that break unit tests, and some others
based on a quick code review. A lot of callers just use the default for
convenience, and were already over-quoting, so the default should still
be good enough for them.

Change-Id: Ie9fbeae6f0417c6cf29dceaf429243a135f9fecb
This commit is contained in:
Tim Starling 2022-01-25 16:23:23 +11:00
parent 9a4a63ade3
commit c5ef6e3091
13 changed files with 26 additions and 24 deletions

View file

@ -863,7 +863,7 @@ class Linker {
], $label );
if ( $mainConfig->get( 'ParserEnableLegacyMediaDOM' ) ) {
$html = htmlspecialchars( $label );
$html = htmlspecialchars( $label, ENT_COMPAT );
}
$repoGroup = $services->getRepoGroup();
@ -1038,7 +1038,7 @@ class Linker {
$attribs['class'] = $class;
if ( $escape ) {
$text = htmlspecialchars( $text );
$text = htmlspecialchars( $text, ENT_COMPAT );
}
if ( !$title ) {
@ -1739,10 +1739,10 @@ class Linker {
public static function makeHeadline( $level, $attribs, $anchor, $html,
$link, $fallbackAnchor = false
) {
$anchorEscaped = htmlspecialchars( $anchor );
$anchorEscaped = htmlspecialchars( $anchor, ENT_COMPAT );
$fallback = '';
if ( $fallbackAnchor !== false && $fallbackAnchor !== $anchor ) {
$fallbackAnchor = htmlspecialchars( $fallbackAnchor );
$fallbackAnchor = htmlspecialchars( $fallbackAnchor, ENT_COMPAT );
$fallback = "<span id=\"$fallbackAnchor\"></span>";
}
return "<h$level$attribs"

View file

@ -284,7 +284,7 @@ class ResponseFactory {
* @return string
*/
protected function getHyperLink( $url ) {
$url = htmlspecialchars( $url );
$url = htmlspecialchars( $url, ENT_COMPAT );
return "<!doctype html><title>Redirect</title><a href=\"$url\">$url</a>";
}

View file

@ -274,7 +274,7 @@ class ApiFeedContributions extends ApiBase {
if ( $content instanceof TextContent ) {
// only textual content has a "source view".
$html = nl2br( htmlspecialchars( $content->getText() ) );
$html = nl2br( htmlspecialchars( $content->getText(), ENT_COMPAT ) );
} else {
// XXX: we could get an HTML representation of the content via getParserOutput, but that may
// contain JS magic and generally may not be suitable for inclusion in a feed.

View file

@ -236,7 +236,7 @@ class TextContentHandler extends ContentHandler {
$html = $method->invoke( $content );
} else {
// Return an HTML representation of the content
$html = htmlspecialchars( $content->getText() );
$html = htmlspecialchars( $content->getText(), ENT_COMPAT );
}
} else {
$html = '';

View file

@ -229,7 +229,7 @@ class CoreParserFunctions {
if ( !is_string( $temp ) ) {
return $temp;
} else {
return htmlspecialchars( $temp );
return htmlspecialchars( $temp, ENT_COMPAT );
}
}
@ -242,7 +242,7 @@ class CoreParserFunctions {
if ( !is_string( $temp ) ) {
return $temp;
} else {
return htmlspecialchars( $temp );
return htmlspecialchars( $temp, ENT_COMPAT );
}
}
@ -255,7 +255,7 @@ class CoreParserFunctions {
if ( !is_string( $temp ) ) {
return $temp;
} else {
return htmlspecialchars( $temp );
return htmlspecialchars( $temp, ENT_COMPAT );
}
}
@ -1146,7 +1146,8 @@ class CoreParserFunctions {
// we can't handle this tag (at least not now), so just re-emit it as an ordinary tag
$attrText = '';
foreach ( $attributes as $name => $value ) {
$attrText .= ' ' . htmlspecialchars( $name ) . '="' . htmlspecialchars( $value ) . '"';
$attrText .= ' ' . htmlspecialchars( $name ) .
'="' . htmlspecialchars( $value, ENT_COMPAT ) . '"';
}
if ( $inner === null ) {
return "<$tagName$attrText/>";

View file

@ -53,7 +53,7 @@ class PPNode_Hash_Attr implements PPNode {
}
public function __toString() {
return "<@{$this->name}>" . htmlspecialchars( $this->value ) . "</@{$this->name}>";
return "<@{$this->name}>" . htmlspecialchars( $this->value, ENT_COMPAT ) . "</@{$this->name}>";
}
public function getName() {

View file

@ -49,7 +49,7 @@ class PPNode_Hash_Text implements PPNode {
}
public function __toString() {
return htmlspecialchars( $this->value );
return htmlspecialchars( $this->value, ENT_COMPAT );
}
public function getNextSibling() {

View file

@ -111,7 +111,8 @@ class PPNode_Hash_Tree implements PPNode {
$attribs = '';
for ( $node = $this->getFirstChild(); $node; $node = $node->getNextSibling() ) {
if ( $node instanceof PPNode_Hash_Attr ) {
$attribs .= ' ' . $node->name . '="' . htmlspecialchars( $node->value ) . '"';
$attribs .= ' ' . $node->name .
'="' . htmlspecialchars( $node->value, ENT_COMPAT ) . '"';
} else {
$inner .= $node->__toString();
}

View file

@ -3973,7 +3973,7 @@ class Parser {
if ( isset( $params['attributes'] ) ) {
foreach ( $params['attributes'] as $attrName => $attrValue ) {
$attrText .= ' ' . htmlspecialchars( $attrName ) . '="' .
htmlspecialchars( $attrValue ) . '"';
htmlspecialchars( $attrValue, ENT_COMPAT ) . '"';
}
}
if ( $content === null ) {
@ -4412,9 +4412,9 @@ class Parser {
// content block because the language converter is supposed to
// be able to convert that piece of data.
// Gets replaced with html in ParserOutput::getText
$editlink = '<mw:editsection page="' . htmlspecialchars( $editsectionPage );
$editlink = '<mw:editsection page="' . htmlspecialchars( $editsectionPage, ENT_COMPAT );
// @phan-suppress-next-line SecurityCheck-DoubleEscaped
$editlink .= '" section="' . htmlspecialchars( $editsectionSection ) . '"';
$editlink .= '" section="' . htmlspecialchars( $editsectionSection, ENT_COMPAT ) . '"';
if ( $editsectionContent !== null ) {
$editlink .= '>' . $editsectionContent . '</mw:editsection>';
} else {

View file

@ -1046,7 +1046,7 @@ class Sanitizer {
public static function safeEncodeTagAttributes( $assoc_array ) {
$attribs = [];
foreach ( $assoc_array as $attribute => $value ) {
$encAttribute = htmlspecialchars( $attribute );
$encAttribute = htmlspecialchars( $attribute, ENT_COMPAT );
$encValue = self::safeEncodeAttribute( $value );
$attribs[] = "$encAttribute=\"$encValue\"";
@ -1141,7 +1141,7 @@ class Sanitizer {
$ret = self::hexCharReference( $matches[3] );
}
if ( $ret === null ) {
return htmlspecialchars( $matches[0] );
return htmlspecialchars( $matches[0], ENT_COMPAT );
} else {
return $ret;
}

View file

@ -46,12 +46,12 @@ abstract class BaseTemplate extends QuickTemplate {
if ( $copyright !== null ) {
$out = $skin->makeFooterIcon( $copyright );
} elseif ( $config->get( 'RightsIcon' ) ) {
$icon = htmlspecialchars( $config->get( 'RightsIcon' ) );
$icon = htmlspecialchars( $config->get( 'RightsIcon' ), ENT_COMPAT );
$url = $config->get( 'RightsUrl' );
if ( $url ) {
$out .= '<a href="' . htmlspecialchars( $url ) . '">';
$out .= '<a href="' . htmlspecialchars( $url, ENT_COMPAT ) . '">';
}
$text = htmlspecialchars( $config->get( 'RightsText' ) );
$text = htmlspecialchars( $config->get( 'RightsText' ), ENT_COMPAT );
$out .= "<img src=\"$icon\" alt=\"$text\" width=\"88\" height=\"31\" />";
if ( $url ) {
$out .= '</a>';

View file

@ -1044,7 +1044,7 @@ TEXT
}
$this->checkpointJustWritten = false;
}
$this->buffer .= htmlspecialchars( $data );
$this->buffer .= htmlspecialchars( $data, ENT_COMPAT );
}
protected function clearOpenElement( $style ) {

View file

@ -122,7 +122,7 @@ class DumpRenderer extends Maintenance {
"<html lang=\"en\" dir=\"ltr\">\n" .
"<head>\n" .
"<meta charset=\"UTF-8\" />\n" .
"<title>" . htmlspecialchars( $display ) . "</title>\n" .
"<title>" . htmlspecialchars( $display, ENT_COMPAT ) . "</title>\n" .
"</head>\n" .
"<body>\n" .
$output->getText() .