Skip to content

Commit

Permalink
#12022 fix NPE when GzipHandler is writing and an exception is thrown…
Browse files Browse the repository at this point in the history
… by the wrapping's Response.write()

Signed-off-by: Ludovic Orban <lorban@bitronix.be>
  • Loading branch information
lorban committed Jul 16, 2024
1 parent 7c42a5b commit f5db520
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ protected void onCompleteFailure(Throwable x)
{
if (_deflaterEntry != null)
{
_state.set(GZState.FINISHED);
_deflaterEntry.release();
_deflaterEntry = null;
}
Expand Down Expand Up @@ -381,6 +382,7 @@ private void cleanup()
{
if (_deflaterEntry != null)
{
_state.set(GZState.FINISHED);
_deflaterEntry.release();
_deflaterEntry = null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
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;
Expand Down Expand Up @@ -194,6 +195,61 @@ public void init() throws Exception
_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()
{
Expand Down Expand Up @@ -2053,4 +2109,18 @@ else if (request.getLength() >= 0)
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;
}
}
}

0 comments on commit f5db520

Please sign in to comment.