Skip to content

Fix potential NPEs in IpcClient and resource leak in DependencyGraphParser - #1945

Merged
gnodet merged 2 commits into
masterfrom
fix/defensive-null-checks-and-resource-leak
Jul 7, 2026
Merged

Fix potential NPEs in IpcClient and resource leak in DependencyGraphParser#1945
gnodet merged 2 commits into
masterfrom
fix/defensive-null-checks-and-resource-leak

Conversation

@gnodet

@gnodet gnodet commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • IpcClient.getJarPath(): getClassLoader() returns null for bootstrap classes, and getResource() returns null when the resource is not found. Either causes an NPE on the chained .toString() call. Added explicit null checks with fallback to system classloader and a clear error message.
  • IpcClient.receive(): The volatile input field is read and used without a local copy. A concurrent close() call can null the field between the read and the method invocation, causing an NPE. Fixed by capturing the volatile read in a local variable.
  • IpcClient.getAddress(): The volatile socket field can be nulled by a concurrent close() call. The resulting NPE is not an IOException and propagates uncaught. Fixed by capturing in a local variable with a null check.
  • DependencyGraphParser.parseMultiResource(): The BufferedReader (and its underlying InputStream) is never closed. If parse(reader) throws, the stream leaks. Wrapped in try-with-resources, consistent with the existing parse(URL) method at line 174.

Test plan

  • mvn compile passes for both modified modules
  • mvn test passes for maven-resolver-named-locks-ipc
  • mvn test passes for maven-resolver-test-util
  • CI passes

🤖 Generated with Claude Code

…arser

- IpcClient.getJarPath(): handle null ClassLoader (bootstrap classes)
  and null resource lookup with explicit null checks
- IpcClient.receive(): capture volatile `input` field in local variable
  before use to prevent NPE from concurrent close()
- IpcClient.getAddress(): capture volatile `socket` field in local
  variable and add null check to prevent NPE during concurrent close()
- DependencyGraphParser.parseMultiResource(): wrap BufferedReader in
  try-with-resources to prevent stream leak on exception

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gnodet
gnodet requested a review from cstamas June 30, 2026 23:19
@gnodet
gnodet marked this pull request as ready for review June 30, 2026 23:20
@gnodet
gnodet requested a review from Copilot July 7, 2026 09:04

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot couldn't run its full agentic review because no GitHub Actions runner was available. Make sure your repository has a runner available to run Copilot's review, or add a copilot-setup-steps.yml file specifying one with the runs-on attribute. See the docs for more details.

This PR hardens IPC client code against null races and missing resources, and fixes a resource leak in the dependency graph parser.

Changes:

  • Add try-with-resources in DependencyGraphParser.parseMultiResource() to ensure streams are closed.
  • Prevent NPEs in IpcClient by adding null-safe resource lookup in getJarPath() and local copies of volatile fields in receive() / getAddress().

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java Ensures readers/streams are closed reliably during multi-resource parsing.
maven-resolver-named-locks-ipc/src/main/java/org/eclipse/aether/named/ipc/IpcClient.java Adds null handling for classpath resource lookup and avoids racy volatile field access.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +266 to +273
ClassLoader classLoader = clazz.getClassLoader();
if (classLoader == null) {
classLoader = ClassLoader.getSystemClassLoader();
}
URL resource = classLoader.getResource(className);
if (resource == null) {
throw new IllegalStateException("Unable to find resource for class " + clazz.getName());
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Switched to clazz.getResource("/" + className) which handles bootstrap-loaded classes natively — Class.getResource() internally delegates to ClassLoader.getSystemResource() when the classloader is null, so no explicit fallback is needed. Fixed in c2464e0.

Comment on lines +271 to +273
if (resource == null) {
throw new IllegalStateException("Unable to find resource for class " + clazz.getName());
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IllegalStateException is consistent with the two existing throws in the same method (lines 280 and 285) for other unrecoverable URL format conditions. The caller at line 176 is inside a catch (Exception e) { throw new RuntimeException("Unable to create and connect to lock server", e) } block (line 257), so the exception is always caught and wrapped with context — nothing is bypassed.

Address Copilot review: replace explicit ClassLoader fallback with
Class.getResource() which natively handles bootstrap-loaded classes
by delegating to ClassLoader.getSystemResource() internally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gnodet gnodet self-assigned this Jul 7, 2026
@gnodet gnodet added bug Something isn't working maintenance labels Jul 7, 2026
@gnodet gnodet added this to the 2.0.21 milestone Jul 7, 2026
@gnodet
gnodet merged commit 16bbda7 into master Jul 7, 2026
17 checks passed
@gnodet
gnodet deleted the fix/defensive-null-checks-and-resource-leak branch July 7, 2026 14:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working maintenance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants