Skip to content

Commit

Permalink
Merge branch 'PHP-8.0' into PHP-8.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Girgias committed Aug 19, 2022
2 parents 5d196d9 + ba029fc commit c36a1ea
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 2 deletions.
8 changes: 8 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 8.1.11

- Core:
. Fixed bug GH-9323 (Crash in ZEND_RETURN/GC/zend_call_function)
(Tim Starling)

- DOM:
. Fixed bug #79451 (Using DOMDocument->replaceChild on doctype causes
double free) (NathanFreeman)

- Streams:
. Fixed bug GH-9316 ($http_response_header is wrong for long status line).
(cmb, timwolla)
Expand Down
3 changes: 2 additions & 1 deletion Zend/zend_vm_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -4329,6 +4329,7 @@ ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER))
zend_refcounted *ref = Z_COUNTED_P(retval_ptr);
ZVAL_COPY_VALUE(return_value, retval_ptr);
if (GC_MAY_LEAK(ref)) {
SAVE_OPLINE();
gc_possible_root(ref);
}
ZVAL_NULL(retval_ptr);
Expand Down Expand Up @@ -8365,8 +8366,8 @@ ZEND_VM_C_LABEL(check_indirect):
zend_refcounted *garbage = Z_COUNTED_P(variable_ptr);

ZVAL_REF(variable_ptr, ref);
SAVE_OPLINE();
if (GC_DELREF(garbage) == 0) {
SAVE_OPLINE();
rc_dtor_func(garbage);
if (UNEXPECTED(EG(exception))) {
ZVAL_NULL(variable_ptr);
Expand Down
12 changes: 11 additions & 1 deletion Zend/zend_vm_execute.h
Original file line number Diff line number Diff line change
Expand Up @@ -4217,6 +4217,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_
zend_refcounted *ref = Z_COUNTED_P(retval_ptr);
ZVAL_COPY_VALUE(return_value, retval_ptr);
if (GC_MAY_LEAK(ref)) {
SAVE_OPLINE();
gc_possible_root(ref);
}
ZVAL_NULL(retval_ptr);
Expand Down Expand Up @@ -4294,6 +4295,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSER
zend_refcounted *ref = Z_COUNTED_P(retval_ptr);
ZVAL_COPY_VALUE(return_value, retval_ptr);
if (GC_MAY_LEAK(ref)) {
SAVE_OPLINE();
gc_possible_root(ref);
}
ZVAL_NULL(retval_ptr);
Expand Down Expand Up @@ -18796,6 +18798,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA
zend_refcounted *ref = Z_COUNTED_P(retval_ptr);
ZVAL_COPY_VALUE(return_value, retval_ptr);
if (GC_MAY_LEAK(ref)) {
SAVE_OPLINE();
gc_possible_root(ref);
}
ZVAL_NULL(retval_ptr);
Expand Down Expand Up @@ -21452,6 +21455,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA
zend_refcounted *ref = Z_COUNTED_P(retval_ptr);
ZVAL_COPY_VALUE(return_value, retval_ptr);
if (GC_MAY_LEAK(ref)) {
SAVE_OPLINE();
gc_possible_root(ref);
}
ZVAL_NULL(retval_ptr);
Expand Down Expand Up @@ -38320,6 +38324,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN
zend_refcounted *ref = Z_COUNTED_P(retval_ptr);
ZVAL_COPY_VALUE(return_value, retval_ptr);
if (GC_MAY_LEAK(ref)) {
SAVE_OPLINE();
gc_possible_root(ref);
}
ZVAL_NULL(retval_ptr);
Expand Down Expand Up @@ -43114,8 +43119,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_GLOBAL_SPEC_C
zend_refcounted *garbage = Z_COUNTED_P(variable_ptr);

ZVAL_REF(variable_ptr, ref);
SAVE_OPLINE();
if (GC_DELREF(garbage) == 0) {
SAVE_OPLINE();
rc_dtor_func(garbage);
if (UNEXPECTED(EG(exception))) {
ZVAL_NULL(variable_ptr);
Expand Down Expand Up @@ -56002,6 +56007,7 @@ ZEND_API void execute_ex(zend_execute_data *ex)
zend_refcounted *ref = Z_COUNTED_P(retval_ptr);
ZVAL_COPY_VALUE(return_value, retval_ptr);
if (GC_MAY_LEAK(ref)) {
SAVE_OPLINE();
gc_possible_root(ref);
}
ZVAL_NULL(retval_ptr);
Expand Down Expand Up @@ -56080,6 +56086,7 @@ ZEND_API void execute_ex(zend_execute_data *ex)
zend_refcounted *ref = Z_COUNTED_P(retval_ptr);
ZVAL_COPY_VALUE(return_value, retval_ptr);
if (GC_MAY_LEAK(ref)) {
SAVE_OPLINE();
gc_possible_root(ref);
}
ZVAL_NULL(retval_ptr);
Expand Down Expand Up @@ -57613,6 +57620,7 @@ ZEND_API void execute_ex(zend_execute_data *ex)
zend_refcounted *ref = Z_COUNTED_P(retval_ptr);
ZVAL_COPY_VALUE(return_value, retval_ptr);
if (GC_MAY_LEAK(ref)) {
SAVE_OPLINE();
gc_possible_root(ref);
}
ZVAL_NULL(retval_ptr);
Expand Down Expand Up @@ -57918,6 +57926,7 @@ ZEND_API void execute_ex(zend_execute_data *ex)
zend_refcounted *ref = Z_COUNTED_P(retval_ptr);
ZVAL_COPY_VALUE(return_value, retval_ptr);
if (GC_MAY_LEAK(ref)) {
SAVE_OPLINE();
gc_possible_root(ref);
}
ZVAL_NULL(retval_ptr);
Expand Down Expand Up @@ -59051,6 +59060,7 @@ ZEND_API void execute_ex(zend_execute_data *ex)
zend_refcounted *ref = Z_COUNTED_P(retval_ptr);
ZVAL_COPY_VALUE(return_value, retval_ptr);
if (GC_MAY_LEAK(ref)) {
SAVE_OPLINE();
gc_possible_root(ref);
}
ZVAL_NULL(retval_ptr);
Expand Down
46 changes: 46 additions & 0 deletions ext/dom/node.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#endif

#include "php.h"

#if defined(HAVE_LIBXML) && defined(HAVE_DOM)
#include "php_dom.h"

Expand Down Expand Up @@ -1003,6 +1004,7 @@ PHP_METHOD(DOMNode, replaceChild)
xmlNodePtr newchild, oldchild, nodep;
dom_object *intern, *newchildobj, *oldchildobj;
int stricterror;
bool replacedoctype = false;

int ret;

Expand Down Expand Up @@ -1042,7 +1044,51 @@ PHP_METHOD(DOMNode, replaceChild)
RETURN_FALSE;
}

<<<<<<< HEAD
if (oldchild->parent != nodep) {
=======
/* check for the old child and whether the new child is already a child */
while (children) {
if (children == oldchild) {
foundoldchild = 1;
break;
}
children = children->next;
}

if (foundoldchild) {
if (newchild->type == XML_DOCUMENT_FRAG_NODE) {
xmlNodePtr prevsib, nextsib;
prevsib = oldchild->prev;
nextsib = oldchild->next;

xmlUnlinkNode(oldchild);

newchild = _php_dom_insert_fragment(nodep, prevsib, nextsib, newchild, intern, newchildobj);
if (newchild) {
dom_reconcile_ns(nodep->doc, newchild);
}
} else if (oldchild != newchild) {
xmlDtdPtr intSubset = xmlGetIntSubset(nodep->doc);
replacedoctype = (intSubset == (xmlDtd *) oldchild);

if (newchild->doc == NULL && nodep->doc != NULL) {
xmlSetTreeDoc(newchild, nodep->doc);
newchildobj->document = intern->document;
php_libxml_increment_doc_ref((php_libxml_node_object *)newchildobj, NULL);
}

xmlReplaceNode(oldchild, newchild);
dom_reconcile_ns(nodep->doc, newchild);

if (replacedoctype) {
nodep->doc->intSubset = (xmlDtd *) newchild;
}
}
DOM_RET_OBJ(oldchild, &ret, intern);
return;
} else {
>>>>>>> PHP-8.0
php_dom_throw_error(NOT_FOUND_ERR, stricterror);
RETURN_FALSE;
}
Expand Down
20 changes: 20 additions & 0 deletions ext/dom/tests/bug79451.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
--TEST--
Bug #79451 (Using DOMDocument->replaceChild on doctype causes double free)
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--FILE--
<?php
$dom = new \DOMDocument();
$dom->loadHTML("<!DOCTYPE html><p>hello</p>");
$impl = new \DOMImplementation();
$dt = $impl->createDocumentType("html_replace", "", "");
$dom->replaceChild($dt, $dom->doctype);

var_dump($dom->doctype->name);
echo $dom->saveXML();
?>
--EXPECTF--
string(12) "html_replace"
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE html_replace>
<html><body><p>hello</p></body></html>

0 comments on commit c36a1ea

Please sign in to comment.