This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch 11.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit e60cf384a3a23a03e4402427c4821e45e82c916b Author: opencode <[email protected]> AuthorDate: Fri Oct 9 13:35:05 2026 +0200 Avoid NPE in EncryptInterceptor.stop() after a failed start start() only assigns the encryption manager if createEncryptionManager returns. It throws an IllegalStateException when no key is configured and an IllegalArgumentException for a blocked algorithm mode, neither of which is caught by start()'s GeneralSecurityException-only handler, and validateChannelChain() can abort even earlier. stop() with the SND_TX_SEQ bit set then dereferenced the null manager. Since SimpleTcpCluster.stopInternal() calls channel.stop() with the configured start options on shutdown, a misconfiguration that aborted the channel start produced a NullPointerException that masked the original configuration error and aborted the rest of the interceptor stop chain. Skip the shutdown call when no encryption manager exists so the stop chain completes and the startup error stays visible. The message paths deliberately keep failing when the interceptor was never started. --- .../group/interceptors/EncryptInterceptor.java | 4 +++- .../group/interceptors/TestEncryptInterceptor.java | 21 ++++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/java/org/apache/catalina/tribes/group/interceptors/EncryptInterceptor.java b/java/org/apache/catalina/tribes/group/interceptors/EncryptInterceptor.java index 0e48975fe4..a5f8b08b52 100644 --- a/java/org/apache/catalina/tribes/group/interceptors/EncryptInterceptor.java +++ b/java/org/apache/catalina/tribes/group/interceptors/EncryptInterceptor.java @@ -110,7 +110,9 @@ public class EncryptInterceptor extends ChannelInterceptorBase implements Encryp @Override public void stop(int svc) throws ChannelException { - if (Channel.SND_TX_SEQ == (svc & Channel.SND_TX_SEQ)) { + // The manager is null if start() failed or was never called with the SND_TX_SEQ + // option. Avoid an NPE at shutdown that would mask the original configuration error. + if (Channel.SND_TX_SEQ == (svc & Channel.SND_TX_SEQ) && encryptionManager != null) { encryptionManager.shutdown(); } diff --git a/test/org/apache/catalina/tribes/group/interceptors/TestEncryptInterceptor.java b/test/org/apache/catalina/tribes/group/interceptors/TestEncryptInterceptor.java index 8c6785c4a8..664d212b50 100644 --- a/test/org/apache/catalina/tribes/group/interceptors/TestEncryptInterceptor.java +++ b/test/org/apache/catalina/tribes/group/interceptors/TestEncryptInterceptor.java @@ -385,7 +385,7 @@ public class TestEncryptInterceptor extends EncryptionInterceptorBaseTest { } @Test - public void testTcpFailureDetectorDetection() { + public void testTcpFailureDetectorDetection() throws Exception { src.setPrevious(new TcpFailureDetector()); try { @@ -399,6 +399,25 @@ public class TestEncryptInterceptor extends EncryptionInterceptorBaseTest { } catch (Throwable t) { Assert.fail("EncryptionInterceptor should throw ChannelConfigException, not " + t.getClass().getName()); } + + // The failed start left the encryption manager uncreated, stop() must cope + src.stop(Channel.SND_TX_SEQ); + } + + @Test + public void testStopAfterFailedStart() throws Exception { + EncryptInterceptor interceptor = new EncryptInterceptor(); + + // No key is set, so start() fails before the encryption manager is created + try { + interceptor.start(Channel.SND_TX_SEQ); + Assert.fail("start() without a key should fail"); + } catch (IllegalStateException ise) { + // Expected + } + + // stop() must tolerate the missing encryption manager rather than fail with an NPE + interceptor.stop(Channel.SND_TX_SEQ); } private byte[] encrypt(String message, long timestamp) throws Exception { --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
