Skip to content

Commit 92db099

Browse files
oscardssmithKristofferC
authored andcommitted
fix _checked_mul_dims in the presence of 0s and overflow. (#54255)
fixes #54244. (cherry picked from commit aeac289)
1 parent 6792cb4 commit 92db099

File tree

2 files changed

+29
-12
lines changed

2 files changed

+29
-12
lines changed

base/boot.jl

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -547,19 +547,22 @@ function _checked_mul_dims(m::Int, n::Int)
547547
return a, ovflw
548548
end
549549
function _checked_mul_dims(m::Int, d::Int...)
550-
@_foldable_meta # the compiler needs to know this loop terminates
551-
a = m
552-
i = 1
553-
ovflw = false
554-
while Intrinsics.sle_int(i, nfields(d))
555-
di = getfield(d, i)
556-
b = Intrinsics.checked_smul_int(a, di)
557-
ovflw = Intrinsics.or_int(ovflw, getfield(b, 2))
558-
ovflw = Intrinsics.or_int(ovflw, Intrinsics.ule_int(typemax_Int, di))
559-
a = getfield(b, 1)
560-
i = Intrinsics.add_int(i, 1)
550+
@_foldable_meta # the compiler needs to know this loop terminates
551+
a = m
552+
i = 1
553+
ovflw = false
554+
neg = Intrinsics.ule_int(typemax_Int, m)
555+
zero = false # if m==0 we won't have overflow since we go left to right
556+
while Intrinsics.sle_int(i, nfields(d))
557+
di = getfield(d, i)
558+
b = Intrinsics.checked_smul_int(a, di)
559+
zero = Intrinsics.or_int(zero, di === 0)
560+
ovflw = Intrinsics.or_int(ovflw, getfield(b, 2))
561+
neg = Intrinsics.or_int(neg, Intrinsics.ule_int(typemax_Int, di))
562+
a = getfield(b, 1)
563+
i = Intrinsics.add_int(i, 1)
561564
end
562-
return a, ovflw
565+
return a, Intrinsics.or_int(neg, Intrinsics.and_int(ovflw, Intrinsics.not_int(zero)))
563566
end
564567

565568
# convert a set of dims to a length, with overflow checking

test/core.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7213,6 +7213,20 @@ end
72137213
@test_throws ArgumentError Array{Int, 2}(undef, -10, 0)
72147214
@test_throws ArgumentError Array{Int, 2}(undef, -1, -1)
72157215

7216+
# issue #54244
7217+
# test that zero sized array doesn't throw even with large axes
7218+
bignum = Int==Int64 ? 2^32 : 2^16
7219+
Array{Int}(undef, 0, bignum, bignum)
7220+
Array{Int}(undef, bignum, bignum, 0)
7221+
Array{Int}(undef, bignum, bignum, 0, bignum, bignum)
7222+
# but also test that it does throw if the axes multiply to a multiple of typemax(UInt)
7223+
@test_throws ArgumentError Array{Int}(undef, bignum, bignum)
7224+
@test_throws ArgumentError Array{Int}(undef, 1, bignum, bignum)
7225+
# also test that we always throw erros for negative dims even if other dims are 0 or the product is positive
7226+
@test_throws ArgumentError Array{Int}(undef, 0, -4, -4)
7227+
@test_throws ArgumentError Array{Int}(undef, -4, 1, 0)
7228+
@test_throws ArgumentError Array{Int}(undef, -4, -4, 1)
7229+
72167230
# issue #28812
72177231
@test Tuple{Vararg{Array{T} where T,3}} === Tuple{Array,Array,Array}
72187232

0 commit comments

Comments
 (0)