diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 4f84404919fa..5ef6bbddc3bf 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -47,8 +47,6 @@ static zend_module_entry **module_request_shutdown_handlers;
static zend_module_entry **module_post_deactivate_handlers;
static zend_module_entry **modules_dl_loaded;
-static zend_class_entry **class_cleanup_handlers;
-
ZEND_API void zend_set_dl_use_deepbind(bool use_deepbind)
{
zend_dl_use_deepbind = use_deepbind;
@@ -2561,8 +2559,6 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
int shutdown_count = 0;
int post_deactivate_count = 0;
int dl_loaded_count = 0;
- zend_class_entry *ce;
- int class_count = 0;
/* Collect extensions with request startup/shutdown handlers */
ZEND_HASH_MAP_FOREACH_PTR(&module_registry, module) {
@@ -2609,29 +2605,6 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
modules_dl_loaded[--dl_loaded_count] = module;
}
} ZEND_HASH_FOREACH_END();
-
- /* Collect internal classes with static members */
- ZEND_HASH_MAP_FOREACH_PTR(CG(class_table), ce) {
- if (ce->type == ZEND_INTERNAL_CLASS &&
- ce->default_static_members_count > 0) {
- class_count++;
- }
- } ZEND_HASH_FOREACH_END();
-
- class_cleanup_handlers = (zend_class_entry**)perealloc(
- class_cleanup_handlers,
- sizeof(zend_class_entry*) *
- (class_count + 1), true);
- class_cleanup_handlers[class_count] = NULL;
-
- if (class_count) {
- ZEND_HASH_MAP_FOREACH_PTR(CG(class_table), ce) {
- if (ce->type == ZEND_INTERNAL_CLASS &&
- ce->default_static_members_count > 0) {
- class_cleanup_handlers[--class_count] = ce;
- }
- } ZEND_HASH_FOREACH_END();
- }
}
/* }}} */
@@ -2644,8 +2617,6 @@ ZEND_API void zend_startup_modules(void) /* {{{ */
ZEND_API void zend_destroy_modules(void) /* {{{ */
{
- free(class_cleanup_handlers);
- class_cleanup_handlers = NULL;
free(module_request_startup_handlers);
module_request_startup_handlers = NULL;
zend_hash_graceful_reverse_destroy(&module_registry);
diff --git a/ext/dom/node.c b/ext/dom/node.c
index 362000792f1a..a3d40a92bfb7 100644
--- a/ext/dom/node.c
+++ b/ext/dom/node.c
@@ -951,6 +951,9 @@ static void dom_node_insert_before_legacy(zval *return_value, zval *ref, dom_obj
php_dom_throw_error(NOT_FOUND_ERR, stricterror);
RETURN_FALSE;
}
+ if (refp == child) {
+ refp = child->next;
+ }
}
if (child->doc == NULL && parentp->doc != NULL) {
@@ -960,7 +963,7 @@ static void dom_node_insert_before_legacy(zval *return_value, zval *ref, dom_obj
php_libxml_invalidate_node_list_cache(intern->document);
- if (ref != NULL) {
+ if (refp != NULL) {
if (child->parent != NULL) {
xmlUnlinkNode(child);
}
diff --git a/ext/dom/tests/gh23365.phpt b/ext/dom/tests/gh23365.phpt
new file mode 100644
index 000000000000..bc283b0659d3
--- /dev/null
+++ b/ext/dom/tests/gh23365.phpt
@@ -0,0 +1,53 @@
+--TEST--
+GH-23365 (DOMNode::insertBefore($n, $n) drops the node and leaves a self-referencing sibling list)
+--CREDITS--
+Alexandre Daubois
+--EXTENSIONS--
+dom
+--FILE--
+loadXML('text');
+$root = $doc->documentElement;
+
+$text = $root->firstChild;
+var_dump($root->insertBefore($text, $text) === $text);
+var_dump($root->childNodes->length);
+var_dump($text->parentNode === $root, $text->nextSibling === $text, $text->previousSibling === $text);
+
+$child = $root->lastChild;
+var_dump($root->insertBefore($child, $child) === $child);
+var_dump($root->childNodes->length);
+
+echo $doc->saveXML($root), PHP_EOL;
+
+$doc2 = new DOMDocument();
+$doc2->loadXML('');
+$el = $doc2->documentElement;
+$attr = $el->getAttributeNode('a');
+var_dump($el->insertBefore($attr, $attr) === $attr);
+echo $doc2->saveXML($el), PHP_EOL;
+
+$doc3 = new DOMDocument();
+$root3 = $doc3->appendChild($doc3->createElement('root'));
+$root3->appendChild($doc3->createTextNode('A'));
+$t = $root3->appendChild($doc3->createTextNode('B'));
+$root3->insertBefore($t, $t);
+$root3->appendChild($t);
+echo $doc3->saveXML($root3), PHP_EOL;
+unset($t, $root3, $doc3);
+echo "done", PHP_EOL;
+?>
+--EXPECT--
+bool(true)
+int(2)
+bool(true)
+bool(false)
+bool(false)
+bool(true)
+int(2)
+text
+bool(true)
+
+AB
+done