Author: markt Date: Tue Mar 18 10:27:31 2014 New Revision: 1578812 URL: http://svn.apache.org/r1578812 Log: Fix possible overflow when parsing long values from a byte array.
Added: tomcat/trunk/test/org/apache/tomcat/util/buf/TestAscii.java Modified: tomcat/trunk/java/org/apache/tomcat/util/buf/Ascii.java tomcat/trunk/webapps/docs/changelog.xml Modified: tomcat/trunk/java/org/apache/tomcat/util/buf/Ascii.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/buf/Ascii.java?rev=1578812&r1=1578811&r2=1578812&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/buf/Ascii.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/buf/Ascii.java Tue Mar 18 10:27:31 2014 @@ -33,10 +33,11 @@ public final class Ascii { */ private static final boolean[] isDigit = new boolean[256]; + private static final long OVERFLOW_LIMIT = Long.MAX_VALUE / 10; + /* * Initialize character translation and type tables. */ - static { for (int i = 0; i < 256; i++) { toLower[i] = (byte)i; @@ -85,19 +86,12 @@ public final class Ascii { } long n = c - '0'; - long m; - while (--len > 0) { - if (!isDigit(c = b[off++])) { - throw new NumberFormatException(); - } - m = n * 10 + c - '0'; - - if (m < n) { - // Overflow - throw new NumberFormatException(); + if (isDigit(c = b[off++]) && + (n < OVERFLOW_LIMIT || (n == OVERFLOW_LIMIT && (c - '0') < 8))) { + n = n * 10 + c - '0'; } else { - n = m; + throw new NumberFormatException(); } } Added: tomcat/trunk/test/org/apache/tomcat/util/buf/TestAscii.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/buf/TestAscii.java?rev=1578812&view=auto ============================================================================== --- tomcat/trunk/test/org/apache/tomcat/util/buf/TestAscii.java (added) +++ tomcat/trunk/test/org/apache/tomcat/util/buf/TestAscii.java Tue Mar 18 10:27:31 2014 @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.util.buf; + +import java.math.BigInteger; + +import org.junit.Assert; +import org.junit.Test; + +public class TestAscii { + + @Test + public void testParseLong1() { + String value = "9223372036854775807"; // Long.MAX_VALUE + byte[] bytes = value.getBytes(); + long result = Ascii.parseLong(bytes, 0, bytes.length); + Assert.assertEquals(value, String.valueOf(result)); + } + + @Test(expected = NumberFormatException.class) + public void testParseLong2() { + byte[] bytes = "9223372036854775808".getBytes(); // Long.MAX_VALUE + 1 + long result = Ascii.parseLong(bytes, 0, bytes.length); + Assert.fail("NumberFormatException expected, got: " + result); + } + + @Test(expected = NumberFormatException.class) + public void testParseLong3() { + byte[] bytes = "9223372036854775810".getBytes(); // Long.MAX_VALUE + 3 + long result = Ascii.parseLong(bytes, 0, bytes.length); + Assert.fail("NumberFormatException expected, got: " + result); + } + + @Test(expected = NumberFormatException.class) + public void testParseLong4() { + BigInteger x = BigInteger.valueOf(5000000000L).shiftLeft(32); + byte[] bytes = String.valueOf(x).getBytes(); + long result = Ascii.parseLong(bytes, 0, bytes.length); + Assert.fail("NumberFormatException expected, got: " + result); + } + + @Test + public void testParseLong5() { + String value = "9223372036854775806"; // Long.MAX_VALUE - 1 + byte[] bytes = value.getBytes(); + long result = Ascii.parseLong(bytes, 0, bytes.length); + Assert.assertEquals(value, String.valueOf(result)); + } + + +} Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1578812&r1=1578811&r2=1578812&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Tue Mar 18 10:27:31 2014 @@ -165,6 +165,10 @@ non-blocking IO support that broke handling of requests with an explicit content length of zero. (markt/kkolinko) </fix> + <fix> + Fix possible overflow when parsing long values from a byte array. + (markt) + </fix> </changelog> </subsection> <subsection name="Jasper"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org