mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-15 20:06:31 +00:00
Fix multi-byte UFT-8 in escape('html_attr')
This commit is contained in:
committed by
Nicolas Grekas
parent
1329b5580f
commit
dc3acfb7cd
+1
-1
@@ -28,7 +28,7 @@
|
|||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.0",
|
"php": "^7.0",
|
||||||
"symfony/polyfill-mbstring": "~1.0",
|
"symfony/polyfill-mbstring": "^1.3",
|
||||||
"symfony/polyfill-ctype": "^1.8"
|
"symfony/polyfill-ctype": "^1.8"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
|||||||
+27
-39
@@ -902,6 +902,10 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ('' === $string) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
if (null === $charset) {
|
if (null === $charset) {
|
||||||
$charset = $env->getCharset();
|
$charset = $env->getCharset();
|
||||||
}
|
}
|
||||||
@@ -953,7 +957,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|||||||
$string = iconv($charset, 'UTF-8', $string);
|
$string = iconv($charset, 'UTF-8', $string);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 == strlen($string) ? false : 1 !== preg_match('/^./su', $string)) {
|
if (!preg_match('//u', $string)) {
|
||||||
throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
|
throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1001,27 +1005,14 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|||||||
$string = iconv($charset, 'UTF-8', $string);
|
$string = iconv($charset, 'UTF-8', $string);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 == strlen($string) ? false : 1 !== preg_match('/^./su', $string)) {
|
if (!preg_match('//u', $string)) {
|
||||||
throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
|
throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$string = preg_replace_callback('#[^a-zA-Z0-9]#Su', function ($matches) {
|
$string = preg_replace_callback('#[^a-zA-Z0-9]#Su', function ($matches) {
|
||||||
$char = $matches[0];
|
$char = $matches[0];
|
||||||
|
|
||||||
// \xHH
|
return sprintf('\\%X ', 1 === strlen($char) ? ord($char) : mb_ord($char, 'UTF-8'));
|
||||||
if (!isset($char[1])) {
|
|
||||||
$hex = ltrim(strtoupper(bin2hex($char)), '0');
|
|
||||||
if (0 === strlen($hex)) {
|
|
||||||
$hex = '0';
|
|
||||||
}
|
|
||||||
|
|
||||||
return '\\'.$hex.' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
// \uHHHH
|
|
||||||
$char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8');
|
|
||||||
|
|
||||||
return '\\'.ltrim(strtoupper(bin2hex($char)), '0').' ';
|
|
||||||
}, $string);
|
}, $string);
|
||||||
|
|
||||||
if ('UTF-8' !== $charset) {
|
if ('UTF-8' !== $charset) {
|
||||||
@@ -1035,7 +1026,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|||||||
$string = iconv($charset, 'UTF-8', $string);
|
$string = iconv($charset, 'UTF-8', $string);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 == strlen($string) ? false : 1 !== preg_match('/^./su', $string)) {
|
if (!preg_match('//u', $string)) {
|
||||||
throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
|
throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1046,18 +1037,6 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|||||||
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (https://www.zend.com)
|
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (https://www.zend.com)
|
||||||
* @license https://framework.zend.com/license/new-bsd New BSD License
|
* @license https://framework.zend.com/license/new-bsd New BSD License
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
* While HTML supports far more named entities, the lowest common denominator
|
|
||||||
* has become HTML5's XML Serialisation which is restricted to the those named
|
|
||||||
* entities that XML supports. Using HTML entities would result in this error:
|
|
||||||
* XML Parsing Error: undefined entity
|
|
||||||
*/
|
|
||||||
static $entityMap = array(
|
|
||||||
34 => 'quot', /* quotation mark */
|
|
||||||
38 => 'amp', /* ampersand */
|
|
||||||
60 => 'lt', /* less-than sign */
|
|
||||||
62 => 'gt', /* greater-than sign */
|
|
||||||
);
|
|
||||||
|
|
||||||
$chr = $matches[0];
|
$chr = $matches[0];
|
||||||
$ord = ord($chr);
|
$ord = ord($chr);
|
||||||
@@ -1074,23 +1053,32 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|||||||
* Check if the current character to escape has a name entity we should
|
* Check if the current character to escape has a name entity we should
|
||||||
* replace it with while grabbing the hex value of the character.
|
* replace it with while grabbing the hex value of the character.
|
||||||
*/
|
*/
|
||||||
if (1 == strlen($chr)) {
|
if (1 === strlen($chr)) {
|
||||||
$hex = strtoupper(substr('00'.bin2hex($chr), -2));
|
/*
|
||||||
} else {
|
* While HTML supports far more named entities, the lowest common denominator
|
||||||
$chr = twig_convert_encoding($chr, 'UTF-16BE', 'UTF-8');
|
* has become HTML5's XML Serialisation which is restricted to the those named
|
||||||
$hex = strtoupper(substr('0000'.bin2hex($chr), -4));
|
* entities that XML supports. Using HTML entities would result in this error:
|
||||||
}
|
* XML Parsing Error: undefined entity
|
||||||
|
*/
|
||||||
|
static $entityMap = array(
|
||||||
|
34 => '"', /* quotation mark */
|
||||||
|
38 => '&', /* ampersand */
|
||||||
|
60 => '<', /* less-than sign */
|
||||||
|
62 => '>', /* greater-than sign */
|
||||||
|
);
|
||||||
|
|
||||||
$int = hexdec($hex);
|
if (isset($entityMap[$ord])) {
|
||||||
if (array_key_exists($int, $entityMap)) {
|
return $entityMap[$ord];
|
||||||
return sprintf('&%s;', $entityMap[$int]);
|
}
|
||||||
|
|
||||||
|
return sprintf('&#x%02X;', $ord);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Per OWASP recommendations, we'll use hex entities for any other
|
* Per OWASP recommendations, we'll use hex entities for any other
|
||||||
* characters where a named entity does not exist.
|
* characters where a named entity does not exist.
|
||||||
*/
|
*/
|
||||||
return sprintf('&#x%s;', $hex);
|
return sprintf('&#x%04X;', mb_ord($chr, 'UTF-8'));
|
||||||
}, $string);
|
}, $string);
|
||||||
|
|
||||||
if ('UTF-8' !== $charset) {
|
if ('UTF-8' !== $charset) {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class Twig_Test_EscapingTest extends \PHPUnit\Framework\TestCase
|
|||||||
'\'' => ''',
|
'\'' => ''',
|
||||||
/* Characters beyond ASCII value 255 to unicode escape */
|
/* Characters beyond ASCII value 255 to unicode escape */
|
||||||
'Ā' => 'Ā',
|
'Ā' => 'Ā',
|
||||||
|
'😀' => '😀',
|
||||||
/* Immune chars excluded */
|
/* Immune chars excluded */
|
||||||
',' => ',',
|
',' => ',',
|
||||||
'.' => '.',
|
'.' => '.',
|
||||||
|
|||||||
Reference in New Issue
Block a user