From 46ad578341162d5143b0f7db138983bda2ee46de Mon Sep 17 00:00:00 2001 From: Ugljesa Jovanovic Date: Wed, 10 Feb 2021 12:58:45 +0100 Subject: [PATCH 1/2] Check for base, and check if character belongs to base. Fixes #152 --- .../ionspin/kotlin/bignum/integer/BigInteger.kt | 3 +++ .../integer/base32/BigInteger32Arithmetic.kt | 2 +- .../base63/BigInteger63LinkedListArithmetic.kt | 2 +- .../base63/array/BigInteger63Arithmetic.kt | 2 +- .../kotlin/bignum/integer/util/DigitUtil.kt | 10 ++++++++-- .../bignum/integer/BigIntegerReadmeTest.kt | 17 +++++++++++++++++ 6 files changed, 31 insertions(+), 5 deletions(-) diff --git a/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/BigInteger.kt b/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/BigInteger.kt index 31749886..84b7e3ab 100644 --- a/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/BigInteger.kt +++ b/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/BigInteger.kt @@ -74,6 +74,9 @@ class BigInteger internal constructor(wordArray: WordArray, requestedSign: Sign) val LOG_10_OF_2 = log10(2.0) override fun parseString(string: String, base: Int): BigInteger { + if (base < 2 || base > 36) { + throw NumberFormatException("Unsupported base: $base. Supported base range is from 2 to 36") + } val decimal = string.contains('.') if (decimal) { val bigDecimal = BigDecimal.parseString(string) diff --git a/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/base32/BigInteger32Arithmetic.kt b/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/base32/BigInteger32Arithmetic.kt index 2407cdb8..8e5d95fa 100644 --- a/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/base32/BigInteger32Arithmetic.kt +++ b/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/base32/BigInteger32Arithmetic.kt @@ -1052,7 +1052,7 @@ internal object BigInteger32Arithmetic : BigInteger32ArithmeticInterface { override fun parseForBase(number: String, base: Int): UIntArray { var parsed = ZERO number.forEach { char -> - parsed = (parsed * base.toUInt()) + char.toDigit().toUInt() + parsed = (parsed * base.toUInt()) + char.toDigit(base).toUInt() } return parsed } diff --git a/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/base63/BigInteger63LinkedListArithmetic.kt b/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/base63/BigInteger63LinkedListArithmetic.kt index 73949420..711dde25 100644 --- a/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/base63/BigInteger63LinkedListArithmetic.kt +++ b/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/base63/BigInteger63LinkedListArithmetic.kt @@ -1034,7 +1034,7 @@ internal object BigInteger63LinkedListArithmetic : BigIntegerList63Arithmetic { override fun parseForBase(number: String, base: Int): List { var parsed = ZERO number.toLowerCase().forEach { char -> - parsed = (parsed * base.toULong()) + (char.toDigit()).toULong() + parsed = (parsed * base.toULong()) + (char.toDigit(base)).toULong() } return removeLeadingZeros(parsed) } diff --git a/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/base63/array/BigInteger63Arithmetic.kt b/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/base63/array/BigInteger63Arithmetic.kt index 3e1056b1..cea4640e 100644 --- a/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/base63/array/BigInteger63Arithmetic.kt +++ b/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/base63/array/BigInteger63Arithmetic.kt @@ -1925,7 +1925,7 @@ internal object BigInteger63Arithmetic : BigIntegerArithmetic { override fun parseForBase(number: String, base: Int): ULongArray { var parsed = ZERO number.toLowerCase().forEach { char -> - parsed = (parsed * base.toULong()) + (char.toDigit()).toULong() + parsed = (parsed * base.toULong()) + (char.toDigit(base)).toULong() } return removeLeadingZeros( parsed diff --git a/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/util/DigitUtil.kt b/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/util/DigitUtil.kt index 43931743..8f1b9646 100644 --- a/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/util/DigitUtil.kt +++ b/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/util/DigitUtil.kt @@ -22,8 +22,10 @@ package com.ionspin.kotlin.bignum.integer.util * ugljesa.jovanovic@ionspin.com * on 18-Mar-2019 */ -fun Char.toDigit(): Int { - return when (this) { +fun Char.toDigit(base: Int = 10): Int { + //Check if number belongs to est used in base + + val digit = when (this) { in '0'..'9' -> (this - 48).toInt() in 'a'..'z' -> this - 'a' + 10 in 'A'..'Z' -> this - 'A' + 10 @@ -32,4 +34,8 @@ fun Char.toDigit(): Int { '.' -> throw NumberFormatException("Invalid digit for radix $this (Possibly a decimal value, which is not supported by BigInteger parser") else -> throw NumberFormatException("Invalid digit for radix $this") } + if (digit < 0 || digit >= base) { + throw NumberFormatException("$this is not a valid digit for number system with base $base") + } + return digit } diff --git a/bignum/src/commonTest/kotlin/com/ionspin/kotlin/bignum/integer/BigIntegerReadmeTest.kt b/bignum/src/commonTest/kotlin/com/ionspin/kotlin/bignum/integer/BigIntegerReadmeTest.kt index 6064a02d..2092ed5e 100644 --- a/bignum/src/commonTest/kotlin/com/ionspin/kotlin/bignum/integer/BigIntegerReadmeTest.kt +++ b/bignum/src/commonTest/kotlin/com/ionspin/kotlin/bignum/integer/BigIntegerReadmeTest.kt @@ -18,6 +18,7 @@ package com.ionspin.kotlin.bignum.integer import kotlin.test.Test +import kotlin.test.assertFailsWith import kotlin.test.assertTrue /** @@ -219,6 +220,22 @@ class BigIntegerReadmeTest { val expected = BigInteger.parseString("12", 10) bigint == expected } + + assertFailsWith(NumberFormatException::class) { + val parsed = BigInteger.parseString("a", 10) + } + + assertFailsWith(NumberFormatException::class) { + val parsed = BigInteger.parseString("Z", 35) + } + + assertFailsWith(NumberFormatException::class) { + val parsed = BigInteger.parseString("A", 37) + } + + assertFailsWith(NumberFormatException::class) { + val parsed = BigInteger.parseString("A", 1) + } } @Test From 54bd3f72e2fed5b3d38f9b1189c86a0e96ccbfc9 Mon Sep 17 00:00:00 2001 From: Ugljesa Jovanovic Date: Wed, 10 Feb 2021 15:33:28 +0100 Subject: [PATCH 2/2] Spotless --- .../kotlin/com/ionspin/kotlin/bignum/integer/util/DigitUtil.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/util/DigitUtil.kt b/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/util/DigitUtil.kt index 8f1b9646..eac3b841 100644 --- a/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/util/DigitUtil.kt +++ b/bignum/src/commonMain/kotlin/com/ionspin/kotlin/bignum/integer/util/DigitUtil.kt @@ -23,7 +23,7 @@ package com.ionspin.kotlin.bignum.integer.util * on 18-Mar-2019 */ fun Char.toDigit(base: Int = 10): Int { - //Check if number belongs to est used in base + // Check if number belongs to est used in base val digit = when (this) { in '0'..'9' -> (this - 48).toInt()