Author: markt Date: Tue Nov 3 12:33:42 2015 New Revision: 1712277 URL: http://svn.apache.org/viewvc?rev=1712277&view=rev Log: Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=58031 Make the (first) reason parameter parsing failed available as a request attribute and then use it to provide a better status code via the FailedRequstFilter (if configured).
Modified: tomcat/tc6.0.x/trunk/STATUS.txt tomcat/tc6.0.x/trunk/java/org/apache/catalina/Globals.java tomcat/tc6.0.x/trunk/java/org/apache/catalina/connector/Request.java tomcat/tc6.0.x/trunk/java/org/apache/catalina/filters/FailedRequestFilter.java tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/Parameters.java tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Modified: tomcat/tc6.0.x/trunk/STATUS.txt URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/STATUS.txt?rev=1712277&r1=1712276&r2=1712277&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/STATUS.txt (original) +++ tomcat/tc6.0.x/trunk/STATUS.txt Tue Nov 3 12:33:42 2015 @@ -28,14 +28,6 @@ None PATCHES PROPOSED TO BACKPORT: [ New proposals should be added at the end of the list ] -* Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=58031 - Provide a mechanism to enable a 413 response if maxPostSize is exceeded while - processing parameters - http://svn.apache.org/r1694433 - http://svn.apache.org/r1694437 - +1: markt, remm - -1: - * Ensure LogFactoryImpl is excluded from extras/tomcat-juli-adapters jar. Reported by Benjamin Gandon on the dev list Mail thread: http://tomcat.markmail.org/thread/7iygcau3vja4cbui Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/Globals.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/Globals.java?rev=1712277&r1=1712276&r2=1712277&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/catalina/Globals.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/Globals.java Tue Nov 3 12:33:42 2015 @@ -5,9 +5,9 @@ * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -30,9 +30,9 @@ public final class Globals { /** * The servlet context attribute under which we store the alternate - * deployment descriptor for this web application + * deployment descriptor for this web application */ - public static final String ALT_DD_ATTR = + public static final String ALT_DD_ATTR = "org.apache.catalina.deploy.alt_dd"; /** @@ -62,13 +62,13 @@ public final class Globals { /** * Request dispatcher state. */ - public static final String DISPATCHER_TYPE_ATTR = + public static final String DISPATCHER_TYPE_ATTR = "org.apache.catalina.core.DISPATCHER_TYPE"; /** * Request dispatcher path. */ - public static final String DISPATCHER_REQUEST_PATH_ATTR = + public static final String DISPATCHER_REQUEST_PATH_ATTR = "org.apache.catalina.core.DISPATCHER_REQUEST_PATH"; /** @@ -223,8 +223,8 @@ public final class Globals { */ public static final String FORWARD_REQUEST_URI_ATTR = "javax.servlet.forward.request_uri"; - - + + /** * The request attribute under which the original context path is stored * on an forwarded dispatcher request. @@ -264,7 +264,7 @@ public final class Globals { public static final String SERVLET_NAME_ATTR = "javax.servlet.error.servlet_name"; - + /** * The name of the cookie used to pass the session identifier back * and forth with the client. @@ -308,7 +308,7 @@ public final class Globals { public static final String SUBJECT_ATTR = "javax.security.auth.subject"; - + /** * The servlet context attribute under which we record the set of * welcome files (as an object of type String[]) for this application. @@ -338,7 +338,14 @@ public final class Globals { /** - * The master flag which controls strict servlet specification + * The reason that the parameter parsing failed. + */ + public static final String PARAMETER_PARSE_FAILED_REASON_ATTR = + "org.apache.catalina.parameter_parse_failed_reason"; + + + /** + * The master flag which controls strict servlet specification * compliance. */ public static final boolean STRICT_SERVLET_COMPLIANCE = Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/connector/Request.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/connector/Request.java?rev=1712277&r1=1712276&r2=1712277&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/catalina/connector/Request.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/connector/Request.java Tue Nov 3 12:33:42 2015 @@ -5,9 +5,9 @@ * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -53,6 +53,7 @@ import org.apache.tomcat.util.buf.String import org.apache.tomcat.util.http.Cookies; import org.apache.tomcat.util.http.FastHttpDateFormat; import org.apache.tomcat.util.http.Parameters; +import org.apache.tomcat.util.http.Parameters.FailReason; import org.apache.tomcat.util.http.ServerCookie; import org.apache.tomcat.util.http.mapper.MappingData; @@ -90,18 +91,18 @@ public class Request private final static boolean ALLOW_EMPTY_QUERY_STRING; private static final Log log = LogFactory.getLog(Request.class); - + static { // Ensure that classes are loaded for SM new StringCache.ByteEntry(); new StringCache.CharEntry(); - + ALLOW_EMPTY_QUERY_STRING = Boolean.parseBoolean(System.getProperty( "org.apache.catalina.connector.Request.ALLOW_EMPTY_QUERY_STRING", Boolean.toString(Globals.STRICT_SERVLET_COMPLIANCE))); } - + // ----------------------------------------------------------- Constructors public Request() { @@ -122,7 +123,7 @@ public class Request /** * Set the Coyote request. - * + * * @param coyoteRequest The Coyote request */ public void setCoyoteRequest(org.apache.coyote.Request coyoteRequest) { @@ -213,19 +214,19 @@ public class Request */ protected String authType = null; - + /** * Associated event. */ protected CometEventImpl event = null; - + /** * Comet state */ protected boolean comet = false; - - + + /** * The current dispatcher type. */ @@ -241,7 +242,7 @@ public class Request /** * ServletInputStream. */ - protected CoyoteInputStream inputStream = + protected CoyoteInputStream inputStream = new CoyoteInputStream(inputBuffer); @@ -292,7 +293,7 @@ public class Request */ protected boolean secure = false; - + /** * The Subject associated with the current AccessControllerContext */ @@ -370,18 +371,18 @@ public class Request */ protected String remoteHost = null; - + /** * Remote port */ protected int remotePort = -1; - + /** * Local address */ protected String localAddr = null; - + /** * Local address */ @@ -422,7 +423,7 @@ public class Request event.clear(); event = null; } - + authType = null; inputBuffer.recycle(); usingInputStream = false; @@ -494,7 +495,7 @@ public class Request public void clearEncoders() { inputBuffer.clearEncoders(); } - + /** * Clear cached encoders (to save memory for Comet requests). @@ -503,7 +504,7 @@ public class Request throws IOException { return (inputBuffer.realReadBytes(null, 0, 0) > 0); } - + // -------------------------------------------------------- Request Methods @@ -570,7 +571,7 @@ public class Request /** * Set filter chain associated with the request. - * + * * @param filterChain new filter chain */ public void setFilterChain(FilterChain filterChain) { @@ -642,7 +643,7 @@ public class Request public HttpServletRequest getRequest() { if (facade == null) { facade = new RequestFacade(this); - } + } return (facade); } @@ -702,7 +703,7 @@ public class Request /** * Set the URI converter. - * + * * @param URIConverter the new URI connverter */ protected void setURIConverter(B2CConverter URIConverter) { @@ -743,7 +744,7 @@ public class Request * * @exception IOException if an input/output error occurs */ - public ServletInputStream createInputStream() + public ServletInputStream createInputStream() throws IOException { if (inputStream == null) { inputStream = new CoyoteInputStream(inputBuffer); @@ -913,11 +914,11 @@ public class Request public Object getAttribute(String name) { if (name.equals(Globals.DISPATCHER_TYPE_ATTR)) { - return (dispatcherType == null) + return (dispatcherType == null) ? ApplicationFilterFactory.REQUEST_INTEGER : dispatcherType; } else if (name.equals(Globals.DISPATCHER_REQUEST_PATH_ATTR)) { - return (requestDispatcherPath == null) + return (requestDispatcherPath == null) ? getRequestPathMB().toString() : requestDispatcherPath.toString(); } else if (name.equals(Globals.PARAMETER_PARSE_FAILED_ATTR)) { @@ -936,7 +937,7 @@ public class Request if(attr != null) return attr; if( isSSLAttribute(name) ) { - coyoteRequest.action(ActionCode.ACTION_REQ_SSL_ATTRIBUTE, + coyoteRequest.action(ActionCode.ACTION_REQ_SSL_ATTRIBUTE, coyoteRequest); attr = coyoteRequest.getAttribute(Globals.CERTIFICATES_ATTR); if( attr != null) { @@ -1259,14 +1260,14 @@ public class Request /** * Returns the Internet Protocol (IP) source port of the client * or last proxy that sent the request. - */ + */ public int getRemotePort(){ if (remotePort == -1) { coyoteRequest.action (ActionCode.ACTION_REQ_REMOTEPORT_ATTRIBUTE, coyoteRequest); remotePort = coyoteRequest.getRemotePort(); } - return remotePort; + return remotePort; } /** @@ -1285,14 +1286,14 @@ public class Request /** * Returns the Internet Protocol (IP) address of the interface on * which the request was received. - */ + */ public String getLocalAddr(){ if (localAddr == null) { coyoteRequest.action (ActionCode.ACTION_REQ_LOCAL_ADDR_ATTRIBUTE, coyoteRequest); localAddr = coyoteRequest.localAddr().toString(); } - return localAddr; + return localAddr; } @@ -1308,7 +1309,7 @@ public class Request } return localPort; } - + /** * Return a RequestDispatcher that wraps the resource at the specified * path, which may be interpreted as relative to the current request path. @@ -1414,7 +1415,7 @@ public class Request } else { return; } - + // Notify interested application event listeners Object listeners[] = context.getApplicationEventListeners(); if ((listeners == null) || (listeners.length == 0)) @@ -1445,7 +1446,7 @@ public class Request * @param value The associated value */ public void setAttribute(String name, Object value) { - + // Name cannot be null if (name == null) throw new IllegalArgumentException @@ -1504,7 +1505,7 @@ public class Request if (name.startsWith("org.apache.tomcat.")) { coyoteRequest.setAttribute(name, value); } - + // Notify interested application event listeners Object listeners[] = context.getApplicationEventListeners(); if ((listeners == null) || (listeners.length == 0)) @@ -1779,7 +1780,7 @@ public class Request /** * Set the decoded request URI. - * + * * @param uri The decoded request URI */ public void setDecodedRequestURI(String uri) { @@ -1789,7 +1790,7 @@ public class Request /** * Get the decoded request URI. - * + * * @return the URL decoded request URI */ public String getDecodedRequestURI() { @@ -1799,7 +1800,7 @@ public class Request /** * Get the decoded request URI. - * + * * @return the URL decoded request URI */ public MessageBytes getDecodedRequestURIMB() { @@ -1831,18 +1832,18 @@ public class Request if (Globals.IS_SECURITY_ENABLED){ HttpSession session = getSession(false); - if ( (subject != null) && + if ( (subject != null) && (!subject.getPrincipals().contains(principal)) ){ - subject.getPrincipals().add(principal); + subject.getPrincipals().add(principal); } else if (session != null && session.getAttribute(Globals.SUBJECT_ATTR) == null) { subject = new Subject(); - subject.getPrincipals().add(principal); + subject.getPrincipals().add(principal); } if (session != null){ session.setAttribute(Globals.SUBJECT_ATTR, subject); } - } + } this.userPrincipal = principal; } @@ -1870,7 +1871,7 @@ public class Request /** * Get the context path. - * + * * @return the context path */ public MessageBytes getContextPathMB() { @@ -1995,7 +1996,7 @@ public class Request /** * Get the path info. - * + * * @return the path info */ public MessageBytes getPathInfoMB() { @@ -2029,7 +2030,7 @@ public class Request if (!ALLOW_EMPTY_QUERY_STRING && "".equals(queryString)) { return null; } - + return queryString; } @@ -2051,7 +2052,7 @@ public class Request /** * Get the request path. - * + * * @return the request path */ public MessageBytes getRequestPathMB() { @@ -2125,7 +2126,7 @@ public class Request /** * Get the servlet path. - * + * * @return the servlet path */ public MessageBytes getServletPathMB() { @@ -2297,7 +2298,7 @@ public class Request * are several things that may trigger an ID change. These include moving * between nodes in a cluster and session fixation prevention during the * authentication process. - * + * * @param newSessionId The new session ID to use */ public void changeSessionId(String newSessionId) { @@ -2306,10 +2307,10 @@ public class Request if (requestedSessionId != null && requestedSessionId.length() > 0) { requestedSessionId = newSessionId; } - + if (context != null && !context.getCookies()) return; - + if (response != null) { String scName = null; if (context != null) { @@ -2318,7 +2319,7 @@ public class Request if (scName == null) { scName = Globals.SESSION_COOKIE_NAME; } - + Cookie newCookie = new Cookie(scName, newSessionId); configureSessionCookie(newCookie); @@ -2332,7 +2333,7 @@ public class Request } } - + /** * Return the session associated with this Request, creating one * if necessary and requested. @@ -2354,8 +2355,8 @@ public class Request } return event; } - - + + /** * Return true if the current request is handling Comet traffic. */ @@ -2363,7 +2364,7 @@ public class Request return comet; } - + /** * Set comet state. */ @@ -2376,8 +2377,8 @@ public class Request */ public boolean isParametersParsed() { return parametersParsed; - } - + } + /** * Return true if bytes are available. */ @@ -2388,11 +2389,11 @@ public class Request public void cometClose() { coyoteRequest.action(ActionCode.ACTION_COMET_CLOSE,getEvent()); } - + public void setCometTimeout(long timeout) { coyoteRequest.action(ActionCode.ACTION_COMET_SETTIMEOUT,new Long(timeout)); } - + // ------------------------------------------------------ Protected Methods @@ -2441,7 +2442,7 @@ public class Request // Attempt to reuse session id if one was submitted in a cookie // Do not reuse the session id if it is from a URL, to prevent possible // phishing attacks - if (connector.getEmptySessionPath() + if (connector.getEmptySessionPath() && isRequestedSessionIdFromCookie()) { session = manager.createSession(getRequestedSessionId()); } else { @@ -2476,9 +2477,9 @@ public class Request */ protected void configureSessionCookie(Cookie cookie) { cookie.setMaxAge(-1); - + Context ctxt = getContext(); - + String contextPath = null; if (ctxt != null && !getConnector().getEmptySessionPath()) { if (ctxt.getSessionCookiePath() != null) { @@ -2492,7 +2493,7 @@ public class Request } else { cookie.setPath("/"); } - + if (ctxt != null && ctxt.getSessionCookieDomain() != null) { cookie.setDomain(ctxt.getSessionCookieDomain()); } @@ -2501,7 +2502,7 @@ public class Request cookie.setSecure(true); } } - + protected String unescape(String s) { if (s==null) return null; if (s.indexOf('\\') == -1) return s; @@ -2622,6 +2623,7 @@ public class Request context.getLogger().debug( sm.getString("coyoteRequest.postTooLarge")); } + parameters.setParseFailedReason(FailReason.POST_TOO_LARGE); return; } byte[] formData = null; @@ -2634,6 +2636,7 @@ public class Request } try { if (readPostBody(formData, len) != len) { + parameters.setParseFailedReason(FailReason.REQUEST_BODY_INCOMPLETE); return; } } catch (IOException e) { @@ -2642,6 +2645,7 @@ public class Request context.getLogger().debug( sm.getString("coyoteRequest.parseParameters"), e); } + parameters.setParseFailedReason(FailReason.CLIENT_DISCONNECT); return; } parameters.processParameters(formData, 0, len); @@ -2652,6 +2656,7 @@ public class Request formData = readChunkedPostBody(); } catch (IllegalStateException ise) { // chunkedPostTooLarge error + parameters.setParseFailedReason(FailReason.POST_TOO_LARGE); Context context = getContext(); if (context != null && context.getLogger().isDebugEnabled()) { context.getLogger().debug( @@ -2661,6 +2666,7 @@ public class Request return; } catch (IOException e) { // Client disconnect + parameters.setParseFailedReason(FailReason.CLIENT_DISCONNECT); if (context.getLogger().isDebugEnabled()) { context.getLogger().debug( sm.getString("coyoteRequest.parseParameters"), e); @@ -2674,7 +2680,7 @@ public class Request success = true; } finally { if (!success) { - parameters.setParseFailed(true); + parameters.setParseFailedReason(FailReason.UNKNOWN); } } @@ -2705,9 +2711,9 @@ public class Request */ protected byte[] readChunkedPostBody() throws IOException { ByteChunk body = new ByteChunk(); - + byte[] buffer = new byte[CACHED_POST_LEN]; - + int len = 0; while (len > -1) { len = getStream().read(buffer, 0, CACHED_POST_LEN); @@ -2733,8 +2739,8 @@ public class Request return body.getBuffer(); } } - - + + /** * Parse request locales. */ @@ -2866,7 +2872,7 @@ public class Request } - + protected static final boolean isAlpha(String value) { for (int i = 0; i < value.length(); i++) { char c = value.charAt(i); @@ -2876,5 +2882,5 @@ public class Request } return true; } - + } Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/filters/FailedRequestFilter.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/filters/FailedRequestFilter.java?rev=1712277&r1=1712276&r2=1712277&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/catalina/filters/FailedRequestFilter.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/filters/FailedRequestFilter.java Tue Nov 3 12:33:42 2015 @@ -30,6 +30,7 @@ import org.apache.catalina.CometFilter; import org.apache.catalina.CometFilterChain; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.util.http.Parameters.FailReason; /** * Filter that will reject requests if there was a failure during parameter @@ -55,8 +56,41 @@ public class FailedRequestFilter extends public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (!isGoodRequest(request)) { - ((HttpServletResponse) response) - .sendError(HttpServletResponse.SC_BAD_REQUEST); + FailReason reason = (FailReason) request.getAttribute( + Globals.PARAMETER_PARSE_FAILED_REASON_ATTR); + + int status; + + switch (reason) { + case IO_ERROR: + // Not the client's fault + status = HttpServletResponse.SC_INTERNAL_SERVER_ERROR; + break; + case POST_TOO_LARGE: + status = HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE; + break; + case TOO_MANY_PARAMETERS: + // 413/414 aren't really correct here since the request body + // and/or URI could be well below any limits set. Use the + // default. + case UNKNOWN: // Assume the client is at fault + // Various things that the client can get wrong that don't have + // a specific status code so use the default. + case INVALID_CONTENT_TYPE: + case MULTIPART_CONFIG_INVALID: + case NO_NAME: + case REQUEST_BODY_INCOMPLETE: + case URL_DECODING: + case CLIENT_DISCONNECT: + // Client is never going to see this so this is really just + // for the access logs. The default is fine. + default: + // 400 + status = HttpServletResponse.SC_BAD_REQUEST; + break; + } + + ((HttpServletResponse) response).sendError(status); return; } chain.doFilter(request, response); Modified: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/Parameters.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/Parameters.java?rev=1712277&r1=1712276&r2=1712277&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/Parameters.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/http/Parameters.java Tue Nov 3 12:33:42 2015 @@ -34,7 +34,7 @@ import org.apache.tomcat.util.log.UserDa import org.apache.tomcat.util.res.StringManager; /** - * + * * @author Costin Manolache */ public final class Parameters { @@ -53,7 +53,7 @@ public final class Parameters { new HashMap<String,ArrayList<String>>(); private boolean didQueryParameters=false; - + MessageBytes queryMB; UDecoder urlDec; @@ -61,15 +61,15 @@ public final class Parameters { String encoding=null; String queryStringEncoding=null; - + private int limit = -1; private int parameterCount = 0; /** - * Is set to <code>true</code> if there were failures during parameter - * parsing. + * Set to the reason for the failure (the first failure if there is more + * than one) if there were failures during parameter parsing. */ - private boolean parseFailed = false; + private FailReason parseFailedReason = null; public Parameters() { // NO-OP @@ -102,11 +102,17 @@ public final class Parameters { } public boolean isParseFailed() { - return parseFailed; + return parseFailedReason != null; } - public void setParseFailed(boolean parseFailed) { - this.parseFailed = parseFailed; + public FailReason getParseFailedReason() { + return parseFailedReason; + } + + public void setParseFailedReason(FailReason failReason) { + if (this.parseFailedReason == null) { + this.parseFailedReason = failReason; + } } public void recycle() { @@ -115,13 +121,13 @@ public final class Parameters { didQueryParameters=false; encoding=null; decodedQuery.recycle(); - parseFailed = false; + parseFailedReason = null; } // -------------------- Data access -------------------- // Access to the current name/values, no side effect ( processing ). // You must explicitly call handleQueryParameters and the post methods. - + public void addParameterValues(String key, String[] newValues) { if (key == null) { return; @@ -147,7 +153,7 @@ public final class Parameters { } return values.toArray(new String[values.size()]); } - + public Enumeration<String> getParameterNames() { handleQueryParameters(); return Collections.enumeration(paramHashValues.keySet()); @@ -176,7 +182,7 @@ public final class Parameters { if( queryMB==null || queryMB.isNull() ) return; - + if(log.isDebugEnabled()) { log.debug("Decoding query " + decodedQuery + " " + queryStringEncoding); @@ -216,15 +222,15 @@ public final class Parameters { private static final String DEFAULT_ENCODING = "ISO-8859-1"; private static final Charset DEFAULT_CHARSET = Charset.forName(DEFAULT_ENCODING); - - + + public void processParameters( byte bytes[], int start, int len ) { processParameters(bytes, start, len, getCharset(encoding)); } private void processParameters(byte bytes[], int start, int len, Charset charset) { - + if(log.isDebugEnabled()) { try { log.debug(sm.getString("parameters.bytes", @@ -235,7 +241,7 @@ public final class Parameters { } int decodeFailCount = 0; - + int pos = start; int end = start + len; @@ -243,7 +249,7 @@ public final class Parameters { parameterCount ++; if (limit > -1 && parameterCount > limit) { - parseFailed = true; + setParseFailedReason(FailReason.TOO_MANY_PARAMETERS); UserDataHelper.Mode logMode = maxParamCountLog.getNextMode(); if (logMode != null) { String message = sm.getString("parameters.maxCountFail", @@ -319,7 +325,7 @@ public final class Parameters { valueEnd = pos; } } - + if (log.isDebugEnabled() && valueStart == -1) { try { log.debug(sm.getString("parameters.noequal", @@ -331,7 +337,7 @@ public final class Parameters { // Not possible. All JVMs must support ISO-8859-1 } } - + if (nameEnd <= nameStart ) { if (valueStart == -1) { // && @@ -370,11 +376,11 @@ public final class Parameters { log.debug(message); } } - parseFailed = true; + setParseFailedReason(FailReason.NO_NAME); continue; // invalid chunk - it's better to ignore } - + tmpName.setBytes(bytes, nameStart, nameEnd - nameStart); if (valueStart >= 0) { tmpValue.setBytes(bytes, valueStart, valueEnd - valueStart); @@ -398,7 +404,7 @@ public final class Parameters { log.error(sm.getString("parameters.copyFail"), ioe); } } - + try { String name; String value; @@ -421,7 +427,7 @@ public final class Parameters { addParam(name, value); } catch (IOException e) { - parseFailed = true; + setParseFailedReason(FailReason.URL_DECODING); decodeFailCount++; if (decodeFailCount == 1 || log.isDebugEnabled()) { if (log.isDebugEnabled()) { @@ -480,7 +486,7 @@ public final class Parameters { private void urlDecode(ByteChunk bc) throws IOException { if( urlDec==null ) { - urlDec=new UDecoder(); + urlDec=new UDecoder(); } urlDec.convert(bc); } @@ -507,7 +513,7 @@ public final class Parameters { } } - /** + /** * Debug purpose */ public String paramsAsString() { @@ -523,4 +529,17 @@ public final class Parameters { return sb.toString(); } + + public enum FailReason { + CLIENT_DISCONNECT, + MULTIPART_CONFIG_INVALID, + INVALID_CONTENT_TYPE, + IO_ERROR, + NO_NAME, + POST_TOO_LARGE, + REQUEST_BODY_INCOMPLETE, + TOO_MANY_PARAMETERS, + UNKNOWN, + URL_DECODING + } } Modified: tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml?rev=1712277&r1=1712276&r2=1712277&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Tue Nov 3 12:33:42 2015 @@ -60,6 +60,11 @@ system property. (kkolinko) </fix> <fix> + <bug>58031</bug>: Make the (first) reason parameter parsing failed + available as a request attribute and then use it to provide a better + status code via the FailedRequstFilter (if configured). (markt) + </fix> + <fix> <bug>58313</bug>: Fix concurrent access of encoders map when clearing encoders during Comet processing. (markt) </fix> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org