diff --git a/CHANGES b/CHANGES index 4e3849af7b..ee2ecc6bf9 100644 --- a/CHANGES +++ b/CHANGES @@ -47,6 +47,10 @@ Release 1.15.4 [PENDING] * Bugfix: fixed an issue in Safelist.removeAttributes which could throw a ConcurrentModificationException when using the ":all" pseudo-attribute. + * Bugfix: given extremely deeply nested HTML, a number of methods in Element could throw a StackOverflowError due + to excessive recursion. Namely: #data(), #hasText(), #parents(), and #wrap(html). + + * Change: deprecated the unused Document#normalise() method. Normalization occurs during the HTML tree construction, and no longer as a distinct phase. diff --git a/src/test/java/org/jsoup/nodes/ElementIT.java b/src/test/java/org/jsoup/nodes/ElementIT.java index 3f5e0e7e5e..ff57cef3b4 100644 --- a/src/test/java/org/jsoup/nodes/ElementIT.java +++ b/src/test/java/org/jsoup/nodes/ElementIT.java @@ -119,4 +119,19 @@ public void testFastReparentExistingContent() { assertEquals(num+2, parents.size()); // +2 for html and body assertEquals(doc, el.ownerDocument()); } + + @Test void wrapNoOverflow() { + // deepChild was recursive, so could overflow if presented with a fairly insane wrap + Document doc = new Document("https://example.com/"); + Element el = doc.body().appendElement("p"); + int num = 50000; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i <= num; i++) { + sb.append("
"); + } + el.wrap(sb.toString()); + String html = doc.body().html(); + assertTrue(html.startsWith("
")); + assertEquals(num + 3, el.parents().size()); + } }