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