eclipse-ee4j / grizzly

Grizzly
https://eclipse-ee4j.github.io/grizzly
Other
149 stars 70 forks source link

AJP throws NPE for responses larger than 8192 bytes #2078

Closed omolenkamp closed 3 years ago

omolenkamp commented 5 years ago

When using AJP between an Apache webserver and GlassFish, GlassFish throws a NullPointerException after writing the response chunks for a request, instead of sending an AJP END_RESPONSE packet. This only happens when the response body is larger than 8192 bytes.

Increasing the send buffer size of the AJP listener (which defaults to 8192 bytes) doesn't make any difference.

java.lang.NullPointerException
        at org.glassfish.grizzly.http.ajp.AjpHandlerFilter.encodeHttpPacket(AjpHandlerFilter.java:258)
        at org.glassfish.grizzly.http.ajp.AjpHandlerFilter.handleWrite(AjpHandlerFilter.java:221)
        at org.glassfish.grizzly.filterchain.ExecutorResolver$8.execute(ExecutorResolver.java:87)
        at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:260)
        at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:177)
        at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:109)
        at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:88)
        at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:53)
        at org.glassfish.grizzly.filterchain.FilterChainContext.write(FilterChainContext.java:866)
        at org.glassfish.grizzly.filterchain.FilterChainContext.write(FilterChainContext.java:834)
        at org.glassfish.grizzly.http.io.OutputBuffer.flushBuffer(OutputBuffer.java:1068)
        at org.glassfish.grizzly.http.io.OutputBuffer.flushBinaryBuffers(OutputBuffer.java:1042)
        at org.glassfish.grizzly.http.io.OutputBuffer.flushAllBuffers(OutputBuffer.java:1012)
        at org.glassfish.grizzly.http.io.OutputBuffer.close(OutputBuffer.java:730)
        at org.glassfish.grizzly.http.io.OutputBuffer.endRequest(OutputBuffer.java:377)
        at org.glassfish.grizzly.http.server.Response.finish(Response.java:518)
        at org.glassfish.grizzly.http.server.HttpServerFilter.afterService(HttpServerFilter.java:373)
        at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:243)
        at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:95)
        at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:260)
        at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:177)
        at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:109)
        at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:88)
        at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:53)
        at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:515)
        at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:89)
        at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:94)
        at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:33)
        at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:114)
        at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:569)
        at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:549)
        at java.lang.Thread.run(Thread.java:748)

I reported this as a GlassFish bug two years ago (https://github.com/eclipse-ee4j/glassfish/issues/22295), but nothing was even done with my report. Because it's possible to work around the bug by patching Grizzly, I'm reporting the bug here. (even though I'm not sure it's in fact a bug in Grizzly; it's also possible that GlassFish is using Grizzly in a way it shouldn't)

SplotyCode commented 4 years ago

This is really wired because in this line it is impossible to get a NullPointerException in the current version and git blame shows no changes since Feb 13, 2018 (that was when the Project was imported to git).

https://github.com/eclipse-ee4j/grizzly/blob/8ce67285bda9938708e965865f1f1a14066f4ee8/modules/http-ajp/src/main/java/org/glassfish/grizzly/http/ajp/AjpHandlerFilter.java#L257-L258

omolenkamp commented 4 years ago

Is it possible, and it does happen.

The if's above these lines leave encodedBuffer null in a number of cases, in this case when httpHeader.isCommitted() returns true, isHeader is false and contentBuffer.hasRemaining() returns false.

SplotyCode commented 4 years ago

But when encodedBuffer is null the assertion (in line 257) will fail and will throw an AssertionError right? So how would line 258 be executed?

omolenkamp commented 4 years ago

Assertions in Java don't do anything unless specifically enabled.