mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2: Fix GH-8996: DOMNode serialization on PHP ^8.1 Fix GH-12380: JIT+private array property access inside closure accesses private property in child class
This commit is contained in:
commit
58a1103bee
9 changed files with 270 additions and 11 deletions
3
NEWS
3
NEWS
|
@ -17,6 +17,7 @@ PHP NEWS
|
||||||
. Restore old namespace reconciliation behaviour. (nielsdos)
|
. Restore old namespace reconciliation behaviour. (nielsdos)
|
||||||
. Fix broken cache invalidation with deallocated and reallocated document
|
. Fix broken cache invalidation with deallocated and reallocated document
|
||||||
node. (nielsdos)
|
node. (nielsdos)
|
||||||
|
. Fixed bug GH-8996 (DOMNode serialization on PHP ^8.1). (nielsdos)
|
||||||
|
|
||||||
- Fileinfo:
|
- Fileinfo:
|
||||||
. Fixed bug GH-11891 (fileinfo returns text/xml for some svg files). (usarise)
|
. Fixed bug GH-11891 (fileinfo returns text/xml for some svg files). (usarise)
|
||||||
|
@ -31,6 +32,8 @@ PHP NEWS
|
||||||
|
|
||||||
- Opcache:
|
- Opcache:
|
||||||
. Fixed opcache_invalidate() on deleted file. (mikhainin)
|
. Fixed opcache_invalidate() on deleted file. (mikhainin)
|
||||||
|
. Fixed bug GH-12380 (JIT+private array property access inside closure
|
||||||
|
accesses private property in child class). (nielsdos)
|
||||||
|
|
||||||
- SimpleXML:
|
- SimpleXML:
|
||||||
. Apply iterator fixes only on master. (nielsdos)
|
. Apply iterator fixes only on master. (nielsdos)
|
||||||
|
|
|
@ -2030,4 +2030,25 @@ PHP_METHOD(DOMNode, getRootNode)
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We want to block the serialization and unserialization of DOM classes.
|
||||||
|
* However, using @not-serializable makes the child classes also not serializable, even if the user implements the methods.
|
||||||
|
* So instead, we implement the methods wherein we throw exceptions.
|
||||||
|
* The reason we choose these methods is because:
|
||||||
|
* - If the user implements __serialize / __unserialize, the respective throwing methods are not called.
|
||||||
|
* - If the user implements __sleep / __wakeup, then it's also not a problem because they will not enter the throwing methods.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PHP_METHOD(DOMNode, __sleep)
|
||||||
|
{
|
||||||
|
zend_throw_exception_ex(NULL, 0, "Serialization of '%s' is not allowed, unless serialization methods are implemented in a subclass", ZSTR_VAL(Z_OBJCE_P(ZEND_THIS)->name));
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP_METHOD(DOMNode, __wakeup)
|
||||||
|
{
|
||||||
|
zend_throw_exception_ex(NULL, 0, "Unserialization of '%s' is not allowed, unless unserialization methods are implemented in a subclass", ZSTR_VAL(Z_OBJCE_P(ZEND_THIS)->name));
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -294,7 +294,6 @@ interface DOMChildNode
|
||||||
public function replaceWith(...$nodes): void;
|
public function replaceWith(...$nodes): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @not-serializable */
|
|
||||||
class DOMNode
|
class DOMNode
|
||||||
{
|
{
|
||||||
/** @readonly */
|
/** @readonly */
|
||||||
|
@ -348,6 +347,10 @@ class DOMNode
|
||||||
|
|
||||||
public string $textContent;
|
public string $textContent;
|
||||||
|
|
||||||
|
public function __sleep(): array {}
|
||||||
|
|
||||||
|
public function __wakeup(): void {}
|
||||||
|
|
||||||
/** @return DOMNode|false */
|
/** @return DOMNode|false */
|
||||||
public function appendChild(DOMNode $node) {}
|
public function appendChild(DOMNode $node) {}
|
||||||
|
|
||||||
|
@ -406,7 +409,6 @@ class DOMNode
|
||||||
public function getRootNode(?array $options = null): DOMNode {}
|
public function getRootNode(?array $options = null): DOMNode {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @not-serializable */
|
|
||||||
class DOMNameSpaceNode
|
class DOMNameSpaceNode
|
||||||
{
|
{
|
||||||
/** @readonly */
|
/** @readonly */
|
||||||
|
@ -438,6 +440,12 @@ class DOMNameSpaceNode
|
||||||
|
|
||||||
/** @readonly */
|
/** @readonly */
|
||||||
public ?DOMElement $parentElement;
|
public ?DOMElement $parentElement;
|
||||||
|
|
||||||
|
/** @implementation-alias DOMNode::__sleep */
|
||||||
|
public function __sleep(): array {}
|
||||||
|
|
||||||
|
/** @implementation-alias DOMNode::__wakeup */
|
||||||
|
public function __wakeup(): void {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DOMImplementation
|
class DOMImplementation
|
||||||
|
|
22
ext/dom/php_dom_arginfo.h
generated
22
ext/dom/php_dom_arginfo.h
generated
|
@ -1,5 +1,5 @@
|
||||||
/* This is a generated file, edit the .stub.php file instead.
|
/* This is a generated file, edit the .stub.php file instead.
|
||||||
* Stub hash: ebe9bcbd185e1973b5447beb306bd9d93051f415 */
|
* Stub hash: a20d21c1796ebb43028856f0ec2d53dcaded6cc0 */
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_dom_import_simplexml, 0, 1, DOMElement, 0)
|
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_dom_import_simplexml, 0, 1, DOMElement, 0)
|
||||||
ZEND_ARG_TYPE_INFO(0, node, IS_OBJECT, 0)
|
ZEND_ARG_TYPE_INFO(0, node, IS_OBJECT, 0)
|
||||||
|
@ -30,6 +30,11 @@ ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
#define arginfo_class_DOMChildNode_replaceWith arginfo_class_DOMParentNode_append
|
#define arginfo_class_DOMChildNode_replaceWith arginfo_class_DOMParentNode_append
|
||||||
|
|
||||||
|
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_DOMNode___sleep, 0, 0, IS_ARRAY, 0)
|
||||||
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
#define arginfo_class_DOMNode___wakeup arginfo_class_DOMChildNode_remove
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DOMNode_appendChild, 0, 0, 1)
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DOMNode_appendChild, 0, 0, 1)
|
||||||
ZEND_ARG_OBJ_INFO(0, node, DOMNode, 0)
|
ZEND_ARG_OBJ_INFO(0, node, DOMNode, 0)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
@ -114,6 +119,10 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_DOMNode_getRootNode, 0, 0,
|
||||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 1, "null")
|
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 1, "null")
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
#define arginfo_class_DOMNameSpaceNode___sleep arginfo_class_DOMNode___sleep
|
||||||
|
|
||||||
|
#define arginfo_class_DOMNameSpaceNode___wakeup arginfo_class_DOMChildNode_remove
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DOMImplementation_getFeature, 0, 2, IS_NEVER, 0)
|
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DOMImplementation_getFeature, 0, 2, IS_NEVER, 0)
|
||||||
ZEND_ARG_TYPE_INFO(0, feature, IS_STRING, 0)
|
ZEND_ARG_TYPE_INFO(0, feature, IS_STRING, 0)
|
||||||
ZEND_ARG_TYPE_INFO(0, version, IS_STRING, 0)
|
ZEND_ARG_TYPE_INFO(0, version, IS_STRING, 0)
|
||||||
|
@ -205,8 +214,7 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DOMElement_getAt
|
||||||
ZEND_ARG_TYPE_INFO(0, qualifiedName, IS_STRING, 0)
|
ZEND_ARG_TYPE_INFO(0, qualifiedName, IS_STRING, 0)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_DOMElement_getAttributeNames, 0, 0, IS_ARRAY, 0)
|
#define arginfo_class_DOMElement_getAttributeNames arginfo_class_DOMNode___sleep
|
||||||
ZEND_END_ARG_INFO()
|
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DOMElement_getAttributeNS, 0, 2, IS_STRING, 0)
|
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DOMElement_getAttributeNS, 0, 2, IS_STRING, 0)
|
||||||
ZEND_ARG_TYPE_INFO(0, namespace, IS_STRING, 1)
|
ZEND_ARG_TYPE_INFO(0, namespace, IS_STRING, 1)
|
||||||
|
@ -533,6 +541,8 @@ ZEND_END_ARG_INFO()
|
||||||
ZEND_FUNCTION(dom_import_simplexml);
|
ZEND_FUNCTION(dom_import_simplexml);
|
||||||
ZEND_METHOD(DOMCdataSection, __construct);
|
ZEND_METHOD(DOMCdataSection, __construct);
|
||||||
ZEND_METHOD(DOMComment, __construct);
|
ZEND_METHOD(DOMComment, __construct);
|
||||||
|
ZEND_METHOD(DOMNode, __sleep);
|
||||||
|
ZEND_METHOD(DOMNode, __wakeup);
|
||||||
ZEND_METHOD(DOMNode, appendChild);
|
ZEND_METHOD(DOMNode, appendChild);
|
||||||
ZEND_METHOD(DOMNode, C14N);
|
ZEND_METHOD(DOMNode, C14N);
|
||||||
ZEND_METHOD(DOMNode, C14NFile);
|
ZEND_METHOD(DOMNode, C14NFile);
|
||||||
|
@ -725,6 +735,8 @@ static const zend_function_entry class_DOMChildNode_methods[] = {
|
||||||
|
|
||||||
|
|
||||||
static const zend_function_entry class_DOMNode_methods[] = {
|
static const zend_function_entry class_DOMNode_methods[] = {
|
||||||
|
ZEND_ME(DOMNode, __sleep, arginfo_class_DOMNode___sleep, ZEND_ACC_PUBLIC)
|
||||||
|
ZEND_ME(DOMNode, __wakeup, arginfo_class_DOMNode___wakeup, ZEND_ACC_PUBLIC)
|
||||||
ZEND_ME(DOMNode, appendChild, arginfo_class_DOMNode_appendChild, ZEND_ACC_PUBLIC)
|
ZEND_ME(DOMNode, appendChild, arginfo_class_DOMNode_appendChild, ZEND_ACC_PUBLIC)
|
||||||
ZEND_ME(DOMNode, C14N, arginfo_class_DOMNode_C14N, ZEND_ACC_PUBLIC)
|
ZEND_ME(DOMNode, C14N, arginfo_class_DOMNode_C14N, ZEND_ACC_PUBLIC)
|
||||||
ZEND_ME(DOMNode, C14NFile, arginfo_class_DOMNode_C14NFile, ZEND_ACC_PUBLIC)
|
ZEND_ME(DOMNode, C14NFile, arginfo_class_DOMNode_C14NFile, ZEND_ACC_PUBLIC)
|
||||||
|
@ -750,6 +762,8 @@ static const zend_function_entry class_DOMNode_methods[] = {
|
||||||
|
|
||||||
|
|
||||||
static const zend_function_entry class_DOMNameSpaceNode_methods[] = {
|
static const zend_function_entry class_DOMNameSpaceNode_methods[] = {
|
||||||
|
ZEND_MALIAS(DOMNode, __sleep, __sleep, arginfo_class_DOMNameSpaceNode___sleep, ZEND_ACC_PUBLIC)
|
||||||
|
ZEND_MALIAS(DOMNode, __wakeup, __wakeup, arginfo_class_DOMNameSpaceNode___wakeup, ZEND_ACC_PUBLIC)
|
||||||
ZEND_FE_END
|
ZEND_FE_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1096,7 +1110,6 @@ static zend_class_entry *register_class_DOMNode(void)
|
||||||
|
|
||||||
INIT_CLASS_ENTRY(ce, "DOMNode", class_DOMNode_methods);
|
INIT_CLASS_ENTRY(ce, "DOMNode", class_DOMNode_methods);
|
||||||
class_entry = zend_register_internal_class_ex(&ce, NULL);
|
class_entry = zend_register_internal_class_ex(&ce, NULL);
|
||||||
class_entry->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE;
|
|
||||||
|
|
||||||
zval property_nodeName_default_value;
|
zval property_nodeName_default_value;
|
||||||
ZVAL_UNDEF(&property_nodeName_default_value);
|
ZVAL_UNDEF(&property_nodeName_default_value);
|
||||||
|
@ -1224,7 +1237,6 @@ static zend_class_entry *register_class_DOMNameSpaceNode(void)
|
||||||
|
|
||||||
INIT_CLASS_ENTRY(ce, "DOMNameSpaceNode", class_DOMNameSpaceNode_methods);
|
INIT_CLASS_ENTRY(ce, "DOMNameSpaceNode", class_DOMNameSpaceNode_methods);
|
||||||
class_entry = zend_register_internal_class_ex(&ce, NULL);
|
class_entry = zend_register_internal_class_ex(&ce, NULL);
|
||||||
class_entry->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE;
|
|
||||||
|
|
||||||
zval property_nodeName_default_value;
|
zval property_nodeName_default_value;
|
||||||
ZVAL_UNDEF(&property_nodeName_default_value);
|
ZVAL_UNDEF(&property_nodeName_default_value);
|
||||||
|
|
120
ext/dom/tests/gh8996.phpt
Normal file
120
ext/dom/tests/gh8996.phpt
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
--TEST--
|
||||||
|
GH-8996: DOMNode serialization on PHP ^8.1
|
||||||
|
--EXTENSIONS--
|
||||||
|
dom
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
echo "=== __sleep and __wakeup ===\n";
|
||||||
|
|
||||||
|
class SerializableDomDocumentSleepWakeup extends DOMDocument
|
||||||
|
{
|
||||||
|
private $xmlData;
|
||||||
|
|
||||||
|
public function __sleep(): array
|
||||||
|
{
|
||||||
|
$this->xmlData = $this->saveXML();
|
||||||
|
return ['xmlData'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __wakeup(): void
|
||||||
|
{
|
||||||
|
$this->loadXML($this->xmlData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$dom = new SerializableDomDocumentSleepWakeup('1.0', 'UTF-8');
|
||||||
|
$dom->loadXML('<tag>value</tag>');
|
||||||
|
|
||||||
|
$serialized = serialize($dom);
|
||||||
|
var_dump($serialized);
|
||||||
|
$unserialized = unserialize($serialized);
|
||||||
|
|
||||||
|
echo "Serialized:\n-----------\n$serialized\n-----------\nRestored:\n-----------\n{$unserialized->saveXml()}";
|
||||||
|
|
||||||
|
echo "=== __serialize and __unserialize ===\n";
|
||||||
|
|
||||||
|
class SerializableDomDocument__Serialize__Unserialize extends DOMDocument
|
||||||
|
{
|
||||||
|
public function __serialize(): array
|
||||||
|
{
|
||||||
|
return ['xmlData' => $this->saveXML()];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __unserialize(array $data): void
|
||||||
|
{
|
||||||
|
$this->loadXML($data['xmlData']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$dom = new SerializableDomDocument__Serialize__Unserialize('1.0', 'UTF-8');
|
||||||
|
$dom->loadXML('<tag>value</tag>');
|
||||||
|
|
||||||
|
$serialized = serialize($dom);
|
||||||
|
$unserialized = unserialize($serialized);
|
||||||
|
|
||||||
|
echo "Serialized:\n-----------\n$serialized\n-----------\nRestored:\n-----------\n{$unserialized->saveXml()}";
|
||||||
|
|
||||||
|
echo "=== serialize and unserialize ===\n";
|
||||||
|
|
||||||
|
class SerializableDomDocumentSerializeUnserialize extends DOMDocument implements Serializable
|
||||||
|
{
|
||||||
|
public function serialize(): ?string
|
||||||
|
{
|
||||||
|
return $this->saveXML();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function unserialize(string $data): void
|
||||||
|
{
|
||||||
|
$this->loadXML($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$dom = new SerializableDomDocumentSerializeUnserialize('1.0', 'UTF-8');
|
||||||
|
$dom->loadXML('<tag>value</tag>');
|
||||||
|
|
||||||
|
$serialized = serialize($dom);
|
||||||
|
$unserialized = unserialize($serialized);
|
||||||
|
|
||||||
|
echo "Serialized:\n-----------\n$serialized\n-----------\nRestored:\n-----------\n{$unserialized->saveXml()}";
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
=== __sleep and __wakeup ===
|
||||||
|
string(144) "O:34:"SerializableDomDocumentSleepWakeup":1:{s:43:"%0SerializableDomDocumentSleepWakeup%0xmlData";s:39:"<?xml version="1.0"?>
|
||||||
|
<tag>value</tag>
|
||||||
|
";}"
|
||||||
|
Serialized:
|
||||||
|
-----------
|
||||||
|
O:34:"SerializableDomDocumentSleepWakeup":1:{s:43:"%0SerializableDomDocumentSleepWakeup%0xmlData";s:39:"<?xml version="1.0"?>
|
||||||
|
<tag>value</tag>
|
||||||
|
";}
|
||||||
|
-----------
|
||||||
|
Restored:
|
||||||
|
-----------
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<tag>value</tag>
|
||||||
|
=== __serialize and __unserialize ===
|
||||||
|
Serialized:
|
||||||
|
-----------
|
||||||
|
O:47:"SerializableDomDocument__Serialize__Unserialize":1:{s:7:"xmlData";s:39:"<?xml version="1.0"?>
|
||||||
|
<tag>value</tag>
|
||||||
|
";}
|
||||||
|
-----------
|
||||||
|
Restored:
|
||||||
|
-----------
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<tag>value</tag>
|
||||||
|
=== serialize and unserialize ===
|
||||||
|
|
||||||
|
Deprecated: SerializableDomDocumentSerializeUnserialize implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d
|
||||||
|
Serialized:
|
||||||
|
-----------
|
||||||
|
C:43:"SerializableDomDocumentSerializeUnserialize":39:{<?xml version="1.0"?>
|
||||||
|
<tag>value</tag>
|
||||||
|
}
|
||||||
|
-----------
|
||||||
|
Restored:
|
||||||
|
-----------
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<tag>value</tag>
|
|
@ -36,7 +36,7 @@ try {
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECT--
|
--EXPECT--
|
||||||
Serialization of 'DOMDocument' is not allowed
|
Serialization of 'DOMDocument' is not allowed, unless serialization methods are implemented in a subclass
|
||||||
Serialization of 'DOMElement' is not allowed
|
Serialization of 'DOMElement' is not allowed, unless serialization methods are implemented in a subclass
|
||||||
Serialization of 'DOMXPath' is not allowed
|
Serialization of 'DOMXPath' is not allowed
|
||||||
Serialization of 'DOMNameSpaceNode' is not allowed
|
Serialization of 'DOMNameSpaceNode' is not allowed, unless serialization methods are implemented in a subclass
|
||||||
|
|
29
ext/dom/tests/not_unserializable.phpt
Normal file
29
ext/dom/tests/not_unserializable.phpt
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
--TEST--
|
||||||
|
DOM classes are not unserializable
|
||||||
|
--EXTENSIONS--
|
||||||
|
dom
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$classes = [
|
||||||
|
"DOMXPath",
|
||||||
|
"DOMDocument",
|
||||||
|
"DOMNode",
|
||||||
|
"DOMNameSpaceNode",
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($classes as $class)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
unserialize('O:' . strlen($class) . ':"' . $class . '":0:{}');
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo $e->getMessage(), "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
Unserialization of 'DOMXPath' is not allowed
|
||||||
|
Unserialization of 'DOMDocument' is not allowed, unless unserialization methods are implemented in a subclass
|
||||||
|
Unserialization of 'DOMNode' is not allowed, unless unserialization methods are implemented in a subclass
|
||||||
|
Unserialization of 'DOMNameSpaceNode' is not allowed, unless unserialization methods are implemented in a subclass
|
|
@ -682,7 +682,11 @@ static zend_property_info* zend_get_known_property_info(const zend_op_array *op_
|
||||||
return info;
|
return info;
|
||||||
} else if (on_this) {
|
} else if (on_this) {
|
||||||
if (ce == info->ce) {
|
if (ce == info->ce) {
|
||||||
return info;
|
if (ce == op_array->scope) {
|
||||||
|
return info;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
} else if ((info->flags & ZEND_ACC_PROTECTED)
|
} else if ((info->flags & ZEND_ACC_PROTECTED)
|
||||||
&& instanceof_function_slow(ce, info->ce)) {
|
&& instanceof_function_slow(ce, info->ce)) {
|
||||||
return info;
|
return info;
|
||||||
|
|
62
ext/opcache/tests/jit/gh12380.phpt
Normal file
62
ext/opcache/tests/jit/gh12380.phpt
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
--TEST--
|
||||||
|
GH-12380: JIT+private array property access inside closure accesses private property in child class
|
||||||
|
--INI--
|
||||||
|
opcache.enable=1
|
||||||
|
opcache.enable_cli=1
|
||||||
|
opcache.file_update_protection=0
|
||||||
|
opcache.jit_buffer_size=1M
|
||||||
|
opcache.protect_memory=1
|
||||||
|
opcache.jit=tracing
|
||||||
|
opcache.jit_hot_loop=1
|
||||||
|
opcache.jit_hot_func=1
|
||||||
|
opcache.jit_hot_return=1
|
||||||
|
opcache.jit_hot_side_exit=1
|
||||||
|
--EXTENSIONS--
|
||||||
|
opcache
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class a
|
||||||
|
{
|
||||||
|
private int $v = 1;
|
||||||
|
|
||||||
|
public function test(): void
|
||||||
|
{
|
||||||
|
var_dump($this->v);
|
||||||
|
(function (): void {
|
||||||
|
var_dump($this->v);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class b extends a {
|
||||||
|
private int $v = 0;
|
||||||
|
}
|
||||||
|
$a = new b;
|
||||||
|
|
||||||
|
for ($i = 0; $i < 10; $i++) {
|
||||||
|
$a->test();
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
int(1)
|
||||||
|
int(1)
|
||||||
|
int(1)
|
||||||
|
int(1)
|
||||||
|
int(1)
|
||||||
|
int(1)
|
||||||
|
int(1)
|
||||||
|
int(1)
|
||||||
|
int(1)
|
||||||
|
int(1)
|
||||||
|
int(1)
|
||||||
|
int(1)
|
||||||
|
int(1)
|
||||||
|
int(1)
|
||||||
|
int(1)
|
||||||
|
int(1)
|
||||||
|
int(1)
|
||||||
|
int(1)
|
||||||
|
int(1)
|
||||||
|
int(1)
|
Loading…
Add table
Add a link
Reference in a new issue