Return-Path: X-Original-To: apmail-tomcat-dev-archive@www.apache.org Delivered-To: apmail-tomcat-dev-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 0E017107B1 for ; Wed, 26 Mar 2014 18:54:11 +0000 (UTC) Received: (qmail 51185 invoked by uid 500); 26 Mar 2014 18:54:06 -0000 Delivered-To: apmail-tomcat-dev-archive@tomcat.apache.org Received: (qmail 50647 invoked by uid 500); 26 Mar 2014 18:54:04 -0000 Mailing-List: contact dev-help@tomcat.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "Tomcat Developers List" Delivered-To: mailing list dev@tomcat.apache.org Received: (qmail 50637 invoked by uid 99); 26 Mar 2014 18:54:03 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 26 Mar 2014 18:54:03 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 26 Mar 2014 18:53:59 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 082DB2388860 for ; Wed, 26 Mar 2014 18:53:37 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1582010 - in /tomcat/tc7.0.x/trunk: ./ java/org/apache/tomcat/util/buf/Utf8Decoder.java test/org/apache/tomcat/util/buf/TestUtf8.java webapps/docs/changelog.xml Date: Wed, 26 Mar 2014 18:53:36 -0000 To: dev@tomcat.apache.org From: markt@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20140326185337.082DB2388860@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: markt Date: Wed Mar 26 18:53:36 2014 New Revision: 1582010 URL: http://svn.apache.org/r1582010 Log: Fix custom UTF-8 decoder so that a byte of value 0xC1 is always rejected immediately as it is never valid in a UTF-8 byte sequence. Update UTF-8 decoder tests to account for UTF-8 decoding improvements in Java 8. The custom UTF-8 decoder is still required due to bugs in the UTF-8 decoder provided by Java. Java 8's decoder is better than Java 7's but it is still buggy. Modified: tomcat/tc7.0.x/trunk/ (props changed) tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/buf/Utf8Decoder.java tomcat/tc7.0.x/trunk/test/org/apache/tomcat/util/buf/TestUtf8.java tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Propchange: tomcat/tc7.0.x/trunk/ ------------------------------------------------------------------------------ Merged /tomcat/trunk:r1582009 Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/buf/Utf8Decoder.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/buf/Utf8Decoder.java?rev=1582010&r1=1582009&r2=1582010&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/buf/Utf8Decoder.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/buf/Utf8Decoder.java Wed Mar 26 18:53:36 2014 @@ -49,7 +49,7 @@ public class Utf8Decoder extends Charset -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 11oyyyyy - -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 111ozzzz 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, Modified: tomcat/tc7.0.x/trunk/test/org/apache/tomcat/util/buf/TestUtf8.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/tomcat/util/buf/TestUtf8.java?rev=1582010&r1=1582009&r2=1582010&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/test/org/apache/tomcat/util/buf/TestUtf8.java (original) +++ tomcat/tc7.0.x/trunk/test/org/apache/tomcat/util/buf/TestUtf8.java Wed Mar 26 18:53:36 2014 @@ -57,7 +57,21 @@ public class TestUtf8 { public static final List TEST_CASES = new ArrayList(); + private static int workAroundCount = 0; + static { + // Future proof test and assume some UTF-8 bugs won't get fixed until + // Java 9 or later + // Base assumption in Java 7 + int javaVersion = 7; + try { + Class.forName("java.util.stream.Collector"); + javaVersion = 8; + } catch (Exception e) { + // Ignore + } + Utf8TestCase testCase = null; + TEST_CASES.add(new Utf8TestCase( "Zero length input", new int[] {}, @@ -89,18 +103,29 @@ public class TestUtf8 { new int[] {0x41, 0xF4, 0x90, 0x80, 0x80, 0x41}, 2, "A\uFFFD\uFFFD\uFFFD\uFFFDA").addForJvm(ERROR_POS_PLUS2)); - // JVM decoder does not report error until all 2 bytes are available - TEST_CASES.add(new Utf8TestCase( + + // Java 7 JVM decoder does not report error until all 2 bytes are available + testCase = new Utf8TestCase( "Valid sequence padded from one byte to two", new int[] {0x41, 0xC0, 0xC1, 0x41}, 1, - "A\uFFFD\uFFFDA").addForJvm(ERROR_POS_PLUS1)); - // JVM decoder does not report error until all 3 bytes are available - TEST_CASES.add(new Utf8TestCase( + "A\uFFFD\uFFFDA"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS1); + } + TEST_CASES.add(testCase); + + // Java 7 JVM decoder does not report error until all 3 bytes are available + testCase = new Utf8TestCase( "Valid sequence padded from one byte to three", new int[] {0x41, 0xE0, 0x80, 0xC1, 0x41}, 2, - "A\uFFFD\uFFFD\uFFFDA").addForJvm(ERROR_POS_PLUS1)); + "A\uFFFD\uFFFD\uFFFDA"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS1); + } + TEST_CASES.add(testCase); + // JVM decoder does not report error until all 4 bytes are available TEST_CASES.add(new Utf8TestCase( "Valid sequence padded from one byte to four", @@ -112,21 +137,37 @@ public class TestUtf8 { new int[] {0x41, 0xFF, 0x41}, 1, "A\uFFFDA")); - TEST_CASES.add(new Utf8TestCase( + + testCase = new Utf8TestCase( "Invalid one byte 1111 0000", new int[] {0x41, 0xF0, 0x41}, 2, - "A\uFFFDA").addForJvm(REPLACE_SWALLOWS_TRAILER)); - TEST_CASES.add(new Utf8TestCase( + "A\uFFFDA"); + if (javaVersion < 8) { + testCase.addForJvm(REPLACE_SWALLOWS_TRAILER); + } + TEST_CASES.add(testCase); + + testCase = new Utf8TestCase( "Invalid one byte 1110 0000", new int[] {0x41, 0xE0, 0x41}, 2, - "A\uFFFDA").addForJvm(REPLACE_SWALLOWS_TRAILER)); - TEST_CASES.add(new Utf8TestCase( + "A\uFFFDA"); + if (javaVersion < 8) { + testCase.addForJvm(REPLACE_SWALLOWS_TRAILER); + } + TEST_CASES.add(testCase); + + testCase = new Utf8TestCase( "Invalid one byte 1100 0000", new int[] {0x41, 0xC0, 0x41}, 1, - "A\uFFFDA").addForJvm(ERROR_POS_PLUS1)); + "A\uFFFDA"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS1); + } + TEST_CASES.add(testCase); + TEST_CASES.add(new Utf8TestCase( "Invalid one byte 1000 000", new int[] {0x41, 0x80, 0x41}, @@ -158,36 +199,63 @@ public class TestUtf8 { new int[] {0x61, 0xF0, 0x90, 0x90, 0x61}, 4, "a\uFFFDa")); - TEST_CASES.add(new Utf8TestCase( + + testCase = new Utf8TestCase( "Valid 4-byte sequence truncated to 2 bytes with trailer", new int[] {0x61, 0xF0, 0x90, 0x61}, 3, - "a\uFFFDa").addForJvm(REPLACE_SWALLOWS_TRAILER)); - TEST_CASES.add(new Utf8TestCase( + "a\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(REPLACE_SWALLOWS_TRAILER); + } + TEST_CASES.add(testCase); + + testCase = new Utf8TestCase( "Valid 4-byte sequence truncated to 1 byte with trailer", new int[] {0x61, 0xF0, 0x61}, 2, - "a\uFFFDa").addForJvm(REPLACE_SWALLOWS_TRAILER)); - TEST_CASES.add(new Utf8TestCase( + "a\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(REPLACE_SWALLOWS_TRAILER); + } + TEST_CASES.add(testCase); + + testCase = new Utf8TestCase( "U+0000 zero-padded to two bytes", new int[] {0x61, 0xC0, 0x80, 0x61}, 1, - "a\uFFFD\uFFFDa").addForJvm(ERROR_POS_PLUS1)); - TEST_CASES.add(new Utf8TestCase( + "a\uFFFD\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS1); + } + TEST_CASES.add(testCase); + + testCase = new Utf8TestCase( "U+007F zero-padded to two bytes", new int[] {0x61, 0xC1, 0xBF, 0x61}, - 2, - "a\uFFFD\uFFFDa")); + 1, + "a\uFFFD\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS1); + } + TEST_CASES.add(testCase); + TEST_CASES.add(new Utf8TestCase( "Two bytes, all 1's", new int[] {0x61, 0xFF, 0xFF, 0x61}, 1, "a\uFFFD\uFFFDa")); - TEST_CASES.add(new Utf8TestCase( + + testCase = new Utf8TestCase( "Two bytes, 1110 first byte first nibble", new int[] {0x61, 0xE0, 0x80, 0x61}, 2, - "a\uFFFD\uFFFDa").addForJvm(ERROR_POS_PLUS1)); + "a\uFFFD\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS1); + } + TEST_CASES.add(testCase); + TEST_CASES.add(new Utf8TestCase( "Two bytes, 101x first byte first nibble", new int[] {0x61, 0xA0, 0x80, 0x61}, @@ -203,37 +271,64 @@ public class TestUtf8 { new int[] {0x61, 0xC2, 0xC0, 0x61}, 2, "a\uFFFD\uFFFDa")); - TEST_CASES.add(new Utf8TestCase( + + testCase = new Utf8TestCase( "Three bytes, U+0000 zero-padded", new int[] {0x61, 0xE0, 0x80, 0x80, 0x61}, 2, - "a\uFFFD\uFFFD\uFFFDa").addForJvm(ERROR_POS_PLUS1)); - TEST_CASES.add(new Utf8TestCase( + "a\uFFFD\uFFFD\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS1); + } + TEST_CASES.add(testCase); + + testCase = new Utf8TestCase( "Three bytes, U+007F zero-padded", new int[] {0x61, 0xE0, 0x81, 0xBF, 0x61}, 2, - "a\uFFFD\uFFFD\uFFFDa").addForJvm(ERROR_POS_PLUS1)); - TEST_CASES.add(new Utf8TestCase( + "a\uFFFD\uFFFD\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS1); + } + TEST_CASES.add(testCase); + + testCase = new Utf8TestCase( "Three bytes, U+07FF zero-padded", new int[] {0x61, 0xE0, 0x9F, 0xBF, 0x61}, 2, - "a\uFFFD\uFFFD\uFFFDa").addForJvm(ERROR_POS_PLUS1)); + "a\uFFFD\uFFFD\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS1); + } + TEST_CASES.add(testCase); + TEST_CASES.add(new Utf8TestCase( "Three bytes, all 1's", new int[] {0x61, 0xFF, 0xFF, 0xFF, 0x61}, 1, "a\uFFFD\uFFFD\uFFFDa")); - TEST_CASES.add(new Utf8TestCase( + + testCase = new Utf8TestCase( "Three bytes, invalid first byte", new int[] {0x61, 0xF8, 0x80, 0x80, 0x61}, 1, - "a\uFFFD\uFFFD\uFFFDa").addForJvm( - REPLACE_SWALLOWS_TRAILER).addForJvm(REPLACE_MISSING2)); - TEST_CASES.add(new Utf8TestCase( + "a\uFFFD\uFFFD\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(REPLACE_MISSING2).addForJvm( + REPLACE_SWALLOWS_TRAILER); + } + TEST_CASES.add(testCase); + + testCase = new Utf8TestCase( "Three bytes, invalid second byte", new int[] {0x61, 0xE0, 0xC0, 0x80, 0x61}, 2, - "a\uFFFD\uFFFD\uFFFDa").addForJvm(ERROR_POS_PLUS1)); + "a\uFFFD\uFFFD\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS1); + } + TEST_CASES.add(testCase); + TEST_CASES.add(new Utf8TestCase( "Three bytes, invalid third byte", new int[] {0x61, 0xE1, 0x80, 0xC0, 0x61}, @@ -264,92 +359,143 @@ public class TestUtf8 { new int[] {0x61, 0xFF, 0xFF, 0xFF, 0xFF, 0x61}, 1, "a\uFFFD\uFFFD\uFFFD\uFFFDa")); - TEST_CASES.add(new Utf8TestCase( + + testCase = new Utf8TestCase( "Four bytes, invalid first byte", new int[] {0x61, 0xF8, 0x80, 0x80, 0x80, 0x61}, 1, - "a\uFFFD\uFFFD\uFFFD\uFFFDa").addForJvm( - ERROR_POS_PLUS4).addForJvm( - REPLACE_MISSING2).addForJvm(REPLACE_MISSING1)); - TEST_CASES.add(new Utf8TestCase( + "a\uFFFD\uFFFD\uFFFD\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS4).addForJvm( + REPLACE_MISSING2).addForJvm(REPLACE_MISSING1); + } + TEST_CASES.add(testCase); + + testCase = new Utf8TestCase( "Four bytes, invalid second byte", new int[] {0x61, 0xF1, 0xC0, 0x80, 0x80, 0x61}, 2, - "a\uFFFD\uFFFD\uFFFD\uFFFDa").addForJvm(ERROR_POS_PLUS2)); - TEST_CASES.add(new Utf8TestCase( + "a\uFFFD\uFFFD\uFFFD\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS2); + } + TEST_CASES.add(testCase); + + testCase = new Utf8TestCase( "Four bytes, invalid third byte", new int[] {0x61, 0xF1, 0x80, 0xC0, 0x80, 0x61}, 3, - "a\uFFFD\uFFFD\uFFFDa").addForJvm(ERROR_POS_PLUS1)); + "a\uFFFD\uFFFD\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS1); + } + TEST_CASES.add(testCase); + TEST_CASES.add(new Utf8TestCase( "Four bytes, invalid fourth byte", new int[] {0x61, 0xF1, 0x80, 0x80, 0xC0, 0x61}, 4, "a\uFFFD\uFFFDa")); - TEST_CASES.add(new Utf8TestCase( + + testCase = new Utf8TestCase( "Five bytes, U+0000 zero padded", new int[] {0x61, 0xF8, 0x80, 0x80, 0x80, 0x80, 0x61}, 1, - "a\uFFFD\uFFFD\uFFFD\uFFFD\uFFFDa").addForJvm( - ERROR_POS_PLUS4).addForJvm(REPLACE_MISSING4)); - TEST_CASES.add(new Utf8TestCase( + "a\uFFFD\uFFFD\uFFFD\uFFFD\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS4).addForJvm(REPLACE_MISSING4); + } + TEST_CASES.add(testCase); + + testCase = new Utf8TestCase( "Five bytes, U+007F zero padded", new int[] {0x61, 0xF8, 0x80, 0x80, 0x81, 0xBF, 0x61}, 1, - "a\uFFFD\uFFFD\uFFFD\uFFFD\uFFFDa").addForJvm( - ERROR_POS_PLUS4).addForJvm(REPLACE_MISSING4)); - TEST_CASES.add(new Utf8TestCase( + "a\uFFFD\uFFFD\uFFFD\uFFFD\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS4).addForJvm(REPLACE_MISSING4); + } + TEST_CASES.add(testCase); + + testCase = new Utf8TestCase( "Five bytes, U+07FF zero padded", new int[] {0x61, 0xF8, 0x80, 0x80, 0x9F, 0xBF, 0x61}, 1, - "a\uFFFD\uFFFD\uFFFD\uFFFD\uFFFDa").addForJvm( - ERROR_POS_PLUS4).addForJvm(REPLACE_MISSING4)); - TEST_CASES.add(new Utf8TestCase( + "a\uFFFD\uFFFD\uFFFD\uFFFD\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS4).addForJvm(REPLACE_MISSING4); + } + TEST_CASES.add(testCase); + + testCase = new Utf8TestCase( "Five bytes, U+FFFF zero padded", new int[] {0x61, 0xF8, 0x80, 0x8F, 0xBF, 0xBF, 0x61}, 1, - "a\uFFFD\uFFFD\uFFFD\uFFFD\uFFFDa").addForJvm( - ERROR_POS_PLUS4).addForJvm(REPLACE_MISSING4)); - TEST_CASES.add(new Utf8TestCase( + "a\uFFFD\uFFFD\uFFFD\uFFFD\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS4).addForJvm(REPLACE_MISSING4); + } + TEST_CASES.add(testCase); + + testCase = new Utf8TestCase( "Six bytes, U+0000 zero padded", new int[] {0x61, 0xFC, 0x80, 0x80, 0x80, 0x80, 0x80, 0x61}, 1, - "a\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFDa").addForJvm( - ERROR_POS_PLUS4).addForJvm( - ERROR_POS_PLUS1).addForJvm( - REPLACE_MISSING4).addForJvm(REPLACE_MISSING1)); - TEST_CASES.add(new Utf8TestCase( + "a\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS4).addForJvm( + ERROR_POS_PLUS1).addForJvm(REPLACE_MISSING4).addForJvm( + REPLACE_MISSING1); + } + TEST_CASES.add(testCase); + + testCase = new Utf8TestCase( "Six bytes, U+007F zero padded", new int[] {0x61, 0xFC, 0x80, 0x80, 0x80, 0x81, 0xBF, 0x61}, 1, - "a\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFDa").addForJvm( - ERROR_POS_PLUS4).addForJvm( - ERROR_POS_PLUS1).addForJvm( - REPLACE_MISSING4).addForJvm(REPLACE_MISSING1)); - TEST_CASES.add(new Utf8TestCase( + "a\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS4).addForJvm( + ERROR_POS_PLUS1).addForJvm(REPLACE_MISSING4).addForJvm( + REPLACE_MISSING1); + } + TEST_CASES.add(testCase); + + testCase = new Utf8TestCase( "Six bytes, U+07FF zero padded", new int[] {0x61, 0xFC, 0x80, 0x80, 0x80, 0x9F, 0xBF, 0x61}, 1, - "a\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFDa").addForJvm( - ERROR_POS_PLUS4).addForJvm( - ERROR_POS_PLUS1).addForJvm( - REPLACE_MISSING4).addForJvm(REPLACE_MISSING1)); - TEST_CASES.add(new Utf8TestCase( + "a\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS4).addForJvm( + ERROR_POS_PLUS1).addForJvm(REPLACE_MISSING4).addForJvm( + REPLACE_MISSING1); + } + TEST_CASES.add(testCase); + + testCase = new Utf8TestCase( "Six bytes, U+FFFF zero padded", new int[] {0x61, 0xFC, 0x80, 0x80, 0x8F, 0xBF, 0xBF, 0x61}, 1, - "a\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFDa").addForJvm( - ERROR_POS_PLUS4).addForJvm( - ERROR_POS_PLUS1).addForJvm( - REPLACE_MISSING4).addForJvm(REPLACE_MISSING1)); - TEST_CASES.add(new Utf8TestCase( + "a\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFDa"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS4).addForJvm( + ERROR_POS_PLUS1).addForJvm(REPLACE_MISSING4).addForJvm( + REPLACE_MISSING1); + } + TEST_CASES.add(testCase); + + testCase = new Utf8TestCase( "Original test case - derived from Autobahn?", new int[] {0xCE, 0xBA, 0xE1, 0xDB, 0xB9, 0xCF, 0x83, 0xCE, 0xBC, 0xCE, 0xB5, 0xED, 0x80, 0x65, 0x64, 0x69, 0x74, 0x65, 0x64}, 3, - "\u03BA\uFFFD\u06F9\u03C3\u03BC\u03B5\uFFFDedited").addForJvm( - ERROR_POS_PLUS1)); + "\u03BA\uFFFD\u06F9\u03C3\u03BC\u03B5\uFFFDedited"); + if (javaVersion < 8) { + testCase.addForJvm(ERROR_POS_PLUS1); + } + TEST_CASES.add(testCase); } @Test @@ -364,8 +510,20 @@ public class TestUtf8 { @Test public void testJvmDecoder() { CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder(); - for (Utf8TestCase testCase : TEST_CASES) { - doTest(decoder, testCase, testCase.flagsJvm); + int testCount = 0; + try { + for (Utf8TestCase testCase : TEST_CASES) { + doTest(decoder, testCase, testCase.flagsJvm); + testCount++; + } + } finally { + System.err.println("Workarounds added to " + workAroundCount + + " tests to account for known JVM bugs"); + if (testCount < TEST_CASES.size()) { + System.err.println("Executed " + testCount + " of " + + TEST_CASES.size() + " UTF-8 tests before " + + "encountering a failure"); + } } } @@ -475,6 +633,9 @@ public class TestUtf8 { } public Utf8TestCase addForJvm(int flag) { + if (this.flagsJvm == 0) { + TestUtf8.workAroundCount++; + } this.flagsJvm = this.flagsJvm | flag; return this; } Modified: tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml?rev=1582010&r1=1582009&r2=1582010&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Wed Mar 26 18:53:36 2014 @@ -55,6 +55,20 @@ They eventually become mixed with the numbered issues. (I.e., numbered issues to not "pop up" wrt. others). --> +
+ + + + Fix custom UTF-8 decoder so that a byte of value 0xC1 is always rejected + immediately as it is never valid in a UTF-8 byte sequence. Update UTF-8 + decoder tests to account for UTF-8 decoding improvements in Java 8. + The custom UTF-8 decoder is still required due to bugs in the UTF-8 + decoder provided by Java. Java 8's decoder is better than Java + 7's but it is still buggy. (markt) + + + +
--------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org For additional commands, e-mail: dev-help@tomcat.apache.org