From d64561787cbfe2aa5179b1e51aa27398e465a383 Mon Sep 17 00:00:00 2001 From: Artyom Osepyan Date: Fri, 21 Nov 2025 00:03:50 +0300 Subject: [PATCH 1/3] fix: use mb_strlen in substrReplace for multibyte safety refs: https://github.com/laravel/framework/issues/57838 --- src/Illuminate/Support/Str.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Support/Str.php b/src/Illuminate/Support/Str.php index 164018788683..cccff1a75f6a 100644 --- a/src/Illuminate/Support/Str.php +++ b/src/Illuminate/Support/Str.php @@ -1748,7 +1748,7 @@ public static function substrCount($haystack, $needle, $offset = 0, $length = nu public static function substrReplace($string, $replace, $offset = 0, $length = null) { if ($length === null) { - $length = strlen($string); + $length = mb_strlen($string); } return substr_replace($string, $replace, $offset, $length); From bb068a70f67f6d4fed906077407329e4649b8840 Mon Sep 17 00:00:00 2001 From: Artyom Osepyan Date: Fri, 21 Nov 2025 01:09:33 +0300 Subject: [PATCH 2/3] feature: support multibyte strings in substrReplace refs: https://github.com/laravel/framework/issues/57838 --- src/Illuminate/Support/Str.php | 14 +++++++++++--- tests/Support/SupportStrTest.php | 2 ++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Illuminate/Support/Str.php b/src/Illuminate/Support/Str.php index cccff1a75f6a..b5c3bad8a187 100644 --- a/src/Illuminate/Support/Str.php +++ b/src/Illuminate/Support/Str.php @@ -1747,11 +1747,19 @@ public static function substrCount($haystack, $needle, $offset = 0, $length = nu */ public static function substrReplace($string, $replace, $offset = 0, $length = null) { - if ($length === null) { - $length = mb_strlen($string); + $encoding = 'UTF-8'; + $strlen = mb_strlen($string, $encoding); + + if ($offset < 0) { + $offset = $offset < -$strlen ? 0 : $strlen + $offset; } - return substr_replace($string, $replace, $offset, $length); + $length = is_null($length) ? $strlen - $offset : max($length, 0); + + $start = mb_substr($string, 0, $offset, $encoding); + $end = mb_substr($string, $offset + $length, $strlen - ($offset + $length), $encoding); + + return $start . $replace . $end; } /** diff --git a/tests/Support/SupportStrTest.php b/tests/Support/SupportStrTest.php index 425966353d29..6a646c70c475 100755 --- a/tests/Support/SupportStrTest.php +++ b/tests/Support/SupportStrTest.php @@ -1262,6 +1262,8 @@ public function testSubstrReplace() $this->assertSame('12:00', Str::substrReplace('1200', ':', 2, 0)); $this->assertSame('The Laravel Framework', Str::substrReplace('The Framework', 'Laravel ', 4, 0)); $this->assertSame('Laravel – The PHP Framework for Web Artisans', Str::substrReplace('Laravel Framework', '– The PHP Framework for Web Artisans', 8)); + $this->assertSame('Laravel – PHP 框架的网络专家', Str::substrReplace('Laravel 的网络专家', '– PHP 框架', 8, 0)); + $this->assertSame('Laravel – PHP Фреймворк для веб-мастеров', Str::substrReplace('Laravel для веб-мастеров', ' – PHP Фреймворк', 7, 0)); } public function testTake() From ac493d16131cdf0793ebb410c221bf6fbcc1038c Mon Sep 17 00:00:00 2001 From: Artyom Osepyan Date: Fri, 21 Nov 2025 01:14:25 +0300 Subject: [PATCH 3/3] style: fix code style --- src/Illuminate/Support/Str.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Support/Str.php b/src/Illuminate/Support/Str.php index b5c3bad8a187..235dbc0cc520 100644 --- a/src/Illuminate/Support/Str.php +++ b/src/Illuminate/Support/Str.php @@ -1759,7 +1759,7 @@ public static function substrReplace($string, $replace, $offset = 0, $length = n $start = mb_substr($string, 0, $offset, $encoding); $end = mb_substr($string, $offset + $length, $strlen - ($offset + $length), $encoding); - return $start . $replace . $end; + return $start.$replace.$end; } /**