mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Fix Double.parseDouble and Float.parseFloat for some cases of illegal input
This commit is contained in:
parent
c5334e344d
commit
1d19562c49
|
@ -77,15 +77,32 @@ public class TDouble extends TNumber implements TComparable<TDouble> {
|
||||||
|
|
||||||
public static double parseDouble(TString string) throws TNumberFormatException {
|
public static double parseDouble(TString string) throws TNumberFormatException {
|
||||||
// TODO: parse infinite and different radix
|
// TODO: parse infinite and different radix
|
||||||
string = string.trim();
|
|
||||||
|
if (string.isEmpty()) {
|
||||||
|
throw new TNumberFormatException();
|
||||||
|
}
|
||||||
|
int start = 0;
|
||||||
|
int end = string.length();
|
||||||
|
while (string.charAt(start) <= ' ') {
|
||||||
|
if (++start == end) {
|
||||||
|
throw new TNumberFormatException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (string.charAt(end - 1) <= ' ') {
|
||||||
|
--end;
|
||||||
|
}
|
||||||
|
|
||||||
boolean negative = false;
|
boolean negative = false;
|
||||||
int index = 0;
|
int index = start;
|
||||||
if (string.charAt(index) == '-') {
|
if (string.charAt(index) == '-') {
|
||||||
++index;
|
++index;
|
||||||
negative = true;
|
negative = true;
|
||||||
} else if (string.charAt(index) == '+') {
|
} else if (string.charAt(index) == '+') {
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
|
if (index == end) {
|
||||||
|
throw new TNumberFormatException();
|
||||||
|
}
|
||||||
char c = string.charAt(index);
|
char c = string.charAt(index);
|
||||||
|
|
||||||
long mantissa = 0;
|
long mantissa = 0;
|
||||||
|
@ -96,12 +113,10 @@ public class TDouble extends TNumber implements TComparable<TDouble> {
|
||||||
if (c < '0' || c > '9') {
|
if (c < '0' || c > '9') {
|
||||||
throw new TNumberFormatException();
|
throw new TNumberFormatException();
|
||||||
}
|
}
|
||||||
while (string.charAt(index) == '0') {
|
while (index < end && string.charAt(index) == '0') {
|
||||||
if (++index == string.length()) {
|
++index;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
while (index < string.length()) {
|
while (index < end) {
|
||||||
c = string.charAt(index);
|
c = string.charAt(index);
|
||||||
if (c < '0' || c > '9') {
|
if (c < '0' || c > '9') {
|
||||||
break;
|
break;
|
||||||
|
@ -114,9 +129,9 @@ public class TDouble extends TNumber implements TComparable<TDouble> {
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (index < string.length() && string.charAt(index) == '.') {
|
if (index < end && string.charAt(index) == '.') {
|
||||||
++index;
|
++index;
|
||||||
while (index < string.length()) {
|
while (index < end) {
|
||||||
c = string.charAt(index);
|
c = string.charAt(index);
|
||||||
if (c < '0' || c > '9') {
|
if (c < '0' || c > '9') {
|
||||||
break;
|
break;
|
||||||
|
@ -132,13 +147,16 @@ public class TDouble extends TNumber implements TComparable<TDouble> {
|
||||||
throw new TNumberFormatException();
|
throw new TNumberFormatException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (index < string.length()) {
|
if (index < end) {
|
||||||
c = string.charAt(index);
|
c = string.charAt(index);
|
||||||
if (c != 'e' && c != 'E') {
|
if (c != 'e' && c != 'E') {
|
||||||
throw new TNumberFormatException();
|
throw new TNumberFormatException();
|
||||||
}
|
}
|
||||||
++index;
|
++index;
|
||||||
boolean negativeExp = false;
|
boolean negativeExp = false;
|
||||||
|
if (index == end) {
|
||||||
|
throw new TNumberFormatException();
|
||||||
|
}
|
||||||
if (string.charAt(index) == '-') {
|
if (string.charAt(index) == '-') {
|
||||||
++index;
|
++index;
|
||||||
negativeExp = true;
|
negativeExp = true;
|
||||||
|
@ -147,7 +165,7 @@ public class TDouble extends TNumber implements TComparable<TDouble> {
|
||||||
}
|
}
|
||||||
int numExp = 0;
|
int numExp = 0;
|
||||||
hasOneDigit = false;
|
hasOneDigit = false;
|
||||||
while (index < string.length()) {
|
while (index < end) {
|
||||||
c = string.charAt(index);
|
c = string.charAt(index);
|
||||||
if (c < '0' || c > '9') {
|
if (c < '0' || c > '9') {
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -121,15 +121,32 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
|
||||||
|
|
||||||
public static float parseFloat(TString string) throws TNumberFormatException {
|
public static float parseFloat(TString string) throws TNumberFormatException {
|
||||||
// TODO: parse infinite and different radix
|
// TODO: parse infinite and different radix
|
||||||
string = string.trim();
|
|
||||||
|
if (string.isEmpty()) {
|
||||||
|
throw new TNumberFormatException();
|
||||||
|
}
|
||||||
|
int start = 0;
|
||||||
|
int end = string.length();
|
||||||
|
while (string.charAt(start) <= ' ') {
|
||||||
|
if (++start == end) {
|
||||||
|
throw new TNumberFormatException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (string.charAt(end - 1) <= ' ') {
|
||||||
|
--end;
|
||||||
|
}
|
||||||
|
|
||||||
boolean negative = false;
|
boolean negative = false;
|
||||||
int index = 0;
|
int index = start;
|
||||||
if (string.charAt(index) == '-') {
|
if (string.charAt(index) == '-') {
|
||||||
++index;
|
++index;
|
||||||
negative = true;
|
negative = true;
|
||||||
} else if (string.charAt(index) == '+') {
|
} else if (string.charAt(index) == '+') {
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
|
if (index == end) {
|
||||||
|
throw new TNumberFormatException();
|
||||||
|
}
|
||||||
char c = string.charAt(index);
|
char c = string.charAt(index);
|
||||||
|
|
||||||
int mantissa = 0;
|
int mantissa = 0;
|
||||||
|
@ -142,12 +159,10 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
|
||||||
throw new TNumberFormatException();
|
throw new TNumberFormatException();
|
||||||
}
|
}
|
||||||
|
|
||||||
while (string.charAt(index) == '0') {
|
while (index < end && string.charAt(index) == '0') {
|
||||||
if (++index == string.length()) {
|
++index;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
while (index < string.length()) {
|
while (index < end) {
|
||||||
c = string.charAt(index);
|
c = string.charAt(index);
|
||||||
if (c < '0' || c > '9') {
|
if (c < '0' || c > '9') {
|
||||||
break;
|
break;
|
||||||
|
@ -161,9 +176,9 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index < string.length() && string.charAt(index) == '.') {
|
if (index < end && string.charAt(index) == '.') {
|
||||||
++index;
|
++index;
|
||||||
while (index < string.length()) {
|
while (index < end) {
|
||||||
c = string.charAt(index);
|
c = string.charAt(index);
|
||||||
if (c < '0' || c > '9') {
|
if (c < '0' || c > '9') {
|
||||||
break;
|
break;
|
||||||
|
@ -179,13 +194,16 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
|
||||||
throw new TNumberFormatException();
|
throw new TNumberFormatException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (index < string.length()) {
|
if (index < end) {
|
||||||
c = string.charAt(index);
|
c = string.charAt(index);
|
||||||
if (c != 'e' && c != 'E') {
|
if (c != 'e' && c != 'E') {
|
||||||
throw new TNumberFormatException();
|
throw new TNumberFormatException();
|
||||||
}
|
}
|
||||||
++index;
|
++index;
|
||||||
boolean negativeExp = false;
|
boolean negativeExp = false;
|
||||||
|
if (index == end) {
|
||||||
|
throw new TNumberFormatException();
|
||||||
|
}
|
||||||
if (string.charAt(index) == '-') {
|
if (string.charAt(index) == '-') {
|
||||||
++index;
|
++index;
|
||||||
negativeExp = true;
|
negativeExp = true;
|
||||||
|
@ -194,7 +212,7 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
|
||||||
}
|
}
|
||||||
int numExp = 0;
|
int numExp = 0;
|
||||||
hasOneDigit = false;
|
hasOneDigit = false;
|
||||||
while (index < string.length()) {
|
while (index < end) {
|
||||||
c = string.charAt(index);
|
c = string.charAt(index);
|
||||||
if (c < '0' || c > '9') {
|
if (c < '0' || c > '9') {
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -17,6 +17,7 @@ package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.teavm.junit.TeaVMTestRunner;
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
|
@ -37,43 +38,51 @@ public class DoubleTest {
|
||||||
assertEquals(23, Double.parseDouble("23."), 1E-12);
|
assertEquals(23, Double.parseDouble("23."), 1E-12);
|
||||||
assertEquals(0.1, Double.parseDouble("0.1"), 0.001);
|
assertEquals(0.1, Double.parseDouble("0.1"), 0.001);
|
||||||
assertEquals(0.1, Double.parseDouble(".1"), 0.001);
|
assertEquals(0.1, Double.parseDouble(".1"), 0.001);
|
||||||
}
|
assertEquals(0.1, Double.parseDouble(" .1"), 0.001);
|
||||||
|
assertEquals(0.1, Double.parseDouble(".1 "), 0.001);
|
||||||
@Test
|
|
||||||
public void negativeParsed() {
|
|
||||||
assertEquals(-23, Double.parseDouble("-23"), 1E-12);
|
assertEquals(-23, Double.parseDouble("-23"), 1E-12);
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void zeroParsed() {
|
|
||||||
assertEquals(0, Double.parseDouble("0.0"), 1E-12);
|
assertEquals(0, Double.parseDouble("0.0"), 1E-12);
|
||||||
|
assertEquals(0, Double.parseDouble("0"), 1E-12);
|
||||||
|
assertEquals(0, Double.parseDouble("00"), 1E-12);
|
||||||
|
assertEquals(0, Double.parseDouble("0."), 1E-12);
|
||||||
|
assertEquals(0, Double.parseDouble(".0"), 1E-12);
|
||||||
assertEquals(0, Double.parseDouble("23E-8000"), 1E-12);
|
assertEquals(0, Double.parseDouble("23E-8000"), 1E-12);
|
||||||
assertEquals(0, Double.parseDouble("00000"), 1E-12);
|
assertEquals(0, Double.parseDouble("00000"), 1E-12);
|
||||||
assertEquals(0, Double.parseDouble("00000.0000"), 1E-12);
|
assertEquals(0, Double.parseDouble("00000.0000"), 1E-12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parsedWithError() {
|
||||||
|
checkIllegalFormat("");
|
||||||
|
checkIllegalFormat(" ");
|
||||||
|
checkIllegalFormat("a");
|
||||||
|
checkIllegalFormat(" a ");
|
||||||
|
checkIllegalFormat("-");
|
||||||
|
checkIllegalFormat("-.");
|
||||||
|
checkIllegalFormat(".");
|
||||||
|
checkIllegalFormat("1e-");
|
||||||
|
checkIllegalFormat("1e");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkIllegalFormat(String string) {
|
||||||
|
try {
|
||||||
|
Double.parseDouble(string);
|
||||||
|
fail("Exception expected parsing string: " + string);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// It's expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void longBitsExtracted() {
|
public void longBitsExtracted() {
|
||||||
assertEquals(0x41E23456789ABCDEL, Double.doubleToLongBits(0x1.23456789ABCDEP+31));
|
assertEquals(0x41E23456789ABCDEL, Double.doubleToLongBits(0x1.23456789ABCDEP+31));
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void longBitsExtracted2() {
|
|
||||||
assertEquals(0x3FE1C28F5C28F5C3L >>> 3, Double.doubleToLongBits(0.555) >>> 3);
|
assertEquals(0x3FE1C28F5C28F5C3L >>> 3, Double.doubleToLongBits(0.555) >>> 3);
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void subNormalLongBitsExtracted() {
|
|
||||||
assertEquals(0x00000056789ABCDEL, Double.doubleToLongBits(0x0.00056789ABCDEP-1022));
|
assertEquals(0x00000056789ABCDEL, Double.doubleToLongBits(0x0.00056789ABCDEP-1022));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void longBitsPacked() {
|
public void longBitsPacked() {
|
||||||
assertEquals(0x1.23456789ABCDEP+31, Double.longBitsToDouble(0x41E23456789ABCDEL), 0x1.0P-19);
|
assertEquals(0x1.23456789ABCDEP+31, Double.longBitsToDouble(0x41E23456789ABCDEL), 0x1.0P-19);
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void subNormalLongBitsPacked() {
|
|
||||||
assertEquals(0x0.00056789ABCDEP-1022, Double.longBitsToDouble(0x00000056789ABCDEL), 0x1.0P-19);
|
assertEquals(0x0.00056789ABCDEP-1022, Double.longBitsToDouble(0x00000056789ABCDEL), 0x1.0P-19);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.teavm.junit.TeaVMTestRunner;
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
|
@ -38,43 +39,51 @@ public class FloatTest {
|
||||||
assertEquals(23, Float.parseFloat("23."), 1E-12F);
|
assertEquals(23, Float.parseFloat("23."), 1E-12F);
|
||||||
assertEquals(0.1F, Float.parseFloat("0.1"), 0.001F);
|
assertEquals(0.1F, Float.parseFloat("0.1"), 0.001F);
|
||||||
assertEquals(0.1F, Float.parseFloat(".1"), 0.001F);
|
assertEquals(0.1F, Float.parseFloat(".1"), 0.001F);
|
||||||
}
|
assertEquals(0.1F, Float.parseFloat(" .1"), 0.001F);
|
||||||
|
assertEquals(0.1F, Float.parseFloat(".1 "), 0.001F);
|
||||||
@Test
|
|
||||||
public void negativeParsed() {
|
|
||||||
assertEquals(-23, Float.parseFloat("-23"), 1E-12F);
|
assertEquals(-23, Float.parseFloat("-23"), 1E-12F);
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void zeroParsed() {
|
|
||||||
assertEquals(0, Float.parseFloat("0.0"), 1E-12F);
|
assertEquals(0, Float.parseFloat("0.0"), 1E-12F);
|
||||||
|
assertEquals(0, Float.parseFloat("0"), 1E-12F);
|
||||||
|
assertEquals(0, Float.parseFloat("00"), 1E-12F);
|
||||||
|
assertEquals(0, Float.parseFloat(".0"), 1E-12F);
|
||||||
|
assertEquals(0, Float.parseFloat("0."), 1E-12F);
|
||||||
assertEquals(0, Float.parseFloat("23E-8000"), 1E-12F);
|
assertEquals(0, Float.parseFloat("23E-8000"), 1E-12F);
|
||||||
assertEquals(0, Float.parseFloat("00000"), 1E-12F);
|
assertEquals(0, Float.parseFloat("00000"), 1E-12F);
|
||||||
assertEquals(0, Float.parseFloat("00000.0000"), 1E-12F);
|
assertEquals(0, Float.parseFloat("00000.0000"), 1E-12F);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parsedWithError() {
|
||||||
|
checkIllegalFormat("");
|
||||||
|
checkIllegalFormat(" ");
|
||||||
|
checkIllegalFormat("a");
|
||||||
|
checkIllegalFormat(" a ");
|
||||||
|
checkIllegalFormat("-");
|
||||||
|
checkIllegalFormat("-.");
|
||||||
|
checkIllegalFormat(".");
|
||||||
|
checkIllegalFormat("1e-");
|
||||||
|
checkIllegalFormat("1e");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkIllegalFormat(String string) {
|
||||||
|
try {
|
||||||
|
Float.parseFloat(string);
|
||||||
|
fail("Exception expected parsing string: " + string);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// It's expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void floatBitsExtracted() {
|
public void floatBitsExtracted() {
|
||||||
assertEquals(0x4591A2B4, Float.floatToIntBits(0x1.234567p+12f));
|
assertEquals(0x4591A2B4, Float.floatToIntBits(0x1.234567p+12f));
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void floatBitsExtracted2() {
|
|
||||||
assertEquals(0x800000, Float.floatToIntBits((float) Math.pow(2, -126)));
|
assertEquals(0x800000, Float.floatToIntBits((float) Math.pow(2, -126)));
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void subNormalFloatBitsExtracted() {
|
|
||||||
assertEquals(0x000092, Float.floatToIntBits(0x0.000123p-126f));
|
assertEquals(0x000092, Float.floatToIntBits(0x0.000123p-126f));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void floatBitsPacked() {
|
public void floatBitsPacked() {
|
||||||
assertEquals(0x1.234567p+12f, Float.intBitsToFloat(0x4591A2B4), 1e7);
|
assertEquals(0x1.234567p+12f, Float.intBitsToFloat(0x4591A2B4), 1e7);
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void subNormalFloatBitsPacked() {
|
|
||||||
assertEquals(0x0.000123p-126f, Float.intBitsToFloat(0x000092), 0x000008p-126);
|
assertEquals(0x0.000123p-126f, Float.intBitsToFloat(0x000092), 0x000008p-126);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,8 +125,8 @@ public class SystemTest {
|
||||||
System.err.println("err overridden");
|
System.err.println("err overridden");
|
||||||
System.err.flush();
|
System.err.flush();
|
||||||
|
|
||||||
assertEquals("err overridden\n", new String(err.toByteArray()));
|
assertEquals("err overridden" + System.lineSeparator(), new String(err.toByteArray()));
|
||||||
assertEquals("out overridden\n", new String(out.toByteArray()));
|
assertEquals("out overridden" + System.lineSeparator(), new String(out.toByteArray()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue
Block a user