Skip to content

Prevent calling clear() on shared EmptyNodeList object. - #2620

Merged
jhy merged 3 commits into
jhy:masterfrom
jaragunde:element-empty-fix
Sep 24, 2026
Merged

jhy merged 3 commits into
jhy:masterfrom
jaragunde:element-empty-fix

Conversation

@jaragunde

@jaragunde jaragunde commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

The object EmptyNodeList is shared across instances of Element, as long as they don't have any children. The Element.empty() operation unconditionally calls clear() on that object, which modifies its internal state and becomes a source of ConcurrentModificationException.

The included test serves as a reproducer of this concurrent modification problem; manipulation of a Stream of the EmptyNodeList object on new Element instances is affected by calls to Element.empty() on different objects in another thread.

We came across this problem when running tests of a piece of software, which has a pipeline that produces HTML documents. These tests use the pipeline to produce documents, then parse the result and check it against a pre-created model file. When running this on CI with multiple tests running in parallel, we got ConcurrentModificationExceptions even when these documents were independent from each other, pointing to some shared state across jsoup objects.

Thank you in advance for considering this patch for review!

jaragunde and others added 3 commits September 23, 2026 09:12
The object EmptyNodeList is shared across instances of Element, as long
as they don't have any children. The Element.empty() operation
unconditionally calls clear() on that object, which modifies its
internal state and becomes a source of ConcurrentModificationException.

The included test serves as a reproducer of this concurrent modification
problem; manipulation of a Stream of the EmptyNodeList object on new
Element instances is affected by calls to Element.empty() on different
objects in another thread.
Prevents CMEs on the shared empty list, and unnecessarry mods.
@jhy

jhy commented Sep 24, 2026

Copy link
Copy Markdown
Owner

Thanks! Merged. I updated the fix a bit to check for any empty list not just the shared one (so we don't spuriously invalidate the list for element-allocated empty lists), and simplified the test coverage to more directly check the modcount.

@jhy
jhy merged commit a939fca into jhy:master Sep 24, 2026
12 checks passed
@jhy jhy added bug A confirmed bug, that we should fix fixed An {bug|improvement} that has been {fixed|implemented} labels Sep 24, 2026
@jhy jhy added this to the 1.24.1 milestone Sep 24, 2026
@jaragunde

Copy link
Copy Markdown
Contributor Author

Thanks for your review, I definitely learned something new! Best regards.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug A confirmed bug, that we should fix fixed An {bug|improvement} that has been {fixed|implemented}

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants