diff --git a/ext/standard/JitStrReplaceArray.php b/ext/standard/JitStrReplaceArray.php index b9ed6609a66..3eb6e563b73 100644 --- a/ext/standard/JitStrReplaceArray.php +++ b/ext/standard/JitStrReplaceArray.php @@ -8,6 +8,7 @@ use PHPCompiler\JIT\BasicBlockHelper; use PHPCompiler\JIT\Context; use PHPCompiler\JIT\HashTableHelper; +use PHPCompiler\JIT\JitValueBox; use PHPCompiler\JIT\Variable; use PHPLLVM\Builder; use PHPLLVM\Value; @@ -82,26 +83,13 @@ private static function buildReplaceHashTable( $context->builder->branchIf($isSet, $replaceBlock, $skipUnset); $context->builder->positionAtEnd($replaceBlock); - $entry = self::listEntryAt($context, $src, $srcIdx); - $valueMap = $context->structFieldMap['__value__']; - $typeByte = $context->builder->load( - $context->builder->structGep($entry, $valueMap['type']) - ); - $i8 = $context->getTypeFromString('int8'); - $isString = $context->builder->icmp( - Builder::INT_EQ, - $typeByte, - $i8->constInt(Variable::TYPE_STRING & 0xff, false) - ); - $doReplaceBlock = BasicBlockHelper::append($context, 'str_replace_do_'.$id); - $context->builder->branchIf($isString, $doReplaceBlock, $skipUnset); - - $context->builder->positionAtEnd($doReplaceBlock); + // php-src convert_to_string per array subject value (#27165). $strPtrTy = $context->getTypeFromString('__string__*'); $itemResultSlot = $context->builder->alloca($strPtrTy, 1, 'str_replace_arr_item_'.$id); - $subject = $context->builder->call( - $context->lookupFunction('__value__readString'), - $entry + $entryBox = HashTableHelper::readIndexedToValueBox($context, $src, $srcIdx); + $subject = (new strval())->valueToString( + $context, + JitValueBox::pointer($context, $entryBox->value) ); $itemCountSlot = null; if (null !== $countSlot) { @@ -158,14 +146,4 @@ private static function buildReplaceHashTable( return $phi; } - - private static function listEntryAt(Context $context, Value $ht, Value $index): Value - { - $map = $context->structFieldMap['__hashtable__']; - $values = $context->builder->load( - $context->builder->structGep($ht, $map['values']) - ); - - return $context->builder->inBoundsGep($values, $index); - } } diff --git a/ext/standard/str_ireplace.php b/ext/standard/str_ireplace.php index 6932a84af3f..efba56f734b 100644 --- a/ext/standard/str_ireplace.php +++ b/ext/standard/str_ireplace.php @@ -80,16 +80,12 @@ public function execute(Frame $frame): void $ht = new HashTable(); $totalCount = 0; foreach ($subjectVar->toArray()->iterateKeyed(true) as [$key, $value]) { - if (Variable::TYPE_STRING !== $value->type) { - throw new \LogicException( - 'str_ireplace() array subject values must be strings in this compiler build' - ); - } + // php-src php_str_replace_array: convert_to_string per array subject (#27165). $elemCount = 0; $replaced = self::replaceWithNeedles( $searchNeedles, $replaceOperand, - $value->toString(), + $value->resolveIndirect()->toString(null, $frame), $elemCount ); $totalCount += $elemCount; diff --git a/ext/standard/str_replace.php b/ext/standard/str_replace.php index 620d4b47279..b99ee0d488b 100644 --- a/ext/standard/str_replace.php +++ b/ext/standard/str_replace.php @@ -78,16 +78,12 @@ public function execute(Frame $frame): void $ht = new HashTable(); $totalCount = 0; foreach ($subjectVar->toArray()->iterateKeyed(true) as [$key, $value]) { - if (Variable::TYPE_STRING !== $value->type) { - throw new \LogicException( - 'str_replace() array subject values must be strings in this compiler build' - ); - } + // php-src php_str_replace_array: convert_to_string per array subject (#27165). $elemCount = 0; $replaced = self::replaceWithNeedles( $searchNeedles, $replaceOperand, - $value->toString(), + $value->resolveIndirect()->toString(null, $frame), $elemCount ); $totalCount += $elemCount; diff --git a/test/compliance/cases/stdlib/str_replace_array_value_coerce.phpt b/test/compliance/cases/stdlib/str_replace_array_value_coerce.phpt new file mode 100644 index 00000000000..6affbb0c1ef --- /dev/null +++ b/test/compliance/cases/stdlib/str_replace_array_value_coerce.phpt @@ -0,0 +1,18 @@ +--TEST-- +stdlib str_replace/str_ireplace coerce non-string array subject values (#27165, ext/standard/string.c) +--FILE-- + 'X2', + 1 => 'X3', +) +array ( + 0 => 'X', + 1 => '12', + 2 => 'X', +) diff --git a/test/compliance/cases/stdlib/str_replace_array_value_coerce_jit.phpt b/test/compliance/cases/stdlib/str_replace_array_value_coerce_jit.phpt new file mode 100644 index 00000000000..6b36c8649aa --- /dev/null +++ b/test/compliance/cases/stdlib/str_replace_array_value_coerce_jit.phpt @@ -0,0 +1,18 @@ +--TEST-- +stdlib str_replace/str_ireplace coerce non-string array subject values JIT (#27165, ext/standard/string.c) +--FILE-- + 'X2', + 1 => 'X3', +) +array ( + 0 => 'X', + 1 => '12', + 2 => 'X', +) diff --git a/test/repro/issue_27165_str_replace_array_value_coerce.php b/test/repro/issue_27165_str_replace_array_value_coerce.php new file mode 100644 index 00000000000..ae337bd2ac8 --- /dev/null +++ b/test/repro/issue_27165_str_replace_array_value_coerce.php @@ -0,0 +1,5 @@ +