SONARJAVA-6870: Fix FP in S9342 when zip stream is wrapped in custom OutputStream - #6056
Conversation
…utputStream Add test example where ObjectMapper writes to a custom OutputStream wrapping a ZipOutputStream. Fix clearTrackedSymbolsUsedAsArguments to deeply scan non-identifier arguments for tracked symbol usage, preventing false positives when the zip stream is passed to a constructor nested inside a method call argument. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Unwrap casts and parenthesized expressions before checking if an argument is a tracked symbol, fixing FPs like `(OutputStream) zos`. Extract a shared removeUsedSymbols helper to eliminate duplicated visitor logic between scanForTrackedSymbolUsage and clearTrackedSymbolsUsedAsArguments. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| if (unwrapped.is(Tree.Kind.IDENTIFIER)) { | ||
| pendingEntries.remove(((IdentifierTree) unwrapped).symbol()); | ||
| } else { | ||
| removeUsedSymbols(unwrapped, pendingEntries); |
There was a problem hiding this comment.
While unwrapping casts and parentheses here covers direct arguments of the method invocation, TrackedSymbolVisitor (visitNewClass and visitMethodInvocation) still checks arg.is(Tree.Kind.IDENTIFIER) directly without unwrapping casts or parentheses.
Since TrackedSymbolVisitor.visitIdentifier is an intentional no-op, tracked symbols nested inside a constructor/method call argument behind a cast or parentheses (e.g., new CustomOutputStream((OutputStream) zos)) won't be detected during the AST traversal.
Extracting a shared helper (e.g. extractIdentifier(ExpressionTree)) to unwrap casts and parentheses and reusing it in both clearTrackedSymbolsUsedAsArguments and TrackedSymbolVisitor would ensure nested cases are handled consistently.
… in S9342 Ensure TrackedSymbolVisitor handles casts and parentheses consistently with clearTrackedSymbolsUsedAsArguments by extracting extractIdentifierSymbol. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…esized Reuse extractIdentifierSymbol in getReceiverSymbol so that expressions like ((OutputStream) zos).write(...) or (zos).write(...) correctly resolve the receiver symbol instead of returning null, which was leaving the stream in pendingEntries and causing a false positive on closeEntry(). Also remove redundant cast/parentheses unwrapping loop in clearTrackedSymbolsUsedAsArguments since BaseTreeVisitor traversal already handles nested expressions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Code Review ✅ Approved 3 resolved / 3 findingsFixes false positives in S9342 when ✅ 3 resolved✅ Edge Case: Deep argument scan misses symbols behind casts or parentheses
✅ Quality: Duplicated visitor/removal logic and per-argument visitor allocation
✅ Edge Case: Cast/parenthesized write receiver still yields FP in S9342
Implementation Status ◻️ 2 of 3 objectives covered◻️ SONARJAVA-6870 - 2 of 3 objectives coveredThis PR covers investigating the FP feedback, fixing false positives in S9342 when zip streams are wrapped in custom OutputStreams or use casts and parentheses, but does not add an example in rspec. Other objectives on this issue, possibly covered elsewhere:
✅ 2 covered here
OptionsAuto-apply is off → Gitar will not commit updates to this branch. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Gitar |
|




Summary
ObjectMapper.writeValuewrites to a customOutputStreamwrapping aZipOutputStreamclearTrackedSymbolsUsedAsArgumentsto deeply scan non-identifier arguments (e.g.,new CustomOutputStream(zos)) for tracked symbol usage, preventing false positives when the zip stream is nested inside a constructor call within a method argumentTest plan
EmptyArchiveEntryCheckTestpasses (both with and without semantic)🤖 Generated with Claude Code