Bug 52577 - Response output written in filter can be truncated
Summary: Response output written in filter can be truncated
Alias: None
Product: Tomcat 7
Classification: Unclassified
Component: Catalina (show other bugs)
Version: 7.0.25
Hardware: PC Linux
: P2 normal (vote)
Target Milestone: ---
Assignee: Tomcat Developers Mailing List
Depends on:
Reported: 2012-02-02 07:45 UTC by Dmitry Neverov
Modified: 2012-02-05 21:17 UTC (History)
0 users


Note You need to log in before you can comment on or make changes to this bug.
Description Dmitry Neverov 2012-02-02 07:45:44 UTC
Due to changes 1229726, 1229727 and 1229728 output written to response in the filter can be truncated up to 8192 bytes. Consider the following scenario:

- you have a filter that invoke getWriter() before chain.doFilter(request, responseWrapper)

- responseWrapper overrides getWriter() method and returns some
  buffered writer, not the real one

- during execution of chain.doFilter there is a forward

Before the forward ApplicationDispather calls resetBuffer on response, which in turn calls reset() on OutputBuffer, which sets gotEnc field to false. This field is initialized in the setConverter() method which is called from response.getWriter(), but since our wrapperResponse overrides getWriter(), OutputBuffer.setConverter() never called and OutputBuffer still has gotEnc = false.

Response's close() and flushBuffer() methods call OutputBuffer's flush(), but since gotEnc == false, conv.flushBuffer() is not called:

if (gotEnc && conv != null) {

A workaround for us is to implement getWriter() method in responseWrapper like this:

public Writer getWriter() {
  Writer originalWriter = originalResponse.getWriter();//save for future processing
  return ourWriter;

Maybe you should change flushing to something like that:

if (conv != null) {

because you invoke conv.convert() without any checks in the write*() methods and it seems like conv is never null.
Comment 1 Mark Thomas 2012-02-05 21:17:58 UTC
Thanks for the report. The issue may be triggered simply by calling reset() on the response. No need for the filter or the wrapper.

This has been fixed in trunk and 7.0.x and will be included in 7.0.26 onwards.