Skip to content

Commit f75a14b

Browse files
[Php74] Align mb_str_split() polyfill with Mbstring and native
The Php74 copy of mb_str_split() returned false for a length lower than 1 even on PHP 8+, where the function raises a ValueError, and used a single .{N} quantifier that fails to compile for a length above the PCRE 65535 limit. Match the Mbstring implementation: throw ValueError on PHP 8+ and chunk the regex so both polyfills behave identically.
1 parent 25cebc6 commit f75a14b

2 files changed

Lines changed: 36 additions & 3 deletions

File tree

src/Php74/Php74.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,28 @@ public static function mb_str_split($string, $split_length = 1, $encoding = null
5050
}
5151

5252
if (1 > $split_length = (int) $split_length) {
53-
trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING);
53+
if (80000 > \PHP_VERSION_ID) {
54+
trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING);
5455

55-
return false;
56+
return false;
57+
}
58+
59+
throw new \ValueError('Argument #2 ($length) must be greater than 0');
5660
}
5761

5862
if (null === $encoding) {
5963
$encoding = mb_internal_encoding();
6064
}
6165

6266
if ('UTF-8' === $encoding || \in_array(strtoupper($encoding), ['UTF-8', 'UTF8'], true)) {
63-
return preg_split("/(.{{$split_length}})/us", $string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
67+
$rx = '/(';
68+
while (65535 < $split_length) {
69+
$rx .= '.{65535}';
70+
$split_length -= 65535;
71+
}
72+
$rx .= '.{'.$split_length.'})/us';
73+
74+
return preg_split($rx, $string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
6475
}
6576

6677
$result = [];

tests/Php74/Php74Test.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Polyfill\Tests\Php74;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Polyfill\Php74\Php74;
1516

1617
/**
1718
* @author Ion Bazan <ion.bazan@gmail.com>
@@ -116,6 +117,27 @@ public function testStrSplitWithInvalidValues()
116117
$this->expectWarningMessage('The length of each segment must be greater than zero');
117118
mb_str_split('победа', 0);
118119
}
120+
121+
/**
122+
* @covers \Symfony\Polyfill\Php74\Php74::mb_str_split
123+
*
124+
* @requires PHP 8
125+
*/
126+
public function testStrSplitThrowsOnInvalidLength()
127+
{
128+
$this->expectException(\ValueError::class);
129+
$this->expectExceptionMessage('Argument #2 ($length) must be greater than 0');
130+
131+
Php74::mb_str_split('победа', 0);
132+
}
133+
134+
/**
135+
* @covers \Symfony\Polyfill\Php74\Php74::mb_str_split
136+
*/
137+
public function testStrSplitWithLengthAbovePcreLimit()
138+
{
139+
$this->assertSame([str_repeat('x', 70000)], Php74::mb_str_split(str_repeat('x', 70000), 70000, 'UTF-8'));
140+
}
119141
}
120142

121143
class A

0 commit comments

Comments
 (0)