Skip to content

Commit 507fdf9

Browse files
committed
Prevent adding non-DOMElement elements in DomCrawler
Many methods of the DomCrawler component are relying on the DOMElement API, not only on the DOMNode API.
1 parent 99745e1 commit 507fdf9

File tree

2 files changed

+24
-7
lines changed

2 files changed

+24
-7
lines changed

src/Symfony/Component/DomCrawler/Crawler.php

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -308,10 +308,14 @@ public function addNodes(array $nodes)
308308
public function addNode(\DOMNode $node)
309309
{
310310
if ($node instanceof \DOMDocument) {
311-
parent::attach($node->documentElement);
312-
} else {
313-
parent::attach($node);
311+
$node = $node->documentElement;
312+
}
313+
314+
if (!$node instanceof \DOMElement) {
315+
throw new \InvalidArgumentException(sprintf('Nodes set in a Crawler must be DOMElement instances, "%s" given.', get_class($node)));
314316
}
317+
318+
parent::attach($node);
315319
}
316320

317321
// Serializing and unserializing a crawler creates DOM objects in a corrupted state. DOM elements are not properly serializable.
@@ -974,7 +978,12 @@ private function filterRelativeXPath($xpath)
974978

975979
foreach ($this as $node) {
976980
$domxpath = $this->createDOMXPath($node->ownerDocument, $prefixes);
977-
$crawler->add($domxpath->query($xpath, $node));
981+
982+
foreach ($domxpath->query($xpath, $node) as $subNode) {
983+
if ($subNode->nodeType === 1) {
984+
$crawler->add($subNode);
985+
}
986+
}
978987
}
979988

980989
return $crawler;

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ public function testConstructor()
2020
$crawler = new Crawler();
2121
$this->assertCount(0, $crawler, '__construct() returns an empty crawler');
2222

23-
$crawler = new Crawler(new \DOMNode());
23+
$doc = new \DOMDocument();
24+
$node = $doc->createElement('test');
25+
26+
$crawler = new Crawler($node);
2427
$this->assertCount(1, $crawler, '__construct() takes a node as a first argument');
2528
}
2629

@@ -37,6 +40,7 @@ public function testAdd()
3740
$crawler->add($this->createNodeList());
3841
$this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->add() adds nodes from a \DOMNodeList');
3942

43+
$list = array();
4044
foreach ($this->createNodeList() as $node) {
4145
$list[] = $node;
4246
}
@@ -267,6 +271,7 @@ public function testAddNodeList()
267271
*/
268272
public function testAddNodes()
269273
{
274+
$list = array();
270275
foreach ($this->createNodeList() as $node) {
271276
$list[] = $node;
272277
}
@@ -290,7 +295,10 @@ public function testAddNode()
290295

291296
public function testClear()
292297
{
293-
$crawler = new Crawler(new \DOMNode());
298+
$doc = new \DOMDocument();
299+
$node = $doc->createElement('test');
300+
301+
$crawler = new Crawler($node);
294302
$crawler->clear();
295303
$this->assertCount(0, $crawler, '->clear() removes all the nodes from the crawler');
296304
}
@@ -526,7 +534,7 @@ public function testFilterXPathWithAttributeAxis()
526534

527535
public function testFilterXPathWithAttributeAxisAfterElementAxis()
528536
{
529-
$this->assertCount(3, $this->createTestCrawler()->filterXPath('//form/button/attribute::*'), '->filterXPath() handles attribute axes properly when they are preceded by an element filtering axis');
537+
$this->assertCount(0, $this->createTestCrawler()->filterXPath('//form/button/attribute::*'), '->filterXPath() handles attribute axes properly when they are preceded by an element filtering axis');
530538
}
531539

532540
public function testFilterXPathWithChildAxis()

0 commit comments

Comments
 (0)