From 57e024a15760bd0721a4a97fdd8986a802f58132 Mon Sep 17 00:00:00 2001 From: Sergey Biryukov <sergeybiryukov.ru@gmail.com> Date: Sat, 14 Dec 2024 23:53:24 +0000 Subject: [PATCH] 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. Built from https://develop.svn.wordpress.org/trunk@59515 git-svn-id: http://core.svn.wordpress.org/trunk@58901 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/formatting.php | 71 +++++++++++++++++++++----------------- wp-includes/version.php | 2 +- 2 files changed, 41 insertions(+), 32 deletions(-) diff --git a/wp-includes/formatting.php b/wp-includes/formatting.php index b579bcd324..3ecc352528 100644 --- a/wp-includes/formatting.php +++ b/wp-includes/formatting.php @@ -3473,40 +3473,49 @@ function translate_smiley( $matches ) { */ function convert_smilies( $text ) { global $wp_smiliessearch; - $output = ''; - if ( get_option( 'use_smilies' ) && ! empty( $wp_smiliessearch ) ) { - // HTML loop taken from texturize function, could possible be consolidated. - $textarr = preg_split( '/(<.*>)/U', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // Capture the tags as well as in between. - $stop = count( $textarr ); // Loop stuff. - // Ignore processing of specific tags. - $tags_to_ignore = 'code|pre|style|script|textarea'; - $ignore_block_element = ''; - - for ( $i = 0; $i < $stop; $i++ ) { - $content = $textarr[ $i ]; - - // If we're in an ignore block, wait until we find its closing tag. - if ( '' === $ignore_block_element && preg_match( '/^<(' . $tags_to_ignore . ')[^>]*>/', $content, $matches ) ) { - $ignore_block_element = $matches[1]; - } - - // If it's not a tag and not in ignore block. - if ( '' === $ignore_block_element && strlen( $content ) > 0 && '<' !== $content[0] ) { - $content = preg_replace_callback( $wp_smiliessearch, 'translate_smiley', $content ); - } - - // Did we exit ignore block? - if ( '' !== $ignore_block_element && '</' . $ignore_block_element . '>' === $content ) { - $ignore_block_element = ''; - } - - $output .= $content; - } - } else { + if ( ! get_option( 'use_smilies' ) || empty( $wp_smiliessearch ) ) { // Return default text. - $output = $text; + return $text; } + + // HTML loop taken from texturize function, could possible be consolidated. + $textarr = preg_split( '/(<[^>]*>)/U', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // Capture the tags as well as in between. + + if ( false === $textarr ) { + // Return default text. + return $text; + } + + // Loop stuff. + $stop = count( $textarr ); + $output = ''; + + // Ignore processing of specific tags. + $tags_to_ignore = 'code|pre|style|script|textarea'; + $ignore_block_element = ''; + + for ( $i = 0; $i < $stop; $i++ ) { + $content = $textarr[ $i ]; + + // If we're in an ignore block, wait until we find its closing tag. + if ( '' === $ignore_block_element && preg_match( '/^<(' . $tags_to_ignore . ')[^>]*>/', $content, $matches ) ) { + $ignore_block_element = $matches[1]; + } + + // If it's not a tag and not in ignore block. + if ( '' === $ignore_block_element && strlen( $content ) > 0 && '<' !== $content[0] ) { + $content = preg_replace_callback( $wp_smiliessearch, 'translate_smiley', $content ); + } + + // Did we exit ignore block? + if ( '' !== $ignore_block_element && '</' . $ignore_block_element . '>' === $content ) { + $ignore_block_element = ''; + } + + $output .= $content; + } + return $output; } diff --git a/wp-includes/version.php b/wp-includes/version.php index c8beddbf30..391edd9fe4 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '6.8-alpha-59514'; +$wp_version = '6.8-alpha-59515'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.