Issue #4828 Buffer Corruption (#4864)

+ improve synchronization around releaseBuffer
 + improve synchronization around acquireBuffer
 + made acquireBuffer private.

Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
Greg Wilkins 2020-05-11 21:48:06 +02:00 committed by GitHub
parent 933ab641ee
commit e86977394e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 14 additions and 8 deletions

View File

@ -487,9 +487,9 @@ public class HttpOutput extends ServletOutputStream implements Runnable
synchronized (_channelState) synchronized (_channelState)
{ {
_state = State.CLOSED; _state = State.CLOSED;
}
releaseBuffer(); releaseBuffer();
} }
}
@Override @Override
public void close() throws IOException public void close() throws IOException
@ -613,10 +613,13 @@ public class HttpOutput extends ServletOutputStream implements Runnable
public ByteBuffer getBuffer() public ByteBuffer getBuffer()
{ {
return _aggregate; synchronized (_channelState)
{
return acquireBuffer();
}
} }
public ByteBuffer acquireBuffer() private ByteBuffer acquireBuffer()
{ {
if (_aggregate == null) if (_aggregate == null)
_aggregate = _channel.getByteBufferPool().acquire(getBufferSize(), _interceptor.isOptimizedForDirectBuffers()); _aggregate = _channel.getByteBufferPool().acquire(getBufferSize(), _interceptor.isOptimizedForDirectBuffers());
@ -1409,12 +1412,15 @@ public class HttpOutput extends ServletOutputStream implements Runnable
} }
public void resetBuffer() public void resetBuffer()
{
synchronized (_channelState)
{ {
_interceptor.resetBuffer(); _interceptor.resetBuffer();
if (BufferUtil.hasContent(_aggregate)) if (BufferUtil.hasContent(_aggregate))
BufferUtil.clear(_aggregate); BufferUtil.clear(_aggregate);
_written = 0; _written = 0;
} }
}
@Override @Override
public void setWriteListener(WriteListener writeListener) public void setWriteListener(WriteListener writeListener)

View File

@ -305,7 +305,7 @@ public class ErrorHandler extends AbstractHandler
// TODO error page may cause a BufferOverflow. In which case we try // TODO error page may cause a BufferOverflow. In which case we try
// TODO again with stacks disabled. If it still overflows, it is // TODO again with stacks disabled. If it still overflows, it is
// TODO written without a body. // TODO written without a body.
ByteBuffer buffer = baseRequest.getResponse().getHttpOutput().acquireBuffer(); ByteBuffer buffer = baseRequest.getResponse().getHttpOutput().getBuffer();
ByteBufferOutputStream out = new ByteBufferOutputStream(buffer); ByteBufferOutputStream out = new ByteBufferOutputStream(buffer);
PrintWriter writer = new PrintWriter(new OutputStreamWriter(out, charset)); PrintWriter writer = new PrintWriter(new OutputStreamWriter(out, charset));