[php-src] PR #23199: Fix use-after-free when __clone() retains the stylesheet copy
| From: | iliaal | Date: | Mon, 10 Aug 2026 14:12:15 +0000 |
| Subject: | [php-src] PR #23199: Fix use-after-free when __clone() retains the stylesheet copy | ||
| Groups: | php.git-pulls | ||
| Request: | Send a blank email to git-pulls+get-37730@lists.php.net to get a copy of this message | ||
Pull Request: https://github.com/php/php-src/pull/23199
Author: iliaal
XSLTProcessor::importStylesheet() clones the stylesheet document through the
object's clone handler and hands the copy to libxslt, which frees it with the stylesheet. A
DOMDocument subclass __clone() runs while that copy is fully wired up and
can stash either the copy itself or a node proxy into it, leaving a dangling pointer once the
processor is destroyed. The clone must now be exclusively owned before libxslt takes it.
```php
class D extends DOMDocument {
public function __clone(): void { $GLOBALS['stash'] = $this; }
}
$d = new D;
$d->loadXML('<?xml version="1.0"?><xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:template
match="/"><out/></xsl:template></xsl:stylesheet>');
$p = new XSLTProcessor;
$p->importStylesheet($d);
$esc = $GLOBALS['stash'];
unset($GLOBALS['stash'], $p, $d);
```
That aborts with a double free on 8.4, 8.5 and master. Stashing
$this->documentElement instead gives a silent read of freed memory in
dom_objects_free_storage. 8.3 is unaffected because it copies at the libxml level and
never builds a PHP object for the copy.