Skip to content

Commit 8071b4a

Browse files
committed
Compat: Fix mb_substr() polyfill for out-of-range offsets.
The delegation to `substr()` in the `_mb_substr()` polyfill left some results returning `false` on PHP < 8.0, but `mb_substr()` always returns an empty string in these cases. This patch updates the behavior to match `mb_substr()`. Some issues were not detected due to duplicate test names that appeared in the [60969] refactor. These have been corrected as part of this patch. Developed in: WordPress#12302 Discussed in: https://core.trac.wordpress.org/ticket/64894 Follow-up to [60969]. Props dmsnell, soean. See #64894. git-svn-id: https://develop.svn.wordpress.org/trunk@62576 602fd350-edb4-49c9-b593-d223f7449a82
1 parent f149add commit 8071b4a

2 files changed

Lines changed: 20 additions & 13 deletions

File tree

src/wp-includes/compat.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,14 @@ function _mb_substr( $str, $start, $length = null, $encoding = null ) {
298298

299299
// The solution below works only for UTF-8; treat all other encodings as byte streams.
300300
if ( ! _is_utf8_charset( $encoding ?? get_option( 'blog_charset' ) ) ) {
301-
return is_null( $length ) ? substr( $str, $start ) : substr( $str, $start, $length );
301+
$result = is_null( $length ) ? substr( $str, $start ) : substr( $str, $start, $length );
302+
303+
/*
304+
* For an out-of-range start, substr() returns false on PHP < 8.0 but an
305+
* empty string on PHP >= 8.0. mb_substr() always returns an empty string,
306+
* so normalize to match its behavior across all supported PHP versions.
307+
*/
308+
return false === $result ? '' : $result;
302309
}
303310

304311
$total_length = ( $start < 0 || $length < 0 )

tests/phpunit/tests/compat/mbSubstr.php

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,18 @@ public function test_8bit_mb_substr( $input_string, $start, $length ) {
4646
*/
4747
public function data_utf8_substrings() {
4848
return array(
49-
'баба' => array( 'баба', 0, 3 ),
50-
'баба' => array( 'баба', 0, -1 ),
51-
'баба' => array( 'баба', 1, null ),
52-
'баба' => array( 'баба', -3, null ),
53-
'баба' => array( 'баба', -3, 2 ),
54-
'баба' => array( 'баба', -2, 1 ),
55-
'баба' => array( 'баба', 30, 1 ),
56-
'баба' => array( 'баба', 15, -30 ),
57-
'баба' => array( 'баба', -5, -5 ),
58-
'баба' => array( 'баба', 5, -3 ),
59-
'баба' => array( 'баба', -3, 5 ),
60-
'I am your баба' => array( 'I am your баба', 0, 11 ),
49+
'positive start, positive length' => array( 'баба', 0, 3 ),
50+
'positive start, negative length' => array( 'баба', 0, -1 ),
51+
'positive start, null length' => array( 'баба', 1, null ),
52+
'negative start, null length' => array( 'баба', -3, null ),
53+
'negative start, positive length' => array( 'баба', -3, 2 ),
54+
'negative start near end, positive length' => array( 'баба', -2, 1 ),
55+
'start beyond length, positive length' => array( 'баба', 30, 1 ),
56+
'start beyond length, large negative length' => array( 'баба', 15, -30 ),
57+
'negative start beyond start, negative length' => array( 'баба', -5, -5 ),
58+
'start beyond length, negative length' => array( 'баба', 5, -3 ),
59+
'negative start, length beyond end' => array( 'баба', -3, 5 ),
60+
'multibyte character in longer string' => array( 'I am your баба', 0, 11 ),
6161
);
6262
}
6363

0 commit comments

Comments
 (0)