Skip to content

Commit 9e60980

Browse files
committed
feature #16058 Prevent adding non-DOMElement elements in DomCrawler (stof)
This PR was merged into the 2.8 branch. Discussion ---------- Prevent adding non-DOMElement elements in DomCrawler | Q | A | ------------- | --- | Bug fix? | kind of | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | n/a | License | MIT | Doc PR | n/a Many methods of the DomCrawler component are relying on the DOMElement API, not only on the DOMNode API. All the typehints in the Form and Link APIs were already fixed in 2.5 because they are unusable with other kinds of nodes (fatal errors). However, the Crawler itself was not fixed. and this means that a bunch of its APIs can trigger fatal errors when passing other kinds of nodes. Thus, there is a case where the code was allowing such nodes to be injected in the Crawler for some XPath queries. I fixed it to avoid it, adding the same kind of filtering than in other places. Commits ------- 9f362a1 Prevent adding non-DOMElement elements in DomCrawler
2 parents 4af8a55 + 9f362a1 commit 9e60980

File tree

2 files changed

+26
-6
lines changed

2 files changed

+26
-6
lines changed

src/Symfony/Component/DomCrawler/Crawler.php

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -322,10 +322,14 @@ public function addNode(\DOMNode $node)
322322
}
323323

324324
if ($node instanceof \DOMDocument) {
325-
parent::attach($node->documentElement);
326-
} else {
327-
parent::attach($node);
325+
$node = $node->documentElement;
326+
}
327+
328+
if (!$node instanceof \DOMElement) {
329+
throw new \InvalidArgumentException(sprintf('Nodes set in a Crawler must be DOMElement or DOMDocument instances, "%s" given.', get_class($node)));
328330
}
331+
332+
parent::attach($node);
329333
}
330334

331335
// Serializing and unserializing a crawler creates DOM objects in a corrupted state. DOM elements are not properly serializable.
@@ -988,7 +992,12 @@ private function filterRelativeXPath($xpath)
988992

989993
foreach ($this as $node) {
990994
$domxpath = $this->createDOMXPath($node->ownerDocument, $prefixes);
991-
$crawler->add($domxpath->query($xpath, $node));
995+
996+
foreach ($domxpath->query($xpath, $node) as $subNode) {
997+
if ($subNode->nodeType === 1) {
998+
$crawler->add($subNode);
999+
}
1000+
}
9921001
}
9931002

9941003
return $crawler;

src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public function testAdd()
4040
$crawler->add($this->createNodeList());
4141
$this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->add() adds nodes from a \DOMNodeList');
4242

43+
$list = array();
4344
foreach ($this->createNodeList() as $node) {
4445
$list[] = $node;
4546
}
@@ -59,12 +60,22 @@ public function testAdd()
5960
/**
6061
* @expectedException \InvalidArgumentException
6162
*/
62-
public function testAddInvalidNode()
63+
public function testAddInvalidType()
6364
{
6465
$crawler = new Crawler();
6566
$crawler->add(1);
6667
}
6768

69+
/**
70+
* @expectedException \InvalidArgumentException
71+
* @expectedExceptionMessage Nodes set in a Crawler must be DOMElement or DOMDocument instances, "DOMNode" given.
72+
*/
73+
public function testAddInvalidNode()
74+
{
75+
$crawler = new Crawler();
76+
$crawler->add(new \DOMNode());
77+
}
78+
6879
/**
6980
* @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent
7081
*/
@@ -541,7 +552,7 @@ public function testFilterXPathWithAttributeAxis()
541552

542553
public function testFilterXPathWithAttributeAxisAfterElementAxis()
543554
{
544-
$this->assertCount(3, $this->createTestCrawler()->filterXPath('//form/button/attribute::*'), '->filterXPath() handles attribute axes properly when they are preceded by an element filtering axis');
555+
$this->assertCount(0, $this->createTestCrawler()->filterXPath('//form/button/attribute::*'), '->filterXPath() handles attribute axes properly when they are preceded by an element filtering axis');
545556
}
546557

547558
public function testFilterXPathWithChildAxis()

0 commit comments

Comments
 (0)