You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by bu...@apache.org on 2011/11/08 21:32:59 UTC

DO NOT REPLY [Bug 52157] New: 7.0.21 change can use undesired Writer object. Wrapper circumvention. Servlet 2.3

https://issues.apache.org/bugzilla/show_bug.cgi?id=52157

             Bug #: 52157
           Summary: 7.0.21 change can use undesired Writer object. Wrapper
                    circumvention. Servlet 2.3
           Product: Tomcat 7
           Version: 7.0.21
          Platform: PC
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Servlet & JSP API
        AssignedTo: dev@tomcat.apache.org
        ReportedBy: bplies@bulliondirect.com
    Classification: Unclassified


in 7.0.21 the commit:
    "41718: Include a response body when sending a redirect. (markt)"

...catalina.connector.Response.sendRedirect() now calls getWriter() in order to
write the body of the http response.  However the committed implementation will
bypass any wrappers.  Note that Servlet 2.3 defines
HttpServletResponseWrapper.getWriter()
http://download.oracle.com/javaee/6/api/javax/servlet/ServletResponseWrapper.html#getWriter%28%29
which would allow someone to return an alternate Writer than the default.

catalina.connector.Response
line 1335 (sendRedirect()):
            String absolute = toAbsolute(location);
            setStatus(SC_FOUND);
            setHeader("Location", absolute);
            PrintWriter writer = getWriter(); // <<<<<< circumvents wrapping by
HttpServletResponseWrapper.getWriter()
        // .. This directly commits a response to the client without allowing
the Wrapper the opportunity to do something different.
            writer.print(sm.getString("coyoteResponse.sendRedirect.note",
                    RequestUtil.filter(absolute)));
            flushBuffer();


So if someone calls wrapper.sendRedirect(location) it invokes the
Reponse.sendRedirect().  That Reponse.sendRedirect() gets a reference to a
Writer relative to itself and not the Wrapper's.  In a case where the user
application desires to intercept  a redirect and do something different, the
response has already been committed and will cause an IllegalStateException.

Not sure what would be the best way to fix this.

Possible areas to consider
http://svn.apache.org/repos/asf/tomcat/tc7.0.x/trunk/java/javax/servlet/ServletResponseWrapper.java 
or
http://svn.apache.org/repos/asf/tomcat/tc7.0.x/trunk/java/javax/servlet/http/HttpServletResponseWrapper.java 
or
http://svn.apache.org/repos/asf/tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/Response.java

Bottom line is Servlet 2.3 HttpServletResponseWrapper allows you to control
what Writer to return, and the current Tomcat 7.0.21 implementation will get a
reference to a default Writer which may be undesirable, commit a response to
the undesired Writer, and expose a scenario for an IllegalStateException.

7.0.20 and previous did not have this problem.

-- 
Configure bugmail: https://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


DO NOT REPLY [Bug 52157] 7.0.21 change can use undesired Writer object. Wrapper circumvention. Servlet 2.3

Posted by bu...@apache.org.
https://issues.apache.org/bugzilla/show_bug.cgi?id=52157

Mark Thomas <ma...@apache.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |DUPLICATE

--- Comment #2 from Mark Thomas <ma...@apache.org> 2011-11-08 23:35:49 UTC ---
There are a bunch of issues related to this for which no simple solution is
available since application provided wrappers are unlikely to be available at
the point where the redirect needs to take place.

See the duplicate for details of the fix.

*** This bug has been marked as a duplicate of bug 51952 ***

-- 
Configure bugmail: https://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


DO NOT REPLY [Bug 52157] 7.0.21 change can use undesired Writer object. Wrapper circumvention. Servlet 2.3

Posted by bu...@apache.org.
https://issues.apache.org/bugzilla/show_bug.cgi?id=52157

Brad Plies <bp...@bulliondirect.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bplies@bulliondirect.com
         OS/Version|                            |All

-- 
Configure bugmail: https://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


DO NOT REPLY [Bug 52157] 7.0.21 change can use undesired Writer object. Wrapper circumvention. Servlet 2.3

Posted by bu...@apache.org.
https://issues.apache.org/bugzilla/show_bug.cgi?id=52157

--- Comment #1 from Brad Plies <bp...@bulliondirect.com> 2011-11-08 20:58:17 UTC ---
Attempted example

// See:
http://download.oracle.com/javaee/6/api/javax/servlet/http/HttpServletResponseWrapper.html
class MyWrapper extends HttpServletResponseWrapper 
{
    public MyWrapper(HttpServletResponse response) { super(response); }
    // This was working fine with Tomcat 7.0.20
    public void sendResponse() throws IOException
    {
        this.pw.flush(); this.pw.close();
        ServletOutputStream realStream = super.getOutputStream(); 
        byte[] byteArray = basos.baos.toByteArray();
        realStream.write(byteArray); realStream.flush();
    }
    // NOTE: Alternate Writer & OutputStream
    MyOutputStream basos = new MyOutputStream();
    PrintWriter pw = new PrintWriter(basos);

    // NOTE: Overriding default behavior of Wrapper, returning alternates
    public ServletOutputStream getOutputStream() throws IOException { return
basos; }
    public PrintWriter getWriter() throws IOException { return pw; }
    }
}

public class MyFilter implements Filter
{
    @Override
    public void doFilter(final ServletRequest request, final ServletResponse
response,
        final FilterChain chain) throws IOException, ServletException
    {
        final HttpServletRequest httpRequest = (HttpServletRequest) request;
        final MyWrapper wrappedResponse = 
            new MyWrapper((HttpServletResponse) response);

        chain.doFilter(httpRequest, wrappedResponse);
        // ... Something down the chain called wrappedResponse.sendRedirect()

        if (someCondition) 
        {
            // Override redirect and handle response directly or something
            response.sendErrorPage(...); // NOTE: Original response object,
discarding anything written to the wrapped buffer

            // !!! Blows up in Tomcat 7.0.21 because sendRedirect()
circumvented the Wrapper's Writer
        }
        else
        {
            // Accept the wrapped Response as the output
            // Set response output to be same as wrappedResponse output
        }
    }
}

-- 
Configure bugmail: https://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org