Skip to content

Stop shadowing Task._stop and Task._lastException (CodeQL java/field-masks-super-field)#238

Open
vharseko wants to merge 3 commits into
OpenIdentityPlatform:masterfrom
vharseko:features/codeql-field-masks-super
Open

Stop shadowing Task._stop and Task._lastException (CodeQL java/field-masks-super-field)#238
vharseko wants to merge 3 commits into
OpenIdentityPlatform:masterfrom
vharseko:features/codeql-field-masks-super

Conversation

@vharseko

@vharseko vharseko commented Jul 8, 2026

Copy link
Copy Markdown
Member

Summary

Addresses the java/field-masks-super-field alerts in StreamLoader and
StreamSaver. Both classes extend Task and redeclared _stop and
_lastException, which Task already declares, so the subclasses shadowed the
base fields instead of sharing them — a real defect, not just style.

File Field Superclass field Effect of the shadow
StreamSaver.java _stop (boolean) Task._stop (AtomicBoolean) save loops never saw a cancellation request
StreamSaver.java _lastException Task._lastException recorded failure never reached the task status
StreamLoader.java _stop, _lastException Task._stop, Task._lastException dead shadow fields, never read or written

Details

  • StreamSaver._stopTask._stop is an AtomicBoolean that Task.stop()
    flips to request cancellation. StreamSaver's own boolean _stop was never
    assigned, so saveAll, saveTrees and the traversal loop kept running even
    after a stop was requested. The shadow is removed and the loops now test the
    inherited _stop.get().
  • StreamSaver._lastExceptionTask reports _lastException in the task
    status; StreamSaver wrote its own copy, so the status stayed none. Removing
    the shadow lets the recorded exception surface.
  • StreamLoader — its _stop / _lastException were never read or written,
    so they are just removed.

For a normal (non-cancelled) run _stop is false throughout, so the loops
behave exactly as before; the change only lets a cancellation take effect and the
recorded exception appear in the task status.

Not changed here

The two remaining alerts on InstallExternalDependencyMojo.installer and
AbstractExternalDependencyMojo.artifactFactory are intentional: these are
Maven 2 @component fields re-declared in the plugin's own source so the
QDox-based plugin-descriptor generator emits the Plexus injection requirement
(the base classes live in compiled Maven artifacts whose @component tags the
generator cannot see). Removing them would drop the injection and NPE at runtime,
so they are left as-is.

Testing

mvn -o -pl persistit/core compile — BUILD SUCCESS.

…masks-super-field)

StreamLoader and StreamSaver each redeclared _stop and _lastException, which are
already declared in their superclass Task. The shadowing meant the two classes
did not share the base fields, breaking the Task framework's contract:

  - Task._stop is an AtomicBoolean that Task.stop() sets to request cancellation,
    but StreamSaver declared its own boolean _stop that nothing ever set, so its
    save loops (saveAll / saveTrees / the traversal loop) never observed a stop
    request and could not be cancelled. Remove the shadow field and test the
    inherited AtomicBoolean via _stop.get().
  - Task._lastException is the field Task reports through the task status, but
    StreamSaver recorded failures into its own shadow copy, so the reported
    status stayed "none". Remove the shadow so the recorded exception reaches the
    status.
  - StreamLoader's _stop and _lastException were shadow fields that were never
    read or written, so they are simply removed.

For a normal (non-cancelled) run _stop is false throughout, so the save loops
behave exactly as before; the change only lets a cancellation actually take
effect and lets the recorded exception surface in the task status.
@vharseko vharseko requested a review from maximthomas July 8, 2026 14:06
@vharseko vharseko added bug codeql CodeQL static-analysis findings labels Jul 8, 2026
Comment thread persistit/core/src/main/java/com/persistit/StreamSaver.java Fixed
Comment thread persistit/core/src/main/java/com/persistit/StreamSaver.java Fixed
…short-circuit-evaluation)

The save loops combined the traversal/index test with the stop flag using the
non-short-circuit & operator. The right operand (!_stop.get()) has no side
effects and the left operand is always evaluated first, so switching to &&
is behaviour-preserving and avoids the redundant _stop.get() once the loop
condition's left side is already false.
@vharseko vharseko force-pushed the features/codeql-field-masks-super branch from 180b72e to 85fbaba Compare July 10, 2026 18:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug codeql CodeQL static-analysis findings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants