Skip to content

Commit c25967a

Browse files
committed
Prevent incorrect decoding of numeric character references
The wp_kses_normalize_entities function should not decode double-encoded inputs like `&#2E;` to `&#2E;`. Ensure that the normalization steps are processed in the correct order so that the input is normalized and its value is preserved.
1 parent 7c6c668 commit c25967a

1 file changed

Lines changed: 34 additions & 3 deletions

File tree

‎src/wp-includes/kses.php‎

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1958,14 +1958,45 @@ function wp_kses_normalize_entities( $content, $context = 'html' ) {
19581958
// Disarm all entities by converting & to &
19591959
$content = str_replace( '&', '&', $content );
19601960

1961-
// Change back the allowed entities in our list of allowed entities.
1961+
/*
1962+
* Decode any character references that are now double-encoded.
1963+
*
1964+
* It's important that the following normalizations happen in the correct order.
1965+
*
1966+
* At this point, all `&` have been transformed to `&`. Double-encoded named character
1967+
* references like `&` will be decoded back to their single-encoded form `&`.
1968+
*
1969+
* First, numeric (decimal and hexadecimal) character references must be handled so that
1970+
* `	` becomes `	`. If the named character references were handled first, there
1971+
* would be no way to know whether the double-encoded character reference had been produced
1972+
* in this function or was the original input.
1973+
*
1974+
* Consider the two examples, first with named entity decoding followed by numeric
1975+
* entity decoding. We'll use U+002E FULL STOP (.) in our example, this table follows the
1976+
* string processing from left to right:
1977+
*
1978+
* | Input | &-encoded | Named ref double-decoded | Numeric ref double-decoded |
1979+
* | ------------ | ---------------- | ------------------------- | -------------------------- |
1980+
* | `.` | `.` | `.` | `.` |
1981+
* | `.` | `.` | `.` | `.` |
1982+
*
1983+
* Notice in the example above that different inputs result in the same result. The second case
1984+
* was not normalized and produced HTML that is semantically different from the input.
1985+
*
1986+
* | Input | &-encoded | Numericref double-decoded | Named ref double-decoded |
1987+
* | ------------ | ---------------- | -------------------------- | ------------------------ |
1988+
* | `.` | `.` | `.` | `.` |
1989+
* | `.` | `.` | `.` | `&amp#x2E;` |
1990+
*
1991+
* Here, each input is normalized to an appropriate output.
1992+
*/
1993+
$content = preg_replace_callback( '/&#(0*[0-9]{1,7});/', 'wp_kses_normalize_entities2', $content );
1994+
$content = preg_replace_callback( '/&#[Xx](0*[0-9A-Fa-f]{1,6});/', 'wp_kses_normalize_entities3', $content );
19621995
if ( 'xml' === $context ) {
19631996
$content = preg_replace_callback( '/&([A-Za-z]{2,8}[0-9]{0,2});/', 'wp_kses_xml_named_entities', $content );
19641997
} else {
19651998
$content = preg_replace_callback( '/&([A-Za-z]{2,8}[0-9]{0,2});/', 'wp_kses_named_entities', $content );
19661999
}
1967-
$content = preg_replace_callback( '/&#(0*[0-9]{1,7});/', 'wp_kses_normalize_entities2', $content );
1968-
$content = preg_replace_callback( '/&#[Xx](0*[0-9A-Fa-f]{1,6});/', 'wp_kses_normalize_entities3', $content );
19692000

19702001
return $content;
19712002
}

0 commit comments

Comments
 (0)