Skip to content

Commit c3c319e

Browse files
Formatting: Check the result of preg_split() in convert_smilies().
This aims to avoid a fatal error from `count()` when `preg_split()` fails on large input. Includes: * Optimizing the regular expression used to split the input by tags to avoid unlimited backtracking for better performance. * Adjusting the function logic for better readability. Follow-up to [340], [4380], [26191]. Props podpirate, nathkrill, rajinsharwar, dmsnell, bjorsch, q0rban, audrasjb, rupw, Ov3rfly, jorbin, nhrrob, chaion07, mcqueen22, azaozz, narenin, roybellingan, SergeyBiryukov. See #51019. git-svn-id: https://develop.svn.wordpress.org/trunk@59515 602fd350-edb4-49c9-b593-d223f7449a82
1 parent b03c9f5 commit c3c319e

File tree

2 files changed

+47
-26
lines changed

2 files changed

+47
-26
lines changed

src/wp-includes/formatting.php

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3473,40 +3473,49 @@ function translate_smiley( $matches ) {
34733473
*/
34743474
function convert_smilies( $text ) {
34753475
global $wp_smiliessearch;
3476-
$output = '';
3477-
if ( get_option( 'use_smilies' ) && ! empty( $wp_smiliessearch ) ) {
3478-
// HTML loop taken from texturize function, could possible be consolidated.
3479-
$textarr = preg_split( '/(<.*>)/U', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // Capture the tags as well as in between.
3480-
$stop = count( $textarr ); // Loop stuff.
34813476

3482-
// Ignore processing of specific tags.
3483-
$tags_to_ignore = 'code|pre|style|script|textarea';
3484-
$ignore_block_element = '';
3477+
if ( ! get_option( 'use_smilies' ) || empty( $wp_smiliessearch ) ) {
3478+
// Return default text.
3479+
return $text;
3480+
}
34853481

3486-
for ( $i = 0; $i < $stop; $i++ ) {
3487-
$content = $textarr[ $i ];
3482+
// HTML loop taken from texturize function, could possible be consolidated.
3483+
$textarr = preg_split( '/(<[^>]*>)/U', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // Capture the tags as well as in between.
34883484

3489-
// If we're in an ignore block, wait until we find its closing tag.
3490-
if ( '' === $ignore_block_element && preg_match( '/^<(' . $tags_to_ignore . ')[^>]*>/', $content, $matches ) ) {
3491-
$ignore_block_element = $matches[1];
3492-
}
3485+
if ( false === $textarr ) {
3486+
// Return default text.
3487+
return $text;
3488+
}
34933489

3494-
// If it's not a tag and not in ignore block.
3495-
if ( '' === $ignore_block_element && strlen( $content ) > 0 && '<' !== $content[0] ) {
3496-
$content = preg_replace_callback( $wp_smiliessearch, 'translate_smiley', $content );
3497-
}
3490+
// Loop stuff.
3491+
$stop = count( $textarr );
3492+
$output = '';
34983493

3499-
// Did we exit ignore block?
3500-
if ( '' !== $ignore_block_element && '</' . $ignore_block_element . '>' === $content ) {
3501-
$ignore_block_element = '';
3502-
}
3494+
// Ignore processing of specific tags.
3495+
$tags_to_ignore = 'code|pre|style|script|textarea';
3496+
$ignore_block_element = '';
3497+
3498+
for ( $i = 0; $i < $stop; $i++ ) {
3499+
$content = $textarr[ $i ];
35033500

3504-
$output .= $content;
3501+
// If we're in an ignore block, wait until we find its closing tag.
3502+
if ( '' === $ignore_block_element && preg_match( '/^<(' . $tags_to_ignore . ')[^>]*>/', $content, $matches ) ) {
3503+
$ignore_block_element = $matches[1];
35053504
}
3506-
} else {
3507-
// Return default text.
3508-
$output = $text;
3505+
3506+
// If it's not a tag and not in ignore block.
3507+
if ( '' === $ignore_block_element && strlen( $content ) > 0 && '<' !== $content[0] ) {
3508+
$content = preg_replace_callback( $wp_smiliessearch, 'translate_smiley', $content );
3509+
}
3510+
3511+
// Did we exit ignore block?
3512+
if ( '' !== $ignore_block_element && '</' . $ignore_block_element . '>' === $content ) {
3513+
$ignore_block_element = '';
3514+
}
3515+
3516+
$output .= $content;
35093517
}
3518+
35103519
return $output;
35113520
}
35123521

tests/phpunit/tests/formatting/convertSmilies.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,4 +393,16 @@ public function _filter_add_smilies( $wpsmiliestrans ) {
393393
$wpsmiliestrans['<3'] = '\xe2\x9d\xa4';
394394
return $wpsmiliestrans;
395395
}
396+
397+
398+
/**
399+
* Tests that the function does not throw a fatal error from count()
400+
* when preg_split() fails on large input.
401+
*
402+
* @ticket 51019
403+
*/
404+
public function test_smilies_with_large_text_input() {
405+
$text = '<p><img alt="" src="data:image/png;base64,' . str_repeat( 'iVBORw0KGgoAAAAN', 65536 ) . '="></p> :)';
406+
$this->assertStringContainsString( "\xf0\x9f\x99\x82", convert_smilies( $text ) );
407+
}
396408
}

0 commit comments

Comments
 (0)