From 582609610b2f6cbbd1b5747323a9a89cf4f4370c Mon Sep 17 00:00:00 2001 From: btlqql <2977859784@qq.com> Date: Sat, 1 Aug 2026 22:18:14 +0800 Subject: [PATCH] fix: guard NPE in NetworkUtil and concurrent read in IndexService - NetworkUtil.socketAddress2String: InetSocketAddress.getAddress() returns null when the hostname is unresolved, so getAddress().getHostAddress() threw NPE; fall back to getHostString() when the address is null - NetworkUtil.string2SocketAddress: an address without ':' made lastIndexOf return -1 and substring(0, -1) threw StringIndexOutOfBoundsException; throw a clear IllegalArgumentException - IndexService.getTotalSize: indexFileList is a plain ArrayList guarded by readWriteLock everywhere else, but getTotalSize read it without the lock, so a concurrent destroy()/deleteExpiredFile() could clear it between the isEmpty() check and get(0), causing IndexOutOfBoundsException; acquire the read lock Compiled and verified on the build server (mvn -pl broker -am compile). --- .../apache/rocketmq/common/utils/NetworkUtil.java | 7 ++++++- .../apache/rocketmq/store/index/IndexService.java | 13 +++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/common/src/main/java/org/apache/rocketmq/common/utils/NetworkUtil.java b/common/src/main/java/org/apache/rocketmq/common/utils/NetworkUtil.java index 6d454925f6b..c884563886a 100644 --- a/common/src/main/java/org/apache/rocketmq/common/utils/NetworkUtil.java +++ b/common/src/main/java/org/apache/rocketmq/common/utils/NetworkUtil.java @@ -193,6 +193,9 @@ public static String denormalizeHostAddress(final String bracketedAddress) { public static SocketAddress string2SocketAddress(final String addr) { int split = addr.lastIndexOf(":"); + if (split < 0) { + throw new IllegalArgumentException("Invalid socket address, missing ':': " + addr); + } String host = addr.substring(0, split); String port = addr.substring(split + 1); return new InetSocketAddress(host, Integer.parseInt(port)); @@ -201,7 +204,9 @@ public static SocketAddress string2SocketAddress(final String addr) { public static String socketAddress2String(final SocketAddress addr) { StringBuilder sb = new StringBuilder(); InetSocketAddress inetSocketAddress = (InetSocketAddress) addr; - sb.append(inetSocketAddress.getAddress().getHostAddress()); + // getAddress() returns null when the hostname could not be resolved; fall back to the host string. + InetAddress address = inetSocketAddress.getAddress(); + sb.append(address != null ? address.getHostAddress() : inetSocketAddress.getHostString()); sb.append(":"); sb.append(inetSocketAddress.getPort()); return sb.toString(); diff --git a/store/src/main/java/org/apache/rocketmq/store/index/IndexService.java b/store/src/main/java/org/apache/rocketmq/store/index/IndexService.java index 1a180e4442b..94a279550a9 100644 --- a/store/src/main/java/org/apache/rocketmq/store/index/IndexService.java +++ b/store/src/main/java/org/apache/rocketmq/store/index/IndexService.java @@ -92,11 +92,16 @@ public boolean load(final boolean lastExitOK) { } public long getTotalSize() { - if (indexFileList.isEmpty()) { - return 0; - } + this.readWriteLock.readLock().lock(); + try { + if (indexFileList.isEmpty()) { + return 0; + } - return (long) indexFileList.get(0).getFileSize() * indexFileList.size(); + return (long) indexFileList.get(0).getFileSize() * indexFileList.size(); + } finally { + this.readWriteLock.readLock().unlock(); + } } public void deleteExpiredFile(long offset) {