On Thu, 18 Jun 2026 08:21:05 GMT, Prasanta Sadhukhan <[email protected]> 
wrote:

> `DTD.getElement(String)` is not thread safe. If there are 2 parallel parser 
> threads which call with the same new name then in the Vector there can be 2 
> identical elements. These unsynchronized elementHash.get(name) calls can both 
> observe null before either thread creates and puts the `Element` which will 
> then have duplicates. The index from elements.size() can also be wrong under 
> races.
> 
> The block needs to be synchronized to prevent this
> 
> ---------
> - [x] I confirm that I make this contribution in accordance with the [OpenJDK 
> Interim AI Policy](https://openjdk.org/legal/ai).

Swing UI classes are generally not thread-safe, yes. But 
`javax.swing.text.html.parser.DTD` is not really a UI component; it is parser 
infrastructure with shared mutable caches/maps. If the JDK parser can be 
reached by parallel parsing code, then this is a real data-race bug: 
Hashtable/Vector being individually synchronized gives a misleading partial 
safety, while the compound operation is not atomic

Agreed, DTD as a whole is not thread-safe. This change is not intended to make 
the entire class thread-safe.

The reason `getElement(String)` is worth fixing separately is that it performs 
a compound "lookup or create" operation across two data structures: elementHash 
and elements. Without synchronization, two concurrent calls for the same new 
name can create duplicate Element objects and leave the DTD's internal element 
list inconsistent with the hash table.

`DTD.getElement(int) `is different: it indexes into elements and may lazily 
grow/fill the Vector depending on implementation, so it should be reviewed 
separately. `DTD.defineEntity` may also have its own races. Those are valid 
follow-up issues, but they do not make this specific race harmless.

But, agreed that fixing only getElement(String) might be incomplete if the 
intent is to make DTD's lazy lookup/definition paths internally consistent 
under concurrent parser access so I extend the patch so `getElement(int)`, 
`getElement(String)`, and `defineEntity ` all synchronize their compound access 
to the backing DTD tables/vectors and these methods now preserve their internal 
invariants under concurrent access.

-------------

PR Comment: https://git.openjdk.org/jdk/pull/31568#issuecomment-4785605337

Reply via email to