You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by hi...@apache.org on 2010/09/15 09:23:14 UTC
svn commit: r997212 - in
/harmony/enhanced/java/trunk/classlib/modules/luni/src:
main/java/org/apache/harmony/luni/util/FloatingPointParser.java
test/api/common/org/apache/harmony/luni/tests/java/lang/FloatTest.java
Author: hindessm
Date: Wed Sep 15 07:23:14 2010
New Revision: 997212
URL: http://svn.apache.org/viewvc?rev=997212&view=rev
Log:
Apply modified patch from "[#HARMONY-6641] [classlib][luni] FloatParser returns wrong value and uses 1GB memory and 100% cpu".
Modified:
harmony/enhanced/java/trunk/classlib/modules/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java
harmony/enhanced/java/trunk/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/lang/FloatTest.java
Modified: harmony/enhanced/java/trunk/classlib/modules/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/java/trunk/classlib/modules/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java?rev=997212&r1=997211&r2=997212&view=diff
==============================================================================
--- harmony/enhanced/java/trunk/classlib/modules/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java (original)
+++ harmony/enhanced/java/trunk/classlib/modules/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java Wed Sep 15 07:23:14 2010
@@ -23,6 +23,16 @@ package org.apache.harmony.luni.util;
* floating point number.
*/
public final class FloatingPointParser {
+ /*
+ * All number with exponent larger than MAX_EXP can be treated as infinity.
+ * All number with exponent smaller than MIN_EXP can be treated as zero.
+ * Exponent is 10 based.
+ * Eg. double's min value is 5e-324, so double "1e-325" should be parsed as 0.0
+ */
+ private static final int FLOAT_MIN_EXP = -46;
+ private static final int FLOAT_MAX_EXP = 38;
+ private static final int DOUBLE_MIN_EXP = -324;
+ private static final int DOUBLE_MAX_EXP = 308;
private static final class StringExponentPair {
String s;
@@ -94,7 +104,7 @@ public final class FloatingPointParser {
private static StringExponentPair initialParse(String s, int length) {
boolean negative = false;
char c;
- int start, end, decimal;
+ int start, end, decimal, shift;
int e = 0;
start = 0;
@@ -119,17 +129,31 @@ public final class FloatingPointParser {
throw new NumberFormatException(s);
}
exponent_offset++; // skip the plus sign
+ if (exponent_offset == length)
+ throw new NumberFormatException(s);
}
+ String strExp = s.substring(exponent_offset, length);
try {
- e = Integer.parseInt(s.substring(exponent_offset,
- length));
- } catch (NumberFormatException ex) {
- // ex contains the exponent substring
- // only so throw a new exception with
- // the correct string
- throw new NumberFormatException(s);
- }
-
+ e = Integer.parseInt(strExp);
+ } catch (NumberFormatException ex) {
+ // strExp is not empty, so there are 2 situations the exception be thrown
+ // if the string is invalid we should throw exception, if the actual number
+ // is out of the range of Integer, we can still parse the original number to
+ // double or float
+ char ch;
+ for (int i = 0; i < strExp.length(); i++) {
+ ch = strExp.charAt(i);
+ if (ch < '0' || ch > '9') {
+ if (i == 0 && ch == '-')
+ continue;
+ // ex contains the exponent substring
+ // only so throw a new exception with
+ // the correct string
+ throw new NumberFormatException(s);
+ }
+ }
+ e = strExp.charAt(0) == '-' ? Integer.MIN_VALUE : Integer.MAX_VALUE;
+ }
} else {
end = length;
}
@@ -150,7 +174,11 @@ public final class FloatingPointParser {
decimal = s.indexOf('.');
if (decimal > -1) {
- e -= end - decimal - 1;
+ shift = end - decimal - 1;
+ //prevent e overflow, shift >= 0
+ if (e >= 0 || e - Integer.MIN_VALUE > shift) {
+ e -= shift;
+ }
s = s.substring(start, decimal) + s.substring(decimal + 1, end);
} else {
s = s.substring(start, end);
@@ -168,7 +196,10 @@ public final class FloatingPointParser {
start++;
if (end != length || start != 0) {
- e += length - end;
+ shift = length - end;
+ if (e <= 0 || Integer.MAX_VALUE - e > shift) {
+ e += shift;
+ }
s = s.substring(start, end);
}
@@ -208,7 +239,7 @@ public final class FloatingPointParser {
if (namedDouble.regionMatches(false, cmpstart, "Infinity", 0, 8)) {
return negative ? Double.NEGATIVE_INFINITY
- : Float.POSITIVE_INFINITY;
+ : Double.POSITIVE_INFINITY;
}
if (namedDouble.regionMatches(false, cmpstart, "NaN", 0, 3)) {
@@ -280,6 +311,17 @@ public final class FloatingPointParser {
StringExponentPair info = initialParse(s, length);
+ // two kinds of situation will directly return 0.0
+ // 1. info.s is 0
+ // 2. actual exponent is less than Double.MIN_EXPONENT
+ if ("0".equals(info.s) || (info.e + info.s.length() - 1 < DOUBLE_MIN_EXP)) {
+ return info.negative ? -0.0 : 0.0;
+ }
+ // if actual exponent is larger than Double.MAX_EXPONENT, return infinity
+ // prevent overflow, check twice
+ if ((info.e > DOUBLE_MAX_EXP) || (info.e + info.s.length() - 1 > DOUBLE_MAX_EXP)) {
+ return info.negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+ }
double result = parseDblImpl(info.s, info.e);
if (info.negative)
result = -result;
@@ -318,6 +360,17 @@ public final class FloatingPointParser {
StringExponentPair info = initialParse(s, length);
+ // two kinds of situation will directly return 0.0f
+ // 1. info.s is 0
+ // 2. actual exponent is less than Float.MIN_EXPONENT
+ if ("0".equals(info.s) || (info.e + info.s.length() - 1 < FLOAT_MIN_EXP)) {
+ return info.negative ? -0.0f : 0.0f;
+ }
+ // if actual exponent is larger than Float.MAX_EXPONENT, return infinity
+ // prevent overflow, check twice
+ if ((info.e > FLOAT_MAX_EXP) || (info.e + info.s.length() - 1 > FLOAT_MAX_EXP)) {
+ return info.negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
+ }
float result = parseFltImpl(info.s, info.e);
if (info.negative)
result = -result;
Modified: harmony/enhanced/java/trunk/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/lang/FloatTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/java/trunk/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/lang/FloatTest.java?rev=997212&r1=997211&r2=997212&view=diff
==============================================================================
--- harmony/enhanced/java/trunk/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/lang/FloatTest.java (original)
+++ harmony/enhanced/java/trunk/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/lang/FloatTest.java Wed Sep 15 07:23:14 2010
@@ -904,6 +904,13 @@ public class FloatTest extends TestCase
Float negInfiniteSigned = Float.valueOf("-Infinity");
assertTrue("Floattest7", negInfiniteSigned.equals(new Float(Float.NEGATIVE_INFINITY)));
+
+ // test HARMONY-6641
+ posInfinite = Float.valueOf("320.0E+2147483647");
+ assertEquals("Floattest8", Float.POSITIVE_INFINITY, posInfinite);
+
+ negZero = Float.valueOf("-1.4E-2147483314");
+ assertEquals("Floattest9", -0.0f, negZero);
}
private void test_toString(float ff, String answer) {