Skip to content

Commit

Permalink
Fix scala-js#4088: Avoid an Int overflow in BigDecimal.toString(). (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
LeeTibbert committed Jul 6, 2020
1 parent e580e67 commit d83fad4
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 9 deletions.
17 changes: 8 additions & 9 deletions javalib/src/main/scala/java/math/Conversion.scala
Expand Up @@ -284,10 +284,10 @@ private[math] object Conversion {
result = (48 + (prev - v * 10)).toChar + result
} while (v != 0)

val exponent = resLengthInChars - currentChar - scale - 1
val exponent: Long = resLengthInChars - currentChar - scale.toLong - 1

if (scale > 0 && exponent >= -6) {
val index = exponent + 1
if (scale > 0 && exponent >= -6L) {
val index = exponent.toInt + 1
if (index > 0) {
// special case 1
result = result.substring(0, index) + "." + result.substring(index)
Expand All @@ -299,16 +299,15 @@ private[math] object Conversion {
result = "0." + result
}
} else if (scale != 0) {
var result1 = exponent.toString
if (exponent > 0)
result1 = '+' + result1
result1 = 'E' + result1
val exponentStr =
if (exponent > 0) "E+" + exponent
else "E" + exponent

result =
if (resLengthInChars - currentChar > 1)
result(0) + "." + result.substring(1) + result1
result.substring(0, 1) + "." + result.substring(1) + exponentStr
else
result + result1
result + exponentStr
}

if (negNumber) '-' + result
Expand Down
68 changes: 68 additions & 0 deletions unit-tests/src/test/scala/java/math/BigDecimalToStringSuite.scala
@@ -0,0 +1,68 @@
// Ported from Scala.js original and adapted for Scala Native.
// BigDecimalToStringTesT.scala, commit 3851c2d, dated: 2020-06-19.
// https://raw.githubusercontent.com/scala-js/scala-js/\
// 83056e39d54c4546a11372add54abb1ece6c5df1/test-suite/\
// shared/src/test/scala/org/scalajs/testsuite/\
// javalib/math/BigDecimalToStringTest.scala

/*
* Scala.js (https://www.scala-js.org/)
*
* Copyright EPFL.
*
* Licensed under Apache License 2.0
* (https://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/

package java.math

object BigDecimalToStringSuite extends tests.Suite {

test("testToStringWithCornerCaseScales") {
val bigIntOne = BigInteger.valueOf(1)

assertEquals("1", new BigDecimal(bigIntOne, 0).toString())

assertEquals("0.01", new BigDecimal(bigIntOne, 2).toString())
assertEquals("0.000001", new BigDecimal(bigIntOne, 6).toString())
assertEquals("1E-7", new BigDecimal(bigIntOne, 7).toString())
assertEquals("1E-2147483647",
new BigDecimal(bigIntOne, 2147483647).toString())

assertEquals("1E+1", new BigDecimal(bigIntOne, -1).toString())
assertEquals("1E+2", new BigDecimal(bigIntOne, -2).toString())
assertEquals("1E+15", new BigDecimal(bigIntOne, -15).toString())
assertEquals("1E+2147483647",
new BigDecimal(bigIntOne, -2147483647).toString())
assertEquals(
"1E+2147483648",
new BigDecimal(bigIntOne, -2147483648).toString()
) // Scala.js Issue #4088

val bigInt123 = BigInteger.valueOf(123)

assertEquals("123", new BigDecimal(bigInt123, 0).toString())

assertEquals("1.23", new BigDecimal(bigInt123, 2).toString())
assertEquals("0.000123", new BigDecimal(bigInt123, 6).toString())
assertEquals("0.00000123", new BigDecimal(bigInt123, 8).toString())
assertEquals("1.23E-7", new BigDecimal(bigInt123, 9).toString())
assertEquals("1.23E-2147483645",
new BigDecimal(bigInt123, 2147483647).toString())

assertEquals("1.23E+3", new BigDecimal(bigInt123, -1).toString())
assertEquals("1.23E+4", new BigDecimal(bigInt123, -2).toString())
assertEquals("1.23E+17", new BigDecimal(bigInt123, -15).toString())
assertEquals(
"1.23E+2147483649",
new BigDecimal(bigInt123, -2147483647).toString()
) // Scala.js Issue #4088
assertEquals(
"1.23E+2147483650",
new BigDecimal(bigInt123, -2147483648).toString()
) // Scala.js Issue #4088
}
}

0 comments on commit d83fad4

Please sign in to comment.