Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

isClientDisconnectedException needs to protect against null input #34533

Closed
grackeon opened this issue Mar 4, 2025 · 0 comments
Closed

isClientDisconnectedException needs to protect against null input #34533

grackeon opened this issue Mar 4, 2025 · 0 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: regression A bug that is also a regression
Milestone

Comments

@grackeon
Copy link

grackeon commented Mar 4, 2025

Spring-Web v6.2.3 of introduced changes within WebAsyncManager to wrap client disconnection errors in #34363, but these changes within the throwable consumer are not null-safe as DisconnectedClientHelper.isClientDisconnectedException(ex) never checks if the exception is null. This causes a NullPointerException when executing NestedExceptionUtils.getMostSpecificCause(ex).getMessage() within isClientDisconnectedException().
Mentioned code changes

Maybe the error was introduced by the incorrect JavaDoc of NestedExceptionUtils.getMostSpecificCause(Throwable original), which can in fact return null if the original exception was also null.

This NPE does not affect the behavior for the client, but causes a lot of warn-logs, as the NPE is caught by Tomcats AsyncContextImpl:

2025-03-04T12:00:34.175Z  WARN 1 --- [springboot-application-xyz] [nio-7210-exec-4] o.apache.catalina.core.AsyncContextImpl  : onError() call failed for listener of type [org.apache.catalina.core.AsyncListenerWrapper]

java.lang.NullPointerException: Cannot invoke "java.lang.Throwable.getMessage()" because the return value of "org.springframework.core.NestedExceptionUtils.getMostSpecificCause(java.lang.Throwable)" is null
        at org.springframework.web.util.DisconnectedClientHelper.isClientDisconnectedException(DisconnectedClientHelper.java:120) ~[spring-web-6.2.3.jar!/:6.2.3]
        at org.springframework.web.context.request.async.WebAsyncManager.lambda$startDeferredResultProcessing$6(WebAsyncManager.java:450) ~[spring-web-6.2.3.jar!/:6.2.3]
        at org.springframework.web.context.request.async.StandardServletAsyncWebRequest.lambda$onError$0(StandardServletAsyncWebRequest.java:195) ~[spring-web-6.2.3.jar!/:6.2.3]
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) ~[na:na]
        at org.springframework.web.context.request.async.StandardServletAsyncWebRequest.onError(StandardServletAsyncWebRequest.java:195) ~[spring-web-6.2.3.jar!/:6.2.3]
        at org.apache.catalina.core.AsyncListenerWrapper.fireOnError(AsyncListenerWrapper.java:49) ~[tomcat-embed-core-10.1.36.jar!/:na]
        at org.apache.catalina.core.AsyncContextImpl.setErrorState(AsyncContextImpl.java:415) ~[tomcat-embed-core-10.1.36.jar!/:na]
        at org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:242) ~[tomcat-embed-core-10.1.36.jar!/:na]
        at org.apache.coyote.AbstractProcessor.dispatch(AbstractProcessor.java:243) ~[tomcat-embed-core-10.1.36.jar!/:na]
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:57) ~[tomcat-embed-core-10.1.36.jar!/:na]
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:905) ~[tomcat-embed-core-10.1.36.jar!/:na]
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1743) ~[tomcat-embed-core-10.1.36.jar!/:na]
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.36.jar!/:na]
        at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190) ~[tomcat-embed-core-10.1.36.jar!/:na]
        at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.36.jar!/:na]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) ~[tomcat-embed-core-10.1.36.jar!/:na]
        at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]

v6.2.1 and prior are able to correctly process null values in their error handler implemented in WebAsyncManager, so I assume this is an unwanted side effect.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Mar 4, 2025
@jhoeller jhoeller added in: web Issues in web modules (web, webmvc, webflux, websocket) type: regression A bug that is also a regression and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Mar 4, 2025
@jhoeller jhoeller added this to the 6.2.4 milestone Mar 4, 2025
@rstoyanchev rstoyanchev self-assigned this Mar 4, 2025
@rstoyanchev rstoyanchev changed the title Spring-Web: Newly added check for wrapping disconnected client exceptions causes a lot of errors in StandardServletAsyncWebRequest New check to wrap disconnected client exceptions in WebAsyncManager causes NullPointerException Mar 4, 2025
@bclozel bclozel marked this as a duplicate of spring-projects/spring-boot#44532 Mar 4, 2025
@rstoyanchev rstoyanchev changed the title New check to wrap disconnected client exceptions in WebAsyncManager causes NullPointerException isClientDisconnectedException checks need to protect against null input Mar 10, 2025
@rstoyanchev rstoyanchev changed the title isClientDisconnectedException checks need to protect against null input isClientDisconnectedException needs to protect against null input Mar 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: regression A bug that is also a regression
Projects
None yet
Development

No branches or pull requests

4 participants