Skip to content

Commit 1655d57

Browse files
committed
Merge branch 'PHP-8.5'
* PHP-8.5: Fix phpGH-21496: UAF in dom_objects_free_storage.
2 parents d92c822 + 4b79bbb commit 1655d57

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

ext/xsl/tests/gh21496.phpt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
GH-21496 (UAF in dom_objects_free_storage when importing non-document node as stylesheet)
3+
--EXTENSIONS--
4+
dom
5+
xsl
6+
--CREDITS--
7+
YuanchengJiang
8+
--FILE--
9+
<?php
10+
$comment = new DOMComment("my value");
11+
$doc = new DOMDocument();
12+
$doc->loadXML(<<<XML
13+
<container/>
14+
XML);
15+
$doc->documentElement->appendChild($comment);
16+
unset($doc);
17+
$proc = new XSLTProcessor();
18+
var_dump($proc->importStylesheet($comment));
19+
$sxe = simplexml_load_string('<container/>');
20+
$proc = new XSLTProcessor();
21+
$proc->importStylesheet($sxe);
22+
?>
23+
--EXPECTF--
24+
Warning: XSLTProcessor::importStylesheet(): compilation error: file %s line 1 element container in %s on line %d
25+
26+
Warning: XSLTProcessor::importStylesheet(): xsltParseStylesheetProcess : document is not a stylesheet in %s on line %d
27+
bool(false)
28+
29+
Warning: XSLTProcessor::importStylesheet(): compilation error: element container in %s on line %d
30+
31+
Warning: XSLTProcessor::importStylesheet(): xsltParseStylesheetProcess : document is not a stylesheet in %s on line %d
32+

ext/xsl/xsltprocessor.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,18 +167,48 @@ PHP_METHOD(XSLTProcessor, importStylesheet)
167167
xsltStylesheetPtr sheetp;
168168
bool clone_docu = false;
169169
xmlNode *nodep = NULL;
170-
zval *cloneDocu, rv, clone_zv;
170+
zval *cloneDocu, rv, clone_zv, owner_zv;
171171
zend_string *member;
172172

173173
id = ZEND_THIS;
174174
if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &docp) == FAILURE) {
175175
RETURN_THROWS();
176176
}
177177

178+
nodep = php_libxml_import_node(docp);
179+
if (nodep == NULL) {
180+
zend_argument_type_error(1, "must be a valid XML node");
181+
RETURN_THROWS();
182+
}
183+
184+
if (Z_OBJ_HANDLER_P(docp, clone_obj) == NULL) {
185+
zend_argument_type_error(1, "must be a cloneable node");
186+
RETURN_THROWS();
187+
}
188+
189+
ZVAL_UNDEF(&owner_zv);
190+
191+
/* For non-document nodes, resolve the ownerDocument and clone that
192+
* instead as xsltParseStylesheetProcess may free nodes in the document. */
193+
if (nodep->type != XML_DOCUMENT_NODE && nodep->type != XML_HTML_DOCUMENT_NODE) {
194+
if (nodep->doc == NULL) {
195+
zend_argument_value_error(1, "must be part of a document");
196+
RETURN_THROWS();
197+
}
198+
199+
/* See dom_import_simplexml_common */
200+
201+
dom_object *nodeobj = (dom_object *) ((char *) Z_OBJ_P(docp) - Z_OBJ_HT_P(docp)->offset);
202+
203+
php_dom_create_object((xmlNodePtr) nodep->doc, &owner_zv, nodeobj);
204+
docp = &owner_zv;
205+
}
206+
178207
/* libxslt uses _private, so we must copy the imported
179208
* stylesheet document otherwise the node proxies will be a mess.
180209
* We will clone the object and detach the libxml internals later. */
181210
zend_object *clone = Z_OBJ_HANDLER_P(docp, clone_obj)(Z_OBJ_P(docp));
211+
zval_ptr_dtor(&owner_zv);
182212
if (!clone) {
183213
RETURN_THROWS();
184214
}

0 commit comments

Comments
 (0)