From 4cc3b41378a4923bb68e03f7c5a27741caa556cb Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Mon, 18 Sep 2017 13:05:45 -0500 Subject: [PATCH] Fix missing bounds checks for trailing zero dimensions (#23723) This fixes issue #23629 for 0.6. It is done independently from the fix for master (in #23628) due to all the deprecation changes. --- base/abstractarray.jl | 5 +++-- src/cgutils.cpp | 13 ++++++++++--- test/arrayops.jl | 5 +++++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 6360769c785c50..8df9186d4ab079 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -407,9 +407,10 @@ function checkbounds_indices(::Type{Bool}, IA::Tuple, I::Tuple{Any}) end function checkbounds_linear_indices(::Type{Bool}, IA::Tuple{Vararg{OneTo}}, i) @_inline_meta - if checkindex(Bool, IA[1], i) + ts = trailingsize(IA) + if checkindex(Bool, IA[1], i) && ts > 0 return true - elseif checkindex(Bool, OneTo(trailingsize(IA)), i) # partial linear indexing + elseif checkindex(Bool, OneTo(ts), i) # partial linear indexing partial_linear_indexing_warning_lookup(length(IA)) return true # TODO: Return false after the above function is removed in deprecated.jl end diff --git a/src/cgutils.cpp b/src/cgutils.cpp index e9554702765fbd..44f60c84f990a5 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -1726,17 +1726,24 @@ static Value *emit_array_nd_index(const jl_cgval_t &ainfo, jl_value_t *ex, ssize // the accessed array, i.e. `if !(i < alen) goto error`. if (nidxs > 1) { // TODO: REMOVE DEPWARN AND RETURN FALSE AFTER 0.6. - // We need to check if this is inside the non-linearized size + // We need to check if this index is inside its non-linearized dimension BasicBlock *partidx = BasicBlock::Create(jl_LLVMContext, "partlinidx"); BasicBlock *partidxwarn = BasicBlock::Create(jl_LLVMContext, "partlinidxwarn"); + BasicBlock *trailingcheck = BasicBlock::Create(jl_LLVMContext, "trailingcheck"); Value *d = emit_arraysize_for_unsafe_dim(ainfo, ex, nidxs, nd, ctx); - builder.CreateCondBr(builder.CreateICmpULT(ii, d), endBB, partidx); + Value *alen = emit_arraylen(ainfo, ex, ctx); + builder.CreateCondBr(builder.CreateICmpULT(ii, d), trailingcheck, partidx); + + // If it is inside its own dimension, we still need to ensure all other + // dimensions are non-zero + ctx->f->getBasicBlockList().push_back(trailingcheck); + builder.SetInsertPoint(trailingcheck); + builder.CreateCondBr(builder.CreateICmpULT(ii, alen), endBB, failBB); // We failed the normal bounds check; check to see if we're // inside the linearized size (partial linear indexing): ctx->f->getBasicBlockList().push_back(partidx); builder.SetInsertPoint(partidx); - Value *alen = emit_arraylen(ainfo, ex, ctx); builder.CreateCondBr(builder.CreateICmpULT(i, alen), partidxwarn, failBB); // We passed the linearized bounds check; now throw the depwarn: diff --git a/test/arrayops.jl b/test/arrayops.jl index 36e6a3695f55e3..e1a0a2497edacf 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -2119,3 +2119,8 @@ Base.:(==)(a::T11053, b::T11053) = a.a == b.a #15907 @test typeof(Array{Int,0}()) == Array{Int,0} + +@testset "issue 23629" begin + @test_throws BoundsError zeros(2,3,0)[2,3] + @test_throws BoundsError checkbounds(zeros(2,3,0), 2, 3) +end