From ad304ea490a50c7a38a36ea01db8f8b7c00aeb8d Mon Sep 17 00:00:00 2001 From: Ujjwal Sarswat <76774914+vmpyr@users.noreply.github.com> Date: Fri, 10 Mar 2023 22:57:33 +0530 Subject: [PATCH] add overflow checking for `abs(::Rational)` (#48912) --- base/rational.jl | 4 ++-- test/hashing.jl | 3 +++ test/rational.jl | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/base/rational.jl b/base/rational.jl index 3cfb038ab3b38..6ab022736388e 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -277,7 +277,7 @@ signbit(x::Rational) = signbit(x.num) copysign(x::Rational, y::Real) = unsafe_rational(copysign(x.num, y), x.den) copysign(x::Rational, y::Rational) = unsafe_rational(copysign(x.num, y.num), x.den) -abs(x::Rational) = Rational(abs(x.num), x.den) +abs(x::Rational) = unsafe_rational(checked_abs(x.num), x.den) typemin(::Type{Rational{T}}) where {T<:Signed} = unsafe_rational(T, -one(T), zero(T)) typemin(::Type{Rational{T}}) where {T<:Integer} = unsafe_rational(T, zero(T), one(T)) @@ -545,7 +545,7 @@ function hash(x::Rational{<:BitInteger64}, h::UInt) pow = trailing_zeros(den) den >>= pow pow = -pow - if den == 1 && abs(num) < 9007199254740992 + if den == 1 && uabs(num) < UInt64(maxintfloat(Float64)) return hash(ldexp(Float64(num),pow),h) end end diff --git a/test/hashing.jl b/test/hashing.jl index 0266b2f06e168..b672c3de817c6 100644 --- a/test/hashing.jl +++ b/test/hashing.jl @@ -60,6 +60,9 @@ end @test hash(nextfloat(2.0^63)) == hash(UInt64(nextfloat(2.0^63))) @test hash(prevfloat(2.0^64)) == hash(UInt64(prevfloat(2.0^64))) +# issue #48744 +@test hash(typemin(Int)//1) === hash(big(typemin(Int)//1)) + # issue #9264 @test hash(1//6,zero(UInt)) == invoke(hash, Tuple{Real, UInt}, 1//6, zero(UInt)) @test hash(1//6) == hash(big(1)//big(6)) diff --git a/test/rational.jl b/test/rational.jl index a0833d08eb218..a1af6eda64516 100644 --- a/test/rational.jl +++ b/test/rational.jl @@ -269,6 +269,9 @@ end @test read(io2, typeof(rational2)) == rational2 end end +@testset "abs overflow for Rational" begin + @test_throws OverflowError abs(typemin(Int) // 1) +end @testset "parse" begin # Non-negative Int in which parsing is expected to work @test parse(Rational{Int}, string(10)) == 10 // 1