Skip to content

Commit

Permalink
Boundschecks for searchsorted & remove step(r::Range)==0 tests
Browse files Browse the repository at this point in the history
1) Check bounds on the more low-level searchsorted* methods.  Before
an error like this was possible:
```
julia> searchsortedfirst([1:10], 5,  -10, 7, Base.Order.Forward)
zsh: segmentation fault (core dumped)
```

2) Removes the step(r)==0 tests as ranges cannot have 0 steps (I
   think)

Note that the low-level sort! methods also do not check bounds.
Probably this should also be rectified.
  • Loading branch information
mauro3 committed Jun 2, 2014
1 parent 17b6262 commit 10e51e5
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 22 deletions.
31 changes: 9 additions & 22 deletions base/sort.jl
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ select(v::AbstractVector, k::Union(Int,OrdinalRange); kws...) = select!(copy(v),
# index of the first value of vector a that is greater than or equal to x;
# returns length(v)+1 if x is greater than all values in v.
function searchsortedfirst(v::AbstractVector, x, lo::Int, hi::Int, o::Ordering)
1 <= lo <= hi <= length(v) || throw(BoundsError())
lo = lo-1
hi = hi+1
@inbounds while lo < hi-1
Expand All @@ -141,6 +142,7 @@ end
# index of the last value of vector a that is less than or equal to x;
# returns 0 if x is less than all values of v.
function searchsortedlast(v::AbstractVector, x, lo::Int, hi::Int, o::Ordering)
1 <= lo <= hi <= length(v) || throw(BoundsError())
lo = lo-1
hi = hi+1
@inbounds while lo < hi-1
Expand All @@ -158,6 +160,7 @@ end
# if v does not contain x, returns a 0-length range
# indicating the insertion point of x
function searchsorted(v::AbstractVector, x, lo::Int, hi::Int, o::Ordering)
1 <= lo <= hi <= length(v) || throw(BoundsError())
lo = lo-1
hi = hi+1
@inbounds while lo < hi-1
Expand All @@ -176,37 +179,21 @@ function searchsorted(v::AbstractVector, x, lo::Int, hi::Int, o::Ordering)
end

function searchsortedlast{T<:Real}(a::Range{T}, x::Real, o::DirectOrdering)
if step(a) == 0
lt(o, x, first(a)) ? 0 : length(a)
else
n = max(min(iround((x-first(a))/step(a))+1,length(a)),1)
lt(o, x, a[n]) ? n-1 : n
end
n = max(min(iround((x-first(a))/step(a))+1,length(a)),1)
lt(o, x, a[n]) ? n-1 : n
end

function searchsortedfirst{T<:Real}(a::Range{T}, x::Real, o::DirectOrdering)
if step(a) == 0
lt(o, first(a), x) ? length(a)+1 : 1
else
n = max(min(iround((x-first(a))/step(a))+1,length(a)),1)
lt(o, a[n] ,x) ? n+1 : n
end
n = max(min(iround((x-first(a))/step(a))+1,length(a)),1)
lt(o, a[n] ,x) ? n+1 : n
end

function searchsortedlast{T<:Integer}(a::Range{T}, x::Real, o::DirectOrdering)
if step(a) == 0
lt(o, x, first(a)) ? 0 : length(a)
else
max(min(fld(ifloor(x)-first(a),step(a))+1,length(a)),0)
end
max(min(fld(ifloor(x)-first(a),step(a))+1,length(a)),0)
end

function searchsortedfirst{T<:Integer}(a::Range{T}, x::Real, o::DirectOrdering)
if step(a) == 0
lt(o, first(a), x) ? length(a)+1 : 1
else
max(min(-fld(ifloor(-x)+first(a),step(a))+1,length(a)+1),1)
end
max(min(-fld(ifloor(-x)+first(a),step(a))+1,length(a)+1),1)
end

searchsorted{T<:Real}(a::Range{T}, x::Real, o::DirectOrdering) =
Expand Down
4 changes: 4 additions & 0 deletions test/sorting.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ end
@test searchsorted(1:10, 1, by=(x -> x >= 5)) == searchsorted([1:10], 1, by=(x -> x >= 5))
@test searchsorted(1:10, 10, by=(x -> x >= 5)) == searchsorted([1:10], 10, by=(x -> x >= 5))

@test_throws BoundsError searchsortedfirst(1:10, 5, 0, 7, Base.Order.Forward)
@test_throws BoundsError searchsortedfirst(1:10, 5, 1, 11, Base.Order.Forward)
@test_throws BoundsError searchsortedfirst(1:10, 5, 5, 1, Base.Order.Forward)

a = rand(1:10000, 1000)

for alg in [InsertionSort, MergeSort]
Expand Down

0 comments on commit 10e51e5

Please sign in to comment.