Description
Description
The following code:
<?php
$html = <<<'HTML'
<p>
<span>
<strong>
<span>
Test
</span>
</strong>
</span>
</p>
HTML;
$doc = new \DOMDocument('1.0', 'UTF-8');
$doc->loadHTML(
'<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body>' . $html . '</body></html>'
);
$xpath = new \DOMXPath($doc);
$spans = [];
foreach ($xpath->query('//span') as $span) {
$spans[] = $span;
}
\assert(\count($spans) === 2);
foreach ($spans as $span) {
\assert($span instanceof \DOMElement);
\assert($span->ownerDocument === $doc);
}
foreach ($spans as $span) {
\assert($span instanceof \DOMElement);
// This call will fail for the second `<span>`. It does not really
// matter what is accessed here, the error message will be the same.
$span->hasAttribute('test');
while ($span->childNodes->length) {
$span->removeChild($span->childNodes[0]);
}
$span->appendChild(
$span->ownerDocument->createTextNode('Hello World')
);
}
echo $span[0]->textContent . "\n"; // Hello World
Resulted in this output:
Fatal error: Uncaught Error: Couldn't fetch DOMElement in /opt/homebrew/var/www/test/dom-not-found.php:36 Stack trace: #0 /opt/homebrew/var/www/test/dom-not-found.php(36): DOMElement->hasAttribute('test') #1 {main} thrown in /opt/homebrew/var/www/test/dom-not-found.php on line 36
But I expected this output instead:
Hello World
The problem was also reproduced on https://3v4l.org/uSEC9 and yields the identical error message for PHP 7.4.0 - 8.2rc1 (EOL version have not been tested). Removing the intermediate <strong>
will cause the script to work, it appears that the implicit removal of the inner <span>
by removing its parent is the cause of the issue.
Even worse, it is impossible to detect this kind of problem without resorting to a try { … } catch (\Error $e) { … }
construct, because any access to the “defective” reference will yield the error. From my understanding of the documentations there is \DOMException
and the \DOM_*
error constants that should be yielded instead, so there is possibly a secondary bug hiding in this issue.
PHP Version
8.1.10
Operating System
macOS 12.6 (aarch64)