From: <asa...@us...> - 2012-11-24 07:20:29
|
Revision: 7760 http://sourceforge.net/p/htmlunit/code/7760 Author: asashour Date: 2012-11-24 07:20:25 +0000 (Sat, 24 Nov 2012) Log Message: ----------- JavaScript: prevent infinite loop during adding a DomNode to a descendant. Issue 1253 Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/DomNode.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/DomNodeTest.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/DomNode.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/DomNode.java 2012-11-23 19:31:58 UTC (rev 7759) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/DomNode.java 2012-11-24 07:20:25 UTC (rev 7760) @@ -884,6 +884,9 @@ return this; } final DomNode domNode = (DomNode) node; + if (domNode.isDescendant(this)) { + Context.throwAsScriptRuntimeEx(new Exception("Can not add (grand)parent to itself " + this)); + } if (domNode instanceof DomDocumentFragment) { final DomDocumentFragment fragment = (DomDocumentFragment) domNode; @@ -1623,4 +1626,19 @@ protected boolean hasFeature(final BrowserVersionFeatures feature) { return getPage().getWebClient().getBrowserVersion().hasFeature(feature); } + + /** + * Checks whether the specified node is descendant of this node or not. + * @param node the node to check if it is descendant or not + * @return whether the specified node is descendant of this node or not + */ + protected boolean isDescendant(final DomNode node) { + for (DomNode parent = node; parent != null; parent = parent.getParentNode()) { + if (parent == this) { + return true; + } + } + return false; + } + } Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java 2012-11-23 19:31:58 UTC (rev 7759) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlPage.java 2012-11-24 07:20:25 UTC (rev 7760) @@ -1760,18 +1760,6 @@ } } - /** - * Checks whether the specified element is descendant of this HtmlPage or not. - */ - private boolean isDescendant(final DomElement element) { - for (DomNode parent = element; parent != null; parent = parent.getParentNode()) { - if (parent == this) { - return true; - } - } - return false; - } - private void addElement(final Map<String, List<DomElement>> map, final DomElement element, final String attribute, final boolean recurse) { final String value = element.getAttribute(attribute); Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/DomNodeTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/DomNodeTest.java 2012-11-23 19:31:58 UTC (rev 7759) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/DomNodeTest.java 2012-11-24 07:20:25 UTC (rev 7760) @@ -788,4 +788,31 @@ loadPageWithAlerts(html); } + /** + * Test for Bug #1253. + * + * @throws Exception on test failure + */ + @Test + @Alerts({ "true", "exception", "1", "0" }) + public void appendChild_recursive_parent() throws Exception { + final String html = "<html><head><title>foo</title>\n" + + "<script>\n" + + "function test(){\n" + + " var e1 = document.createElement('div');\n" + + " var e2 = document.createElement('div');\n" + + " try {\n" + + " alert(e1.appendChild(e2) === e2);\n" + + " alert(e2.appendChild(e1) === e1);\n" + + " } catch(e) {alert('exception');}\n" + + " alert(e1.childNodes.length);" + + " alert(e2.childNodes.length);" + + "}\n" + + "</script>\n" + + "</head><body onload='test()'>\n" + + "</body></html>"; + + loadPageWithAlerts(html); + } + } |