This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch fix/defensive-null-checks-and-resource-leak in repository https://gitbox.apache.org/repos/asf/maven-resolver.git
commit fe19c43c99ad8b033d0299716fec87817a083bcd Author: Guillaume Nodet <[email protected]> AuthorDate: Tue Jun 30 22:48:45 2026 +0000 Fix potential NPEs in IpcClient and resource leak in DependencyGraphParser - 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 <[email protected]> --- .../org/eclipse/aether/named/ipc/IpcClient.java | 27 ++++++++++++++++++---- .../internal/test/util/DependencyGraphParser.java | 15 ++++++------ 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/maven-resolver-named-locks-ipc/src/main/java/org/eclipse/aether/named/ipc/IpcClient.java b/maven-resolver-named-locks-ipc/src/main/java/org/eclipse/aether/named/ipc/IpcClient.java index 852bdcc66..751d872d1 100644 --- a/maven-resolver-named-locks-ipc/src/main/java/org/eclipse/aether/named/ipc/IpcClient.java +++ b/maven-resolver-named-locks-ipc/src/main/java/org/eclipse/aether/named/ipc/IpcClient.java @@ -29,6 +29,7 @@ import java.io.InterruptedIOException; import java.io.PrintWriter; import java.io.RandomAccessFile; import java.net.SocketAddress; +import java.net.URL; import java.nio.channels.ByteChannel; import java.nio.channels.Channels; import java.nio.channels.FileLock; @@ -262,7 +263,15 @@ public class IpcClient { private String getJarPath(Class<?> clazz) { String classpath; String className = clazz.getName().replace('.', '/') + ".class"; - String url = clazz.getClassLoader().getResource(className).toString(); + 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()); + } + String url = resource.toString(); if (url.startsWith("jar:")) { url = url.substring("jar:".length(), url.indexOf("!/")); if (url.startsWith("file:")) { @@ -288,11 +297,15 @@ public class IpcClient { void receive() { try { while (true) { - int id = input.readInt(); - int sz = input.readInt(); + DataInputStream in = input; + if (in == null) { + throw new IOException("Connection closed"); + } + int id = in.readInt(); + int sz = in.readInt(); List<String> s = new ArrayList<>(sz); for (int i = 0; i < sz; i++) { - s.add(input.readUTF()); + s.add(in.readUTF()); } CompletableFuture<List<String>> f = responses.remove(id); if (f == null) { @@ -445,8 +458,12 @@ public class IpcClient { } private String getAddress() { + SocketChannel s = socket; + if (s == null) { + return "[closed]"; + } try { - return SocketFamily.toString(socket.getLocalAddress()); + return SocketFamily.toString(s.getLocalAddress()); } catch (IOException e) { return "[not bound]"; } diff --git a/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java b/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java index 18da45bb7..b4c060fb2 100644 --- a/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java +++ b/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java @@ -158,14 +158,15 @@ public class DependencyGraphParser { throw new IOException("Could not find classpath resource " + prefix + resource); } - BufferedReader reader = new BufferedReader(new InputStreamReader(res.openStream(), StandardCharsets.UTF_8)); - - List<DependencyNode> ret = new ArrayList<>(); - DependencyNode root = null; - while ((root = parse(reader)) != null) { - ret.add(root); + try (BufferedReader reader = + new BufferedReader(new InputStreamReader(res.openStream(), StandardCharsets.UTF_8))) { + List<DependencyNode> ret = new ArrayList<>(); + DependencyNode root = null; + while ((root = parse(reader)) != null) { + ret.add(root); + } + return ret; } - return ret; } /**
