[
https://issues.apache.org/jira/browse/WW-5826?focusedWorklogId=1051602&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1051602
]
ASF GitHub Bot logged work on WW-5826:
--------------------------------------
Author: ASF GitHub Bot
Created on: 31/Oct/26 10:20
Start Date: 31/Oct/26 10:20
Worklog Time Spent: 10m
Work Description: g0w6y opened a new pull request, #2082:
URL: https://github.com/apache/struts/pull/2082
Fixes [WW-5826](https://issues.apache.org/jira/browse/WW-5826)
Hardening, no behaviour change. `ScopeInterceptor.locks` is a static
`IdentityHashMap` shared by all requests. `lock()`/`unlock()` mutate it inside
`synchronized (o)`, but `o` is the session map, which `Dispatcher` creates per
request, so concurrent requests never share that monitor and the map is
modified unsynchronized. It is now `Collections.synchronizedMap(...)`, which
also matches the `synchronized (locks)` already used by `clearLocks()`.
`ScopeInterceptorTest#testConcurrentLockAndUnlockLeavesNoEntries` runs 8
threads x 40,000 lock/unlock pairs on distinct objects and asserts the map is
empty afterwards. Without the change it failed in every run I made (25 runs);
the observed size varies per run, both positive and negative (for example 229,
230, 288, 563, -473, -547), i.e. the map's size counter is corrupted. With the
change it passed 20/20.
The test is statistical: it can pass without the fix on a fast machine, but
it never fails with the fix.
Not changed: what `ScopeInterceptor` locks on. Not claiming a security issue
or any cross-request data exposure; only the corrupted map size was measured.
The same kind of change for the XSLT plugin's `BeanAdapter` cache is a separate
PR.
Issue Time Tracking
-------------------
Worklog Id: (was: 1051602)
Remaining Estimate: 0h
Time Spent: 10m
> Make ScopeInterceptor lock table thread-safe
> --------------------------------------------
>
> Key: WW-5826
> URL: https://issues.apache.org/jira/browse/WW-5826
> Project: Struts 2
> Issue Type: Improvement
> Components: Core
> Affects Versions: 7.0.0, 7.3.0, 7.4.0
> Reporter: Gouri Sankar A
> Priority: Minor
> Time Spent: 10m
> Remaining Estimate: 0h
>
> ScopeInterceptor keeps a static IdentityHashMap named locks. lock() and
> unlock() modify it inside synchronized (o), where o is the session map.
> Dispatcher creates a new SessionMap per request, so concurrent requests do
> not share that monitor and the map is modified without mutual exclusion.
> Under concurrent use the map's size counter was observed to be corrupted
> (positive and negative values). This is hardening; no security impact was
> demonstrated. The interceptor is opt-in (scope and scopedModelDriven stacks,
> not defaultStack).
> Affected versions: the same code (a static IdentityHashMap locks guarded by
> synchronized (o)) is present in the 7.0.0, 7.3.0 and 7.4.0 tags, by source
> inspection. The race itself was only reproduced on main. The 6.12.0 tag
> differs (lock() synchronizes on locks), so 6.x is not claimed.
> Fix: wrap the map with Collections.synchronizedMap, consistent with the
> synchronized (locks) in clearLocks().
> Tests: ScopeInterceptorTest#testConcurrentLockAndUnlockLeavesNoEntries. It
> failed in every run without the fix (25 runs) and passed 20/20 with it. It is
> statistical: it can pass without the fix on a fast machine.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)