diff --git a/base/boot.jl b/base/boot.jl index a3c5c03bdf721..16820aa070369 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -562,19 +562,22 @@ function _checked_mul_dims(m::Int, n::Int) return a, ovflw end function _checked_mul_dims(m::Int, d::Int...) - @_foldable_meta # the compiler needs to know this loop terminates - a = m - i = 1 - ovflw = false - while Intrinsics.sle_int(i, nfields(d)) - di = getfield(d, i) - b = Intrinsics.checked_smul_int(a, di) - ovflw = Intrinsics.or_int(ovflw, getfield(b, 2)) - ovflw = Intrinsics.or_int(ovflw, Intrinsics.ule_int(typemax_Int, di)) - a = getfield(b, 1) - i = Intrinsics.add_int(i, 1) + @_foldable_meta # the compiler needs to know this loop terminates + a = m + i = 1 + ovflw = false + neg = Intrinsics.ule_int(typemax_Int, m) + zero = false # if m==0 we won't have overflow since we go left to right + while Intrinsics.sle_int(i, nfields(d)) + di = getfield(d, i) + b = Intrinsics.checked_smul_int(a, di) + zero = Intrinsics.or_int(zero, di === 0) + ovflw = Intrinsics.or_int(ovflw, getfield(b, 2)) + neg = Intrinsics.or_int(neg, Intrinsics.ule_int(typemax_Int, di)) + a = getfield(b, 1) + i = Intrinsics.add_int(i, 1) end - return a, ovflw + return a, Intrinsics.or_int(neg, Intrinsics.and_int(ovflw, Intrinsics.not_int(zero))) end # convert a set of dims to a length, with overflow checking diff --git a/test/core.jl b/test/core.jl index ed1e1fc6757d2..c908a9c2b5afd 100644 --- a/test/core.jl +++ b/test/core.jl @@ -7213,6 +7213,20 @@ end @test_throws ArgumentError Array{Int, 2}(undef, -10, 0) @test_throws ArgumentError Array{Int, 2}(undef, -1, -1) +# issue #54244 +# test that zero sized array doesn't throw even with large axes +bignum = Int==Int64 ? 2^32 : 2^16 +Array{Int}(undef, 0, bignum, bignum) +Array{Int}(undef, bignum, bignum, 0) +Array{Int}(undef, bignum, bignum, 0, bignum, bignum) +# but also test that it does throw if the axes multiply to a multiple of typemax(UInt) +@test_throws ArgumentError Array{Int}(undef, bignum, bignum) +@test_throws ArgumentError Array{Int}(undef, 1, bignum, bignum) +# also test that we always throw erros for negative dims even if other dims are 0 or the product is positive +@test_throws ArgumentError Array{Int}(undef, 0, -4, -4) +@test_throws ArgumentError Array{Int}(undef, -4, 1, 0) +@test_throws ArgumentError Array{Int}(undef, -4, -4, 1) + # issue #28812 @test Tuple{Vararg{Array{T} where T,3}} === Tuple{Array,Array,Array}