Author: markt
Date: Sat Mar  2 22:04:46 2013
New Revision: 1451947

URL: http://svn.apache.org/r1451947
Log:
Remove fall back to 'ASCII' (really ISO-8859-1)
Replace partial / invalid byte sequences rather than trigger an error (allows 
application to handle the resulting 404)

Modified:
    tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
    tomcat/trunk/java/org/apache/tomcat/util/buf/B2CConverter.java
    tomcat/trunk/test/org/apache/catalina/connector/TestCoyoteAdapter.java

Modified: tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java?rev=1451947&r1=1451946&r2=1451947&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java Sat Mar  
2 22:04:46 2013
@@ -23,6 +23,7 @@ import java.util.EnumSet;
 
 import javax.servlet.RequestDispatcher;
 import javax.servlet.SessionTrackingMode;
+import javax.servlet.http.HttpServletResponse;
 
 import org.apache.catalina.Context;
 import org.apache.catalina.Host;
@@ -1034,30 +1035,30 @@ public class CoyoteAdapter implements Ad
             B2CConverter conv = request.getURIConverter();
             try {
                 if (conv == null) {
-                    conv = new B2CConverter(enc);
+                    conv = new B2CConverter(enc, true);
                     request.setURIConverter(conv);
                 } else {
                     conv.recycle();
                 }
             } catch (IOException e) {
-                // Ignore
                 log.error("Invalid URI encoding; using HTTP default");
                 connector.setURIEncoding(null);
             }
             if (conv != null) {
                 try {
                     conv.convert(bc, cc, true);
-                    uri.setChars(cc.getBuffer(), cc.getStart(),
-                                 cc.getLength());
+                    uri.setChars(cc.getBuffer(), cc.getStart(), 
cc.getLength());
                     return;
-                } catch (IOException e) {
-                    log.error("Invalid URI character encoding; trying ascii");
-                    cc.recycle();
+                } catch (IOException ioe) {
+                    // Should never happen as B2CConverter should replace
+                    // problematic characters
+                    request.getResponse().sendError(
+                            HttpServletResponse.SC_BAD_REQUEST);
                 }
             }
         }
 
-        // Default encoding: fast conversion
+        // Default encoding: fast conversion for ISO-8859-1
         byte[] bbuf = bc.getBuffer();
         char[] cbuf = cc.getBuffer();
         int start = bc.getStart();
@@ -1065,7 +1066,6 @@ public class CoyoteAdapter implements Ad
             cbuf[i] = (char) (bbuf[i + start] & 0xff);
         }
         uri.setChars(cbuf, 0, length);
-
     }
 
 

Modified: tomcat/trunk/java/org/apache/tomcat/util/buf/B2CConverter.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/buf/B2CConverter.java?rev=1451947&r1=1451946&r2=1451947&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/buf/B2CConverter.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/buf/B2CConverter.java Sat Mar  2 
22:04:46 2013
@@ -23,6 +23,7 @@ import java.nio.CharBuffer;
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
@@ -103,9 +104,22 @@ public class B2CConverter {
     private final ByteBuffer leftovers;
 
     public B2CConverter(String encoding) throws IOException {
+        this(encoding, false);
+    }
+
+    public B2CConverter(String encoding, boolean replaceOnError)
+            throws IOException {
         byte[] left = new byte[LEFTOVER_SIZE];
         leftovers = ByteBuffer.wrap(left);
+        CodingErrorAction action;
+        if (replaceOnError) {
+            action = CodingErrorAction.REPLACE;
+        } else {
+            action = CodingErrorAction.REPORT;
+        }
         decoder = getCharset(encoding).newDecoder();
+        decoder.onMalformedInput(action);
+        decoder.onUnmappableCharacter(action);
     }
 
     /**

Modified: tomcat/trunk/test/org/apache/catalina/connector/TestCoyoteAdapter.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/connector/TestCoyoteAdapter.java?rev=1451947&r1=1451946&r2=1451947&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/connector/TestCoyoteAdapter.java 
(original)
+++ tomcat/trunk/test/org/apache/catalina/connector/TestCoyoteAdapter.java Sat 
Mar  2 22:04:46 2013
@@ -25,9 +25,7 @@ import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
+import org.junit.Assert;
 import org.junit.Test;
 
 import org.apache.catalina.Context;
@@ -89,7 +87,7 @@ public class TestCoyoteAdapter extends T
         File foo = new File(docBase, "foo");
         addDeleteOnTearDown(foo);
         if (!foo.mkdirs() && !foo.isDirectory()) {
-            fail("Unable to create foo directory in docBase");
+            Assert.fail("Unable to create foo directory in docBase");
         }
 
         Context ctx = tomcat.addContext("", docBase.getAbsolutePath());
@@ -122,12 +120,12 @@ public class TestCoyoteAdapter extends T
         tomcat.start();
 
         ByteChunk res = getUrl("http://localhost:"; + getPort() + path);
-        assertEquals(expected, res.toString());
+        Assert.assertEquals(expected, res.toString());
     }
 
     private void testPath(String path, String expected) throws Exception {
         ByteChunk res = getUrl("http://localhost:"; + getPort() + path);
-        assertEquals(expected, res.toString());
+        Assert.assertEquals(expected, res.toString());
     }
 
     private static class PathParamServlet extends HttpServlet {
@@ -176,6 +174,68 @@ public class TestCoyoteAdapter extends T
         tomcat.start();
 
         ByteChunk res = getUrl("http://localhost:"; + getPort() + path);
-        assertEquals(expected, res.toString());
+        Assert.assertEquals(expected, res.toString());
+    }
+
+    @Test
+    public void testBug54602a() throws Exception {
+        // No UTF-8
+        doTestUriDecoding("/foo", "UTF-8", "/foo");
+    }
+
+    @Test
+    public void testBug54602b() throws Exception {
+        // Valid UTF-8
+        doTestUriDecoding("/foo%c4%87", "UTF-8", "/foo\u0107");
+    }
+
+    @Test
+    public void testBug54602c() throws Exception {
+        // Partial UTF-8
+        doTestUriDecoding("/foo%c4", "UTF-8", "/foo\uFFFD");
+    }
+
+    private void doTestUriDecoding(String path, String encoding,
+            String expectedPathInfo) throws Exception{
+
+        // Setup Tomcat instance
+        Tomcat tomcat = getTomcatInstance();
+
+        tomcat.getConnector().setURIEncoding(encoding);
+
+        // Must have a real docBase - just use temp
+        Context ctx =
+            tomcat.addContext("/", System.getProperty("java.io.tmpdir"));
+
+        PathInfoServlet servlet = new PathInfoServlet();
+        Tomcat.addServlet(ctx, "servlet", servlet);
+        ctx.addServletMapping("/*", "servlet");
+
+        tomcat.start();
+
+        int rc = getUrl("http://localhost:"; + getPort() + path,
+                new ByteChunk(), null);
+        Assert.assertEquals(HttpServletResponse.SC_OK, rc);
+
+        Assert.assertEquals(expectedPathInfo, servlet.getPathInfo());
+    }
+
+    private static class PathInfoServlet extends HttpServlet {
+
+        private static final long serialVersionUID = 1L;
+
+        private String pathInfo = null;
+
+        public String getPathInfo() {
+            return pathInfo;
+        }
+
+        @Override
+        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+                throws ServletException, IOException {
+
+            // Not thread safe
+            pathInfo = req.getPathInfo();
+        }
     }
 }



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

Reply via email to