From a603de8bd79a06f6c04a7406e54b9a4b6aa68a25 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Tue, 24 Jan 2017 01:02:46 +0300 Subject: [PATCH] Ensure string to number conversion fails on empty and blank inputs. #KT-4497 --- js/js.libraries/src/core/numberConversions.kt | 4 ++-- .../test/text/StringNumberConversionTest.kt | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/js/js.libraries/src/core/numberConversions.kt b/js/js.libraries/src/core/numberConversions.kt index 00dcd45d65f..64c7e8e3c43 100644 --- a/js/js.libraries/src/core/numberConversions.kt +++ b/js/js.libraries/src/core/numberConversions.kt @@ -72,7 +72,7 @@ public fun String.toLong(radix: Int): Long = toLongOrNull(radix) ?: numberFormat * @throws NumberFormatException if the string is not a valid representation of a number. */ public fun String.toDouble(): Double = (+(this.asDynamic())).unsafeCast().also { - if (it.isNaN() && !this.isNaN()) + if (it.isNaN() && !this.isNaN() || it == 0.0 && this.isBlank()) numberFormatError(this) } @@ -87,7 +87,7 @@ public inline fun String.toFloat(): Float = toDouble().unsafeCast() * or `null` if the string is not a valid representation of a number. */ public fun String.toDoubleOrNull(): Double? = (+(this.asDynamic())).unsafeCast().takeIf { - !(it.isNaN() && !this.isNaN()) + !(it.isNaN() && !this.isNaN() || it == 0.0 && this.isBlank()) } /** diff --git a/libraries/stdlib/test/text/StringNumberConversionTest.kt b/libraries/stdlib/test/text/StringNumberConversionTest.kt index 53f1f35709a..1fcb16e000a 100644 --- a/libraries/stdlib/test/text/StringNumberConversionTest.kt +++ b/libraries/stdlib/test/text/StringNumberConversionTest.kt @@ -19,6 +19,8 @@ class StringNumberConversionTest { assertProduces("+77", 77.toByte()) assertProduces("-128", Byte.MIN_VALUE) assertFailsOrNull("128") + assertFailsOrNull("") + assertFailsOrNull(" ") } compareConversionWithRadix(String::toByte, String::toByteOrNull) { @@ -26,6 +28,8 @@ class StringNumberConversionTest { assertProduces(16, "+7F", 127.toByte()) assertProduces(16, "-80", (-128).toByte()) assertFailsOrNull(2, "10000000") + assertFailsOrNull(8, "") + assertFailsOrNull(8, " ") } } @@ -35,12 +39,16 @@ class StringNumberConversionTest { assertProduces("32767", Short.MAX_VALUE) assertProduces("-32768", Short.MIN_VALUE) assertFailsOrNull("+32768") + assertFailsOrNull("") + assertFailsOrNull(" ") } compareConversionWithRadix(String::toShort, String::toShortOrNull) { assertProduces(16, "7FFF", 0x7FFF.toShort()) assertProduces(16, "-8000", (-0x8000).toShort()) assertFailsOrNull(5, "10000000") + assertFailsOrNull(2, "") + assertFailsOrNull(2, " ") } } @@ -53,6 +61,8 @@ class StringNumberConversionTest { assertFailsOrNull("2147483648") assertFailsOrNull("-2147483649") assertFailsOrNull("239239kotlin") + assertFailsOrNull("") + assertFailsOrNull(" ") } compareConversionWithRadix(String::toInt, String::toIntOrNull) { @@ -71,6 +81,8 @@ class StringNumberConversionTest { assertFailsOrNull(10, "2147483648") assertFailsOrNull(8, "99") assertFailsOrNull(10, "Kona") + assertFailsOrNull(16, "") + assertFailsOrNull(16, " ") } assertFailsWith("Expected to fail with radix 1") { "1".toInt(radix = 1) } @@ -96,6 +108,8 @@ class StringNumberConversionTest { assertFailsOrNull("92233,75809") assertFailsOrNull("92233`75809") assertFailsOrNull("-922337KOTLIN775809") + assertFailsOrNull("") + assertFailsOrNull(" ") } compareConversionWithRadix(String::toLong, String::toLongOrNull) { @@ -112,6 +126,8 @@ class StringNumberConversionTest { assertFailsOrNull(8, "99") assertFailsOrNull(10, "Hazelnut") + assertFailsOrNull(4, "") + assertFailsOrNull(4, " ") } assertFailsWith("Expected to fail with radix 37") { "37".toLong(radix = 37) } @@ -132,6 +148,8 @@ class StringNumberConversionTest { assertProduces("-1e39", Float.NEGATIVE_INFINITY) assertProduces("1000000000000000000000000000000000000000", Float.POSITIVE_INFINITY) assertFailsOrNull("dark side") + assertFailsOrNull("") + assertFailsOrNull(" ") } } @@ -151,6 +169,8 @@ class StringNumberConversionTest { assertFailsOrNull("7..7") assertFailsOrNull("007 not a number") + assertFailsOrNull("") + assertFailsOrNull(" ") } }