Skip to content

Commit

Permalink
Fix E notation parsing in BigDecimal (#9577)
Browse files Browse the repository at this point in the history
  • Loading branch information
stevegeek authored Mar 20, 2022
1 parent 91ac123 commit ecb97a9
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 5 deletions.
68 changes: 68 additions & 0 deletions spec/std/big/big_decimal_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,74 @@ describe BigDecimal do
expect_raises(InvalidBigDecimalException) do
BigDecimal.new("1.2a")
end

expect_raises(InvalidBigDecimalException) do
BigDecimal.new("1ee1")
end

expect_raises(InvalidBigDecimalException) do
BigDecimal.new("e+e1")
end

expect_raises(InvalidBigDecimalException) do
BigDecimal.new("1e1e")
end

expect_raises(InvalidBigDecimalException) do
BigDecimal.new("1 e1")
end

expect_raises(InvalidBigDecimalException) do
BigDecimal.new("..e1")
end

expect_raises(InvalidBigDecimalException) do
BigDecimal.new("-..e1")
end

expect_raises(InvalidBigDecimalException) do
BigDecimal.new("e1")
end

expect_raises(InvalidBigDecimalException) do
BigDecimal.new("e+5")
end

expect_raises(InvalidBigDecimalException) do
BigDecimal.new(".e1")
end

expect_raises(InvalidBigDecimalException) do
BigDecimal.new(".e+1")
end

expect_raises(InvalidBigDecimalException) do
BigDecimal.new("-.e1")
end

expect_raises(InvalidBigDecimalException) do
BigDecimal.new("1e.")
end

expect_raises(InvalidBigDecimalException) do
BigDecimal.new("1e0.1")
end

expect_raises(InvalidBigDecimalException) do
BigDecimal.new("1e+")
end

expect_raises(InvalidBigDecimalException) do
BigDecimal.new("1.1e-")
end

expect_raises(InvalidBigDecimalException) do
BigDecimal.new("-")
end

expect_raises(InvalidBigDecimalException) do
BigDecimal.new("1.0e")
end
end

it "performs arithmetic with bigdecimals" do
Expand Down
14 changes: 9 additions & 5 deletions src/big/big_decimal.cr
Original file line number Diff line number Diff line change
Expand Up @@ -76,23 +76,27 @@ struct BigDecimal < Number
# Check str's validity and find index of 'e'
exponent_index = nil

input_length = str.bytesize

str.each_char_with_index do |char, index|
final_character = index == input_length - 1
first_character = index == 0
case char
when '-'
unless index == 0 || exponent_index == index - 1
unless (first_character && !final_character) || (exponent_index == index - 1 && !final_character)
raise InvalidBigDecimalException.new(str, "Unexpected '-' character")
end
when '+'
unless exponent_index == index - 1
if final_character || exponent_index != index - 1
raise InvalidBigDecimalException.new(str, "Unexpected '+' character")
end
when '.'
if decimal_index
if decimal_index || exponent_index
raise InvalidBigDecimalException.new(str, "Unexpected '.' character")
end
decimal_index = index
when 'e', 'E'
if exponent_index
if first_character || final_character || exponent_index || decimal_index == index - 1
raise InvalidBigDecimalException.new(str, "Unexpected #{char.inspect} character")
end
exponent_index = index
Expand All @@ -103,7 +107,7 @@ struct BigDecimal < Number
end
end

decimal_end_index = (exponent_index || str.bytesize) - 1
decimal_end_index = (exponent_index || input_length) - 1
if decimal_index
decimal_count = (decimal_end_index - decimal_index).to_u64

Expand Down

0 comments on commit ecb97a9

Please sign in to comment.