diff --git a/lib/BuiltinParamNames.php b/lib/BuiltinParamNames.php index d98d72c5c3..a3699a7809 100644 --- a/lib/BuiltinParamNames.php +++ b/lib/BuiltinParamNames.php @@ -526,6 +526,15 @@ public static function forFunction(string $name): ?array return ['string', 'start', 'width', 'trimmarker', 'encoding']; case 'mb_convert_encoding': return ['string', 'to_encoding', 'from_encoding']; + // php-src ext/mbstring/mbstring.stub.php — Reflection had empty params (#23291) + case 'mb_chr': + return ['codepoint', 'encoding']; + case 'mb_ord': + return ['string', 'encoding']; + case 'mb_scrub': + return ['string', 'encoding']; + case 'mb_str_split': + return ['string', 'length', 'encoding']; case 'mb_trim': case 'mb_ltrim': case 'mb_rtrim': diff --git a/prelinked/bootstrap-gen0/.m3_compiler_lib_sidecar.sha b/prelinked/bootstrap-gen0/.m3_compiler_lib_sidecar.sha index 6cf0e208b1..3cecb55eb0 100755 --- a/prelinked/bootstrap-gen0/.m3_compiler_lib_sidecar.sha +++ b/prelinked/bootstrap-gen0/.m3_compiler_lib_sidecar.sha @@ -1 +1 @@ -7b1884f9ccd8797602e3db7a9461a56f58d70a72 \ No newline at end of file +32e122fc45eae93276634011bfdb7ff1ba8c8911 \ No newline at end of file diff --git a/test/compliance/cases/mbstring/named_args_mb_chr_ord.phpt b/test/compliance/cases/mbstring/named_args_mb_chr_ord.phpt new file mode 100644 index 0000000000..fb4ed65d9b --- /dev/null +++ b/test/compliance/cases/mbstring/named_args_mb_chr_ord.phpt @@ -0,0 +1,23 @@ +--TEST-- +mb_chr/mb_ord named arguments (VM, issue #23291) +--FILE-- +getParameters() as $p) { + echo $p->getName(), PHP_EOL; +} +$rf = new ReflectionFunction('mb_ord'); +foreach ($rf->getParameters() as $p) { + echo $p->getName(), PHP_EOL; +} +--EXPECT-- +'A' +65 +codepoint +encoding +string +encoding diff --git a/test/repro/issue_23291_mb_chr_ord_named_params.php b/test/repro/issue_23291_mb_chr_ord_named_params.php new file mode 100644 index 0000000000..59477663cd --- /dev/null +++ b/test/repro/issue_23291_mb_chr_ord_named_params.php @@ -0,0 +1,21 @@ +getParameters() as $p) { + $chrNames[] = $p->getName(); +} +$ordNames = []; +foreach ((new ReflectionFunction('mb_ord'))->getParameters() as $p) { + $ordNames[] = $p->getName(); +} +$namedChr = mb_chr(codepoint: 0x41); +$namedOrd = mb_ord(string: 'A'); +$positionalChr = mb_chr(0x41); +$positionalOrd = mb_ord('A'); +$ok = ['codepoint', 'encoding'] === $chrNames + && ['string', 'encoding'] === $ordNames + && 'A' === $namedChr + && 65 === $namedOrd + && $namedChr === $positionalChr + && $namedOrd === $positionalOrd; +echo $ok ? "ok\n" : "fail\n"; diff --git a/test/selfhost/compiler_lib_spine_smoke/main.php b/test/selfhost/compiler_lib_spine_smoke/main.php index 29645caddd..3ea1a2bc44 100644 --- a/test/selfhost/compiler_lib_spine_smoke/main.php +++ b/test/selfhost/compiler_lib_spine_smoke/main.php @@ -4362,6 +4362,7 @@ require_once __DIR__.'/../../../ext/xsl/XslExtensionPolicy.php'; require_once __DIR__.'/../../../ext/xsl/XsltClassMethod.php'; require_once __DIR__.'/../../../ext/xsl/XsltHostBridge.php'; +require_once __DIR__.'/../../../ext/xsl/XsltPhpFunctionBridge.php'; require_once __DIR__.'/../../../ext/xsl/XsltProcessorConstruct.php'; require_once __DIR__.'/../../../ext/xsl/XsltProcessorGetParameter.php'; require_once __DIR__.'/../../../ext/xsl/XsltProcessorGetSecurityPrefs.php'; diff --git a/test/unit/BuiltinParamNamesAliasTest.php b/test/unit/BuiltinParamNamesAliasTest.php index b57fe71408..4e71b74c01 100644 --- a/test/unit/BuiltinParamNamesAliasTest.php +++ b/test/unit/BuiltinParamNamesAliasTest.php @@ -871,6 +871,30 @@ public function testChrZendStubNamedParams(): void self::assertFalse(BuiltinParamNames::lookupNamedParamIndex($names, 'ascii', 'chr')); } + /** @covers issue #23291 */ + public function testMbChrOrdZendStubNamedParams(): void + { + $chr = BuiltinParamNames::forFunction('mb_chr'); + self::assertSame(['codepoint', 'encoding'], $chr); + self::assertSame(0, BuiltinParamNames::lookupNamedParamIndex($chr, 'codepoint', 'mb_chr')); + self::assertSame(1, BuiltinParamNames::lookupNamedParamIndex($chr, 'encoding', 'mb_chr')); + + $ord = BuiltinParamNames::forFunction('mb_ord'); + self::assertSame(['string', 'encoding'], $ord); + self::assertSame(0, BuiltinParamNames::lookupNamedParamIndex($ord, 'string', 'mb_ord')); + self::assertSame(1, BuiltinParamNames::lookupNamedParamIndex($ord, 'encoding', 'mb_ord')); + + $scrub = BuiltinParamNames::forFunction('mb_scrub'); + self::assertSame(['string', 'encoding'], $scrub); + self::assertSame(0, BuiltinParamNames::lookupNamedParamIndex($scrub, 'string', 'mb_scrub')); + + $split = BuiltinParamNames::forFunction('mb_str_split'); + self::assertSame(['string', 'length', 'encoding'], $split); + self::assertSame(0, BuiltinParamNames::lookupNamedParamIndex($split, 'string', 'mb_str_split')); + self::assertSame(1, BuiltinParamNames::lookupNamedParamIndex($split, 'length', 'mb_str_split')); + self::assertSame(2, BuiltinParamNames::lookupNamedParamIndex($split, 'encoding', 'mb_str_split')); + } + /** @covers issue #23205 */ public function testHashEqualsZendStubNamedParams(): void {