mirror of
https://github.com/php/php-src.git
synced 2024-09-21 18:07:23 +00:00
Merge branch 'PHP-8.1' into PHP-8.2
* PHP-8.1: Fix GH-12223: Entity reference produces infinite loop in var_dump/print_r Fix GH-12192: SimpleXML infinite loop when getName() is called within foreach Fix GH-12186: segfault copying/cloning a finalized HashContext
This commit is contained in:
commit
5df473d2c7
8
NEWS
8
NEWS
@ -5,8 +5,16 @@ PHP NEWS
|
|||||||
- Filter:
|
- Filter:
|
||||||
. Fix explicit FILTER_REQUIRE_SCALAR with FILTER_CALLBACK (ilutov)
|
. Fix explicit FILTER_REQUIRE_SCALAR with FILTER_CALLBACK (ilutov)
|
||||||
|
|
||||||
|
- Hash:
|
||||||
|
. Fixed bug GH-12186 (segfault copying/cloning a finalized HashContext).
|
||||||
|
(MaxSem)
|
||||||
|
|
||||||
- SimpleXML:
|
- SimpleXML:
|
||||||
. Fixed bug GH-12170 (Can't use xpath with comments in SimpleXML). (nielsdos)
|
. Fixed bug GH-12170 (Can't use xpath with comments in SimpleXML). (nielsdos)
|
||||||
|
. Fixed bug GH-12192 (SimpleXML infinite loop when getName() is called
|
||||||
|
within foreach). (nielsdos)
|
||||||
|
. Fixed bug GH-12223 (Entity reference produces infinite loop in
|
||||||
|
var_dump/print_r). (nielsdos)
|
||||||
|
|
||||||
28 Sep 2023, PHP 8.2.11
|
28 Sep 2023, PHP 8.2.11
|
||||||
|
|
||||||
|
@ -681,7 +681,7 @@ PHP_FUNCTION(hash_init)
|
|||||||
|
|
||||||
#define PHP_HASHCONTEXT_VERIFY(hash) { \
|
#define PHP_HASHCONTEXT_VERIFY(hash) { \
|
||||||
if (!hash->context) { \
|
if (!hash->context) { \
|
||||||
zend_argument_type_error(1, "must be a valid Hash Context resource"); \
|
zend_argument_type_error(1, "must be a valid, non-finalized HashContext"); \
|
||||||
RETURN_THROWS(); \
|
RETURN_THROWS(); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
@ -838,11 +838,15 @@ PHP_FUNCTION(hash_final)
|
|||||||
PHP_FUNCTION(hash_copy)
|
PHP_FUNCTION(hash_copy)
|
||||||
{
|
{
|
||||||
zval *zhash;
|
zval *zhash;
|
||||||
|
php_hashcontext_object *context;
|
||||||
|
|
||||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &zhash, php_hashcontext_ce) == FAILURE) {
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &zhash, php_hashcontext_ce) == FAILURE) {
|
||||||
RETURN_THROWS();
|
RETURN_THROWS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context = php_hashcontext_from_object(Z_OBJ_P(zhash));
|
||||||
|
PHP_HASHCONTEXT_VERIFY(context);
|
||||||
|
|
||||||
RETVAL_OBJ(Z_OBJ_HANDLER_P(zhash, clone_obj)(Z_OBJ_P(zhash)));
|
RETVAL_OBJ(Z_OBJ_HANDLER_P(zhash, clone_obj)(Z_OBJ_P(zhash)));
|
||||||
|
|
||||||
if (php_hashcontext_from_object(Z_OBJ_P(return_value))->context == NULL) {
|
if (php_hashcontext_from_object(Z_OBJ_P(return_value))->context == NULL) {
|
||||||
@ -1395,6 +1399,11 @@ static zend_object *php_hashcontext_clone(zend_object *zobj) {
|
|||||||
zend_object *znew = php_hashcontext_create(zobj->ce);
|
zend_object *znew = php_hashcontext_create(zobj->ce);
|
||||||
php_hashcontext_object *newobj = php_hashcontext_from_object(znew);
|
php_hashcontext_object *newobj = php_hashcontext_from_object(znew);
|
||||||
|
|
||||||
|
if (!oldobj->context) {
|
||||||
|
zend_throw_exception(zend_ce_value_error, "Cannot clone a finalized HashContext", 0);
|
||||||
|
return znew;
|
||||||
|
}
|
||||||
|
|
||||||
zend_objects_clone_members(znew, zobj);
|
zend_objects_clone_members(znew, zobj);
|
||||||
|
|
||||||
newobj->ops = oldobj->ops;
|
newobj->ops = oldobj->ops;
|
||||||
|
17
ext/hash/tests/gh12186_1.phpt
Normal file
17
ext/hash/tests/gh12186_1.phpt
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
--TEST--
|
||||||
|
Hash: bug #12186 - segfault in hash_copy() on a finalized context
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$c = hash_init('sha1');
|
||||||
|
hash_final($c);
|
||||||
|
|
||||||
|
try {
|
||||||
|
hash_copy($c);
|
||||||
|
} catch (Throwable $ex) {
|
||||||
|
echo $ex->getMessage() . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
hash_copy(): Argument #1 ($context) must be a valid, non-finalized HashContext
|
17
ext/hash/tests/gh12186_2.phpt
Normal file
17
ext/hash/tests/gh12186_2.phpt
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
--TEST--
|
||||||
|
Hash: bug #12186 - segfault when cloning a finalized context
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$c = hash_init('sha1');
|
||||||
|
hash_final($c);
|
||||||
|
|
||||||
|
try {
|
||||||
|
clone $c;
|
||||||
|
} catch (Throwable $ex) {
|
||||||
|
echo $ex->getMessage() . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Cannot clone a finalized HashContext
|
@ -14,4 +14,4 @@ catch (\Error $e) {
|
|||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECT--
|
--EXPECT--
|
||||||
hash_update(): Argument #1 ($context) must be a valid Hash Context resource
|
hash_update(): Argument #1 ($context) must be a valid, non-finalized HashContext
|
||||||
|
@ -45,6 +45,7 @@ PHP_SXE_API zend_class_entry *sxe_get_element_class_entry(void) /* {{{ */
|
|||||||
|
|
||||||
static php_sxe_object* php_sxe_object_new(zend_class_entry *ce, zend_function *fptr_count);
|
static php_sxe_object* php_sxe_object_new(zend_class_entry *ce, zend_function *fptr_count);
|
||||||
static xmlNodePtr php_sxe_reset_iterator(php_sxe_object *sxe, int use_data);
|
static xmlNodePtr php_sxe_reset_iterator(php_sxe_object *sxe, int use_data);
|
||||||
|
static xmlNodePtr php_sxe_reset_iterator_no_clear_iter_data(php_sxe_object *sxe, int use_data);
|
||||||
static xmlNodePtr php_sxe_iterator_fetch(php_sxe_object *sxe, xmlNodePtr node, int use_data);
|
static xmlNodePtr php_sxe_iterator_fetch(php_sxe_object *sxe, xmlNodePtr node, int use_data);
|
||||||
static void php_sxe_iterator_dtor(zend_object_iterator *iter);
|
static void php_sxe_iterator_dtor(zend_object_iterator *iter);
|
||||||
static int php_sxe_iterator_valid(zend_object_iterator *iter);
|
static int php_sxe_iterator_valid(zend_object_iterator *iter);
|
||||||
@ -77,6 +78,7 @@ static void _node_as_zval(php_sxe_object *sxe, xmlNodePtr node, zval *value, SXE
|
|||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/* Important: this overwrites the iterator data, if you wish to keep it use php_sxe_get_first_node_non_destructive() instead! */
|
||||||
static xmlNodePtr php_sxe_get_first_node(php_sxe_object *sxe, xmlNodePtr node) /* {{{ */
|
static xmlNodePtr php_sxe_get_first_node(php_sxe_object *sxe, xmlNodePtr node) /* {{{ */
|
||||||
{
|
{
|
||||||
php_sxe_object *intern;
|
php_sxe_object *intern;
|
||||||
@ -95,6 +97,15 @@ static xmlNodePtr php_sxe_get_first_node(php_sxe_object *sxe, xmlNodePtr node) /
|
|||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
static xmlNodePtr php_sxe_get_first_node_non_destructive(php_sxe_object *sxe, xmlNodePtr node)
|
||||||
|
{
|
||||||
|
if (sxe && sxe->iter.type != SXE_ITER_NONE) {
|
||||||
|
return php_sxe_reset_iterator_no_clear_iter_data(sxe, false);
|
||||||
|
} else {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline int match_ns(php_sxe_object *sxe, xmlNodePtr node, xmlChar *name, int prefix) /* {{{ */
|
static inline int match_ns(php_sxe_object *sxe, xmlNodePtr node, xmlChar *name, int prefix) /* {{{ */
|
||||||
{
|
{
|
||||||
if (name == NULL && (node->ns == NULL || node->ns->prefix == NULL)) {
|
if (name == NULL && (node->ns == NULL || node->ns->prefix == NULL)) {
|
||||||
@ -1186,6 +1197,12 @@ static HashTable *sxe_get_prop_hash(zend_object *object, int is_debug) /* {{{ */
|
|||||||
sxe_properties_add(rv, name, namelen, &value);
|
sxe_properties_add(rv, name, namelen, &value);
|
||||||
}
|
}
|
||||||
next_iter:
|
next_iter:
|
||||||
|
if (UNEXPECTED(node->type == XML_ENTITY_DECL)) {
|
||||||
|
/* Entity decls are linked together via the next pointer.
|
||||||
|
* The only way to get to an entity decl is via an entity reference in the document.
|
||||||
|
* If we then continue iterating, we'll end up in the DTD. Even worse, if the entities reference each other we'll infinite loop. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (use_iter) {
|
if (use_iter) {
|
||||||
node = php_sxe_iterator_fetch(sxe, node->next, 0);
|
node = php_sxe_iterator_fetch(sxe, node->next, 0);
|
||||||
} else {
|
} else {
|
||||||
@ -1625,7 +1642,7 @@ PHP_METHOD(SimpleXMLElement, getName)
|
|||||||
sxe = Z_SXEOBJ_P(ZEND_THIS);
|
sxe = Z_SXEOBJ_P(ZEND_THIS);
|
||||||
|
|
||||||
GET_NODE(sxe, node);
|
GET_NODE(sxe, node);
|
||||||
node = php_sxe_get_first_node(sxe, node);
|
node = php_sxe_get_first_node_non_destructive(sxe, node);
|
||||||
if (node) {
|
if (node) {
|
||||||
namelen = xmlStrlen(node->name);
|
namelen = xmlStrlen(node->name);
|
||||||
RETURN_STRINGL((char*)node->name, namelen);
|
RETURN_STRINGL((char*)node->name, namelen);
|
||||||
@ -2450,15 +2467,9 @@ static xmlNodePtr php_sxe_iterator_fetch(php_sxe_object *sxe, xmlNodePtr node, i
|
|||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
static xmlNodePtr php_sxe_reset_iterator(php_sxe_object *sxe, int use_data) /* {{{ */
|
static xmlNodePtr php_sxe_reset_iterator_no_clear_iter_data(php_sxe_object *sxe, int use_data)
|
||||||
{
|
{
|
||||||
xmlNodePtr node;
|
xmlNodePtr node;
|
||||||
|
|
||||||
if (!Z_ISUNDEF(sxe->iter.data)) {
|
|
||||||
zval_ptr_dtor(&sxe->iter.data);
|
|
||||||
ZVAL_UNDEF(&sxe->iter.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
GET_NODE(sxe, node)
|
GET_NODE(sxe, node)
|
||||||
|
|
||||||
if (node) {
|
if (node) {
|
||||||
@ -2471,10 +2482,23 @@ static xmlNodePtr php_sxe_reset_iterator(php_sxe_object *sxe, int use_data) /* {
|
|||||||
case SXE_ITER_ATTRLIST:
|
case SXE_ITER_ATTRLIST:
|
||||||
node = (xmlNodePtr) node->properties;
|
node = (xmlNodePtr) node->properties;
|
||||||
}
|
}
|
||||||
|
if (use_data) {
|
||||||
|
ZEND_ASSERT(Z_ISUNDEF(sxe->iter.data));
|
||||||
|
}
|
||||||
return php_sxe_iterator_fetch(sxe, node, use_data);
|
return php_sxe_iterator_fetch(sxe, node, use_data);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static xmlNodePtr php_sxe_reset_iterator(php_sxe_object *sxe, int use_data) /* {{{ */
|
||||||
|
{
|
||||||
|
if (!Z_ISUNDEF(sxe->iter.data)) {
|
||||||
|
zval_ptr_dtor(&sxe->iter.data);
|
||||||
|
ZVAL_UNDEF(&sxe->iter.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return php_sxe_reset_iterator_no_clear_iter_data(sxe, use_data);
|
||||||
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
zend_object_iterator *php_sxe_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */
|
zend_object_iterator *php_sxe_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */
|
||||||
|
37
ext/simplexml/tests/gh12192.phpt
Normal file
37
ext/simplexml/tests/gh12192.phpt
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
--TEST--
|
||||||
|
GH-12192 (SimpleXML infinite loop when getName() is called within foreach)
|
||||||
|
--EXTENSIONS--
|
||||||
|
simplexml
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$xml = "<root><a>1</a><a>2</a></root>";
|
||||||
|
$xml = simplexml_load_string($xml);
|
||||||
|
|
||||||
|
$a = $xml->a;
|
||||||
|
|
||||||
|
foreach ($a as $test) {
|
||||||
|
echo "Iteration\n";
|
||||||
|
var_dump($a->key());
|
||||||
|
var_dump($a->getName());
|
||||||
|
var_dump((string) $test);
|
||||||
|
}
|
||||||
|
|
||||||
|
var_dump($a);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
Iteration
|
||||||
|
string(1) "a"
|
||||||
|
string(1) "a"
|
||||||
|
string(1) "1"
|
||||||
|
Iteration
|
||||||
|
string(1) "a"
|
||||||
|
string(1) "a"
|
||||||
|
string(1) "2"
|
||||||
|
object(SimpleXMLElement)#2 (2) {
|
||||||
|
[0]=>
|
||||||
|
string(1) "1"
|
||||||
|
[1]=>
|
||||||
|
string(1) "2"
|
||||||
|
}
|
67
ext/simplexml/tests/gh12223.phpt
Normal file
67
ext/simplexml/tests/gh12223.phpt
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
--TEST--
|
||||||
|
GH-12223: Entity reference produces infinite loop in var_dump/print_r
|
||||||
|
--EXTENSIONS--
|
||||||
|
simplexml
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$xml = <<<XML
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE somedoc [
|
||||||
|
<!ENTITY a "something">
|
||||||
|
<!ENTITY b "&a;">
|
||||||
|
<!ENTITY c "&b;">
|
||||||
|
]>
|
||||||
|
<somedoc>&c;</somedoc>
|
||||||
|
XML;
|
||||||
|
|
||||||
|
$sxe = simplexml_load_string($xml);
|
||||||
|
|
||||||
|
var_dump($sxe);
|
||||||
|
print_r($sxe);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
object(SimpleXMLElement)#1 (1) {
|
||||||
|
["c"]=>
|
||||||
|
object(SimpleXMLElement)#2 (1) {
|
||||||
|
["c"]=>
|
||||||
|
object(SimpleXMLElement)#3 (1) {
|
||||||
|
["b"]=>
|
||||||
|
object(SimpleXMLElement)#4 (1) {
|
||||||
|
["b"]=>
|
||||||
|
object(SimpleXMLElement)#5 (1) {
|
||||||
|
["a"]=>
|
||||||
|
object(SimpleXMLElement)#6 (1) {
|
||||||
|
["a"]=>
|
||||||
|
string(9) "something"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SimpleXMLElement Object
|
||||||
|
(
|
||||||
|
[c] => SimpleXMLElement Object
|
||||||
|
(
|
||||||
|
[c] => SimpleXMLElement Object
|
||||||
|
(
|
||||||
|
[b] => SimpleXMLElement Object
|
||||||
|
(
|
||||||
|
[b] => SimpleXMLElement Object
|
||||||
|
(
|
||||||
|
[a] => SimpleXMLElement Object
|
||||||
|
(
|
||||||
|
[a] => something
|
||||||
|
)
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user