diff --git a/UPGRADING b/UPGRADING index b7b160820bb2a..e55b9730f71a4 100644 --- a/UPGRADING +++ b/UPGRADING @@ -246,6 +246,7 @@ PHP 8.6 UPGRADE NOTES creation of intermediate Closures, the overhead of calling userland callbacks from internal functions and providing for better insight for the JIT. + . The performance of the TAILCALL VM has been improved. - DOM: . Made splitText() faster and consume less memory. diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index cbfae90802cfa..7dfedca98d3b9 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -53457,6 +53457,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_NULL_HANDLER( # undef ZEND_VM_RETURN # undef ZEND_VM_DISPATCH_TO_HELPER # undef ZEND_VM_INTERRUPT +# undef ZEND_VM_ENTER_EX +# undef ZEND_VM_LEAVE # define ZEND_VM_TAIL_CALL(call) ZEND_MUSTTAIL return call # define ZEND_VM_CONTINUE() ZEND_VM_TAIL_CALL(opline->handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)) @@ -53468,6 +53470,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_NULL_HANDLER( } while (0) # define ZEND_VM_DISPATCH_TO_LEAVE_HELPER(helper) opline = &call_leave_op; SAVE_OPLINE(); ZEND_VM_CONTINUE() # define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)) +# define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE() +# define ZEND_VM_LEAVE() ZEND_VM_CONTINUE() static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_interrupt_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS); static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS); diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index f8989b2336f47..ed0256832d589 100755 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -2126,6 +2126,8 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"# undef ZEND_VM_RETURN\n"); out($f,"# undef ZEND_VM_DISPATCH_TO_HELPER\n"); out($f,"# undef ZEND_VM_INTERRUPT\n"); + out($f,"# undef ZEND_VM_ENTER_EX\n"); + out($f,"# undef ZEND_VM_LEAVE\n"); out($f,"\n"); out($f,"# define ZEND_VM_TAIL_CALL(call) ZEND_MUSTTAIL return call\n"); out($f,"# define ZEND_VM_CONTINUE() ZEND_VM_TAIL_CALL(opline->handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))\n"); @@ -2137,6 +2139,8 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f," } while (0)\n"); out($f,"# define ZEND_VM_DISPATCH_TO_LEAVE_HELPER(helper) opline = &call_leave_op; SAVE_OPLINE(); ZEND_VM_CONTINUE()\n"); out($f,"# define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper".($spec?"_SPEC":"")."_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))\n"); + out($f,"# define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n"); + out($f,"# define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); out($f,"\n"); out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_interrupt_helper".($spec?"_SPEC":"")."_TAILCALL(ZEND_OPCODE_HANDLER_ARGS);\n"); out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS);\n"); diff --git a/ext/dba/libinifile/inifile.c b/ext/dba/libinifile/inifile.c index c5467396d4bfe..6221c7f7a6e71 100644 --- a/ext/dba/libinifile/inifile.c +++ b/ext/dba/libinifile/inifile.c @@ -249,7 +249,7 @@ val_type inifile_fetch(inifile *dba, const key_type *key, int skip) { ln.key.group = estrdup(dba->next.key.group); } else { /* specific instance or not same key -> restart search */ - /* the slow way: restart and seacrch */ + /* the slow way: restart and search */ php_stream_rewind(dba->fp); inifile_line_free(&dba->next); } @@ -471,7 +471,7 @@ static int inifile_delete_replace_append(inifile *dba, const key_type *key, cons * 8) Append temporary stream */ - assert(!append || (key->name && value)); /* missuse */ + assert(!append || (key->name && value)); /* misuse */ /* 1 - 3 */ inifile_find_group(dba, key, &pos_grp_start); diff --git a/ext/xsl/tests/gh21496.phpt b/ext/xsl/tests/gh21496.phpt new file mode 100644 index 0000000000000..7a5cea37937d0 --- /dev/null +++ b/ext/xsl/tests/gh21496.phpt @@ -0,0 +1,32 @@ +--TEST-- +GH-21496 (UAF in dom_objects_free_storage when importing non-document node as stylesheet) +--EXTENSIONS-- +dom +xsl +--CREDITS-- +YuanchengJiang +--FILE-- +loadXML(<< +XML); +$doc->documentElement->appendChild($comment); +unset($doc); +$proc = new XSLTProcessor(); +var_dump($proc->importStylesheet($comment)); +$sxe = simplexml_load_string(''); +$proc = new XSLTProcessor(); +$proc->importStylesheet($sxe); +?> +--EXPECTF-- +Warning: XSLTProcessor::importStylesheet(): compilation error: file %s line 1 element container in %s on line %d + +Warning: XSLTProcessor::importStylesheet(): xsltParseStylesheetProcess : document is not a stylesheet in %s on line %d +bool(false) + +Warning: XSLTProcessor::importStylesheet(): compilation error: element container in %s on line %d + +Warning: XSLTProcessor::importStylesheet(): xsltParseStylesheetProcess : document is not a stylesheet in %s on line %d + diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c index 823c56f1cfb57..d06d008176172 100644 --- a/ext/xsl/xsltprocessor.c +++ b/ext/xsl/xsltprocessor.c @@ -167,7 +167,7 @@ PHP_METHOD(XSLTProcessor, importStylesheet) xsltStylesheetPtr sheetp; bool clone_docu = false; xmlNode *nodep = NULL; - zval *cloneDocu, rv, clone_zv; + zval *cloneDocu, rv, clone_zv, owner_zv; zend_string *member; id = ZEND_THIS; @@ -175,10 +175,40 @@ PHP_METHOD(XSLTProcessor, importStylesheet) RETURN_THROWS(); } + nodep = php_libxml_import_node(docp); + if (nodep == NULL) { + zend_argument_type_error(1, "must be a valid XML node"); + RETURN_THROWS(); + } + + if (Z_OBJ_HANDLER_P(docp, clone_obj) == NULL) { + zend_argument_type_error(1, "must be a cloneable node"); + RETURN_THROWS(); + } + + ZVAL_UNDEF(&owner_zv); + + /* For non-document nodes, resolve the ownerDocument and clone that + * instead as xsltParseStylesheetProcess may free nodes in the document. */ + if (nodep->type != XML_DOCUMENT_NODE && nodep->type != XML_HTML_DOCUMENT_NODE) { + if (nodep->doc == NULL) { + zend_argument_value_error(1, "must be part of a document"); + RETURN_THROWS(); + } + + /* See dom_import_simplexml_common */ + + dom_object *nodeobj = (dom_object *) ((char *) Z_OBJ_P(docp) - Z_OBJ_HT_P(docp)->offset); + + php_dom_create_object((xmlNodePtr) nodep->doc, &owner_zv, nodeobj); + docp = &owner_zv; + } + /* libxslt uses _private, so we must copy the imported * stylesheet document otherwise the node proxies will be a mess. * We will clone the object and detach the libxml internals later. */ zend_object *clone = Z_OBJ_HANDLER_P(docp, clone_obj)(Z_OBJ_P(docp)); + zval_ptr_dtor(&owner_zv); if (!clone) { RETURN_THROWS(); }