#12022 fix NPE when GzipHandler is writing and an exception is thrown by the wrapping's Response.write()

Signed-off-by: Ludovic Orban <lorban@bitronix.be>
This commit is contained in:
Ludovic Orban 2024-07-10 12:14:09 +02:00
parent 7c42a5b3ae
commit f5db5209f4
2 changed files with 72 additions and 0 deletions

View File

@ -326,6 +326,7 @@ public class GzipResponseAndCallback extends Response.Wrapper implements Callbac
{
if (_deflaterEntry != null)
{
_state.set(GZState.FINISHED);
_deflaterEntry.release();
_deflaterEntry = null;
}
@ -381,6 +382,7 @@ public class GzipResponseAndCallback extends Response.Wrapper implements Callbac
{
if (_deflaterEntry != null)
{
_state.set(GZState.FINISHED);
_deflaterEntry.release();
_deflaterEntry = null;
}

View File

@ -59,6 +59,7 @@ import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ErrorHandler;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.toolchain.test.MavenPaths;
@ -194,6 +195,61 @@ public class GzipHandlerTest
_gzipHandler.setHandler(_contextHandler);
}
@Test
public void testFailureDuringGzipWrite() throws Exception
{
Handler leafHandler = new Handler.Abstract()
{
@Override
public boolean handle(Request request, Response response, Callback callback) throws Exception
{
try (var out = Content.Sink.asOutputStream(response))
{
out.write("Hello, Jetty".getBytes(StandardCharsets.UTF_8));
}
return true;
}
};
Handler rootHandler = new Handler.Wrapper(new GzipHandler(leafHandler))
{
@Override
public boolean handle(Request request, Response response, Callback callback) throws Exception
{
return super.handle(request, new Response.Wrapper(request, response)
{
@Override
public void write(boolean last, ByteBuffer byteBuffer, Callback callback)
{
throw new StacklessException("expected");
}
}, callback);
}
};
_server.setHandler(rootHandler);
ErrorHandler errorHandler = new ErrorHandler();
errorHandler.setShowStacks(true);
errorHandler.setShowCauses(true);
_server.setErrorHandler(errorHandler);
_server.start();
// generated and parsed test
HttpTester.Request request = HttpTester.newRequest();
HttpTester.Response response;
request.setMethod("GET");
request.setURI("/");
request.setVersion("HTTP/1.0");
request.setHeader("Host", "tester");
request.setHeader("accept-encoding", "gzip");
response = HttpTester.parseResponse(_connector.getResponse(request.generate()));
assertThat(response.getStatus(), is(500));
String content = response.getContent();
assertThat(content, containsString("StacklessException: expected"));
assertThat(content, not(containsString("Suppressed: ")));
}
@Test
public void testAddIncludePaths()
{
@ -2053,4 +2109,18 @@ public class GzipHandlerTest
return super.handle(request, response, callback);
}
}
public static class StacklessException extends RuntimeException
{
public StacklessException(String message)
{
super(message);
}
@Override
public synchronized Throwable fillInStackTrace()
{
return this;
}
}
}