Skip to content

Commit

Permalink
fix _checked_mul_dims in the presence of 0s and overflow. (#54255)
Browse files Browse the repository at this point in the history
fixes #54244.
  • Loading branch information
oscardssmith authored Apr 26, 2024
1 parent b902a38 commit aeac289
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 12 deletions.
27 changes: 15 additions & 12 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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}

Expand Down

0 comments on commit aeac289

Please sign in to comment.