From fdcaa0674bbd3c2b3f73ddfebac83b46218f0f53 Mon Sep 17 00:00:00 2001 From: simeonschaub Date: Tue, 17 Dec 2019 16:38:13 +0100 Subject: [PATCH] check for `typemin(T)` in denominator of rational (#32572) --- base/rational.jl | 14 ++++++++++---- test/rational.jl | 4 ++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/base/rational.jl b/base/rational.jl index 45e39ea285f28..be0f84a094e73 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -11,12 +11,18 @@ struct Rational{T<:Integer} <: Real den::T function Rational{T}(num::Integer, den::Integer) where T<:Integer - num == den == zero(T) && __throw_rational_argerror(T) - num2, den2 = signbit(den) ? divgcd(-num, -den) : divgcd(num, den) - new(num2, den2) + num == den == zero(T) && __throw_rational_argerror_zero(T) + num2, den2 = divgcd(num, den) + if T<:Signed && signbit(den2) + den2 = -den2 + signbit(den2) && __throw_rational_argerror_typemin(T) + num2 = -num2 + end + return new(num2, den2) end end -@noinline __throw_rational_argerror(T) = throw(ArgumentError("invalid rational: zero($T)//zero($T)")) +@noinline __throw_rational_argerror_zero(T) = throw(ArgumentError("invalid rational: zero($T)//zero($T)")) +@noinline __throw_rational_argerror_typemin(T) = throw(ArgumentError("invalid rational: denominator can't be typemin($T)")) Rational(n::T, d::T) where {T<:Integer} = Rational{T}(n,d) Rational(n::Integer, d::Integer) = Rational(promote(n,d)...) diff --git a/test/rational.jl b/test/rational.jl index 4f59bf586fff2..083fb1c19c10f 100644 --- a/test/rational.jl +++ b/test/rational.jl @@ -32,6 +32,10 @@ using Test @test_throws ArgumentError rationalize(Int, big(3.0), -1.) # issue 26823 @test_throws InexactError rationalize(Int, NaN) + # issue 32569 + @test_throws ArgumentError 1 // typemin(Int) + @test -2 // typemin(Int) == -1 // (typemin(Int) >> 1) + @test 2 // typemin(Int) == 1 // (typemin(Int) >> 1) for a = -5:5, b = -5:5 if a == b == 0; continue; end