diff --git a/ext/standard/similar_text.php b/ext/standard/similar_text.php index 1ad5347d339..7c4c44ced28 100644 --- a/ext/standard/similar_text.php +++ b/ext/standard/similar_text.php @@ -8,9 +8,11 @@ use PHPCompiler\Func\Internal; use PHPCompiler\JIT\Builtin\StringSimilarText; use PHPCompiler\JIT\Context; +use PHPCompiler\JIT\InternalStrictArg as JitInternalStrictArg; use PHPCompiler\JIT\JitStringBuiltinArg; use PHPCompiler\JIT\JitValueBox; use PHPCompiler\JIT\Variable as JITVariable; +use PHPCompiler\VM\InternalStrictArg; use PHPLLVM\Builder; use PHPLLVM\Value; @@ -30,8 +32,8 @@ public function execute(Frame $frame): void if ($argc < 2 || $argc > 3) { throw new \LogicException('similar_text() accepts two or three arguments in this compiler build'); } - $s1 = VmString::coerceStringBuiltinArg($frame->calledArgs[0], 'similar_text', 0, 'string1'); - $s2 = VmString::coerceStringBuiltinArg($frame->calledArgs[1], 'similar_text', 1, 'string2'); + $s1 = self::vmStringArg($frame, 0, 'string1'); + $s2 = self::vmStringArg($frame, 1, 'string2'); if (3 === $argc) { $percent = 0.0; $sim = VmString::similar_text($s1, $s2, $percent); @@ -55,8 +57,8 @@ public function call(Context $context, JITVariable ...$args): Value throw new \LogicException('similar_text() accepts two or three arguments in this compiler build'); } StringSimilarText::ensureLinked($context); - $str0 = JitStringBuiltinArg::lower($context, $args[0], 'similar_text', 0, 'string1'); - $str1 = JitStringBuiltinArg::lower($context, $args[1], 'similar_text', 1, 'string2'); + $str0 = self::jitStringArg($context, $args[0], 1, 'string1'); + $str1 = self::jitStringArg($context, $args[1], 2, 'string2'); $p0 = $this->stringDataPtr($context, $str0); $p1 = $this->stringDataPtr($context, $str1); $fn = $context->lookupFunction('phpc_similar_text'); @@ -71,6 +73,37 @@ public function call(Context $context, JITVariable ...$args): Value return $sim; } + private static function vmStringArg(Frame $frame, int $argIndex, string $paramName): string + { + if (null !== $frame->parent && $frame->parent->block->strictTypes) { + return InternalStrictArg::requireString($frame, $argIndex, 'similar_text', $paramName)->toString(); + } + + return VmString::coerceStringBuiltinArg( + $frame->calledArgs[$argIndex], + 'similar_text', + $argIndex, + $paramName + ); + } + + private static function jitStringArg( + Context $context, + JITVariable $arg, + int $argNumber, + string $paramName + ): Value { + JitInternalStrictArg::requireString($context, $arg, 'similar_text', $paramName, $argNumber); + + return JitStringBuiltinArg::lower( + $context, + $arg, + 'similar_text', + $argNumber - 1, + $paramName + ); + } + private function jitWriteSimilarityPercent( Context $context, Value $strData0, diff --git a/test/compliance/SimilarTextJITTest.php b/test/compliance/SimilarTextJITTest.php index 86bdeaf1abc..cb53aabfb39 100644 --- a/test/compliance/SimilarTextJITTest.php +++ b/test/compliance/SimilarTextJITTest.php @@ -25,6 +25,10 @@ public static function providePHPTests(): \Generator __DIR__.'/cases/stdlib/similar_text_coerce_jit.phpt', 'similar_text_coerce_jit.phpt' ); + yield 'similar_text_strict_types_jit.phpt' => self::parsePHPT( + __DIR__.'/cases/stdlib/similar_text_strict_types_jit.phpt', + 'similar_text_strict_types_jit.phpt' + ); } public function setUp(): void diff --git a/test/compliance/SimilarTextVMTest.php b/test/compliance/SimilarTextVMTest.php index 28f8ef0351a..ed0763aa58f 100644 --- a/test/compliance/SimilarTextVMTest.php +++ b/test/compliance/SimilarTextVMTest.php @@ -29,6 +29,10 @@ public static function providePHPTests(): \Generator __DIR__.'/cases/stdlib/similar_text_type_error.phpt', 'similar_text_type_error.phpt' ); + yield 'similar_text_strict_types.phpt' => self::parsePHPT( + __DIR__.'/cases/stdlib/similar_text_strict_types.phpt', + 'similar_text_strict_types.phpt' + ); } public function setUp(): void diff --git a/test/compliance/cases/stdlib/similar_text_strict_types.phpt b/test/compliance/cases/stdlib/similar_text_strict_types.phpt new file mode 100644 index 00000000000..34e7102926e --- /dev/null +++ b/test/compliance/cases/stdlib/similar_text_strict_types.phpt @@ -0,0 +1,18 @@ +--TEST-- +stdlib similar_text() — strict call-site TypeError on int operands (#9519, ext/standard/string.c) +--FILE-- +getMessage(), "\n"; +} +$p = 0.0; +similar_text('hello', 'hello world', $p); +var_export($p > 99.0); +echo "\n"; +--EXPECT-- +TypeError: similar_text(): Argument #1 ($string1) must be of type string, int given +false diff --git a/test/compliance/cases/stdlib/similar_text_strict_types_jit.phpt b/test/compliance/cases/stdlib/similar_text_strict_types_jit.phpt new file mode 100644 index 00000000000..8080ae8f493 --- /dev/null +++ b/test/compliance/cases/stdlib/similar_text_strict_types_jit.phpt @@ -0,0 +1,14 @@ +--TEST-- +stdlib similar_text() JIT — strict call-site TypeError on int operands (#9519) +--JIT-- +--FILE-- +getMessage(), "\n"; +} +--EXPECT-- +TypeError: similar_text(): Argument #1 ($string1) must be of type string, int given diff --git a/test/repro/issue_4543_similar_text.php b/test/repro/issue_4543_similar_text.php index deaa066b2ba..4669b7824bb 100644 --- a/test/repro/issue_4543_similar_text.php +++ b/test/repro/issue_4543_similar_text.php @@ -1,10 +1,8 @@