From 9b2dae719515de162cad19480c1cdd0fcbefd601 Mon Sep 17 00:00:00 2001 From: markt Date: Sat, 4 Nov 2006 22:35:15 +0000 Subject: [PATCH] Port fix for bug 34956. Enforce requirements of SRV.8.2 / SRV.14.2.5.1 git-svn-id: https://svn.apache.org/repos/asf/tomcat/tc6.0.x/trunk@471281 13f79535-47bb-0310-9956-ffa450edef68 --- .../catalina/core/ApplicationDispatcher.java | 60 ++++++++++++++++++++++ .../catalina/core/ApplicationFilterChain.java | 47 +++++++++++++++++ .../apache/catalina/core/LocalStrings.properties | 2 + 3 files changed, 109 insertions(+) diff --git a/java/org/apache/catalina/core/ApplicationDispatcher.java b/java/org/apache/catalina/core/ApplicationDispatcher.java index b0bec2f2e..f5e8e1dee 100644 --- a/java/org/apache/catalina/core/ApplicationDispatcher.java +++ b/java/org/apache/catalina/core/ApplicationDispatcher.java @@ -325,6 +325,11 @@ final class ApplicationDispatcher // Set up to handle the specified request and response setup(request, response, false); + if (Globals.STRICT_SERVLET_COMPLIANCE) { + // Check SRV.8.2 / SRV.14.2.5.1 compliance + checkSameObjects(); + } + // Identify the HTTP-specific request and response objects (if any) HttpServletRequest hrequest = null; if (request instanceof HttpServletRequest) @@ -507,6 +512,11 @@ final class ApplicationDispatcher // Set up to handle the specified request and response setup(request, response, true); + if (Globals.STRICT_SERVLET_COMPLIANCE) { + // Check SRV.8.2 / SRV.14.2.5.1 compliance + checkSameObjects(); + } + // Create a wrapped response to use for this request // ServletResponse wresponse = null; ServletResponse wresponse = wrapResponse(); @@ -958,5 +968,55 @@ final class ApplicationDispatcher } + private void checkSameObjects() throws ServletException { + ServletRequest originalRequest = + ApplicationFilterChain.getLastServicedRequest(); + ServletResponse originalResponse = + ApplicationFilterChain.getLastServicedResponse(); + + // Some forwards, eg from valves will not set original values + if (originalRequest == null || originalResponse == null) { + return; + } + + boolean same = false; + ServletRequest dispatchedRequest = appRequest; + + while (!same) { + if (originalRequest.equals(dispatchedRequest)) { + same = true; + } + if (!same && dispatchedRequest instanceof ServletRequestWrapper) { + dispatchedRequest = + ((ServletRequestWrapper) dispatchedRequest).getRequest(); + } else { + break; + } + } + if (!same) { + throw new ServletException(sm.getString( + "applicationDispatcher.specViolation.request")); + } + + same = false; + ServletResponse dispatchedResponse = appResponse; + + while (!same) { + if (originalResponse.equals(dispatchedResponse)) { + same = true; + } + + if (!same && dispatchedResponse instanceof ServletResponseWrapper) { + dispatchedResponse = + ((ServletResponseWrapper) dispatchedResponse).getResponse(); + } else { + break; + } + } + if (!same) { + throw new ServletException(sm.getString( + "applicationDispatcher.specViolation.response")); + } + } } diff --git a/java/org/apache/catalina/core/ApplicationFilterChain.java b/java/org/apache/catalina/core/ApplicationFilterChain.java index 375879e78..0e884db28 100644 --- a/java/org/apache/catalina/core/ApplicationFilterChain.java +++ b/java/org/apache/catalina/core/ApplicationFilterChain.java @@ -36,6 +36,7 @@ import org.apache.catalina.CometEvent; import org.apache.catalina.CometFilter; import org.apache.catalina.CometFilterChain; import org.apache.catalina.CometProcessor; +import org.apache.catalina.Globals; import org.apache.catalina.InstanceEvent; import org.apache.catalina.security.SecurityUtil; import org.apache.catalina.util.InstanceSupport; @@ -54,6 +55,19 @@ import org.apache.catalina.util.StringManager; final class ApplicationFilterChain implements FilterChain, CometFilterChain { + // Used to enforce requirements of SRV.8.2 / SRV.14.2.5.1 + private final static ThreadLocal lastServicedRequest; + private final static ThreadLocal lastServicedResponse; + + static { + if (Globals.STRICT_SERVLET_COMPLIANCE) { + lastServicedRequest = new ThreadLocal(); + lastServicedResponse = new ThreadLocal(); + } else { + lastServicedRequest = null; + lastServicedResponse = null; + } + } // -------------------------------------------------------------- Constants @@ -250,6 +264,11 @@ final class ApplicationFilterChain implements FilterChain, CometFilterChain { // We fell off the end of the chain -- call the servlet instance try { + if (Globals.STRICT_SERVLET_COMPLIANCE) { + lastServicedRequest.set(request); + lastServicedResponse.set(response); + } + support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT, servlet, request, response); if ((request instanceof HttpServletRequest) && @@ -293,6 +312,11 @@ final class ApplicationFilterChain implements FilterChain, CometFilterChain { servlet, request, response, e); throw new ServletException (sm.getString("filterChain.servlet"), e); + } finally { + if (Globals.STRICT_SERVLET_COMPLIANCE) { + lastServicedRequest.set(null); + lastServicedResponse.set(null); + } } } @@ -340,6 +364,29 @@ final class ApplicationFilterChain implements FilterChain, CometFilterChain { } } + + /** + * The last request passed to a servlet for servicing from the current + * thread. + * + * @return The last request to be serviced. + */ + public static ServletRequest getLastServicedRequest() { + return (ServletRequest) lastServicedRequest.get(); + } + + + /** + * The last response passed to a servlet for servicing from the current + * thread. + * + * @return The last response to be serviced. + */ + public static ServletResponse getLastServicedResponse() { + return (ServletResponse) lastServicedResponse.get(); + } + + private void internalDoFilterEvent(CometEvent event) throws IOException, ServletException { diff --git a/java/org/apache/catalina/core/LocalStrings.properties b/java/org/apache/catalina/core/LocalStrings.properties index 4c81b9dc6..28ce70549 100644 --- a/java/org/apache/catalina/core/LocalStrings.properties +++ b/java/org/apache/catalina/core/LocalStrings.properties @@ -10,6 +10,8 @@ applicationDispatcher.forward.throw=Forwarded resource threw an exception applicationDispatcher.include.throw=Included resource threw an exception applicationDispatcher.isUnavailable=Servlet {0} is currently unavailable applicationDispatcher.serviceException=Servlet.service() for servlet {0} threw exception +applicationDispatcher.specViolation.request=Original SevletRequest or wrapped original ServletRequest not passed to RequestDispatcher in violation of SRV.8.2 and SRV.14.2.5.1 +applicationDispatcher.specViolation.response=Original SevletResponse or wrapped original ServletResponse not passed to RequestDispatcher in violation of SRV.8.2 and SRV.14.2.5.1 applicationRequest.badParent=Cannot locate parent Request implementation applicationRequest.badRequest=Request is not a javax.servlet.ServletRequestWrapper applicationResponse.badParent=Cannot locate parent Response implementation -- 2.11.0