Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions base/strings/basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ UInt8
See also [`ncodeunits`](@ref), [`checkbounds`](@ref).
"""
@propagate_inbounds codeunit(s::AbstractString, i::Integer) = i isa Int ?
throw(MethodError(codeunit, (s, i))) : codeunit(s, Int(i))
throw(MethodError(codeunit, (s, i))) : codeunit(s, Int(i)::Int)

"""
isvalid(s::AbstractString, i::Integer)::Bool
Expand Down Expand Up @@ -141,7 +141,7 @@ Stacktrace:
```
"""
@propagate_inbounds isvalid(s::AbstractString, i::Integer) = i isa Int ?
throw(MethodError(isvalid, (s, i))) : isvalid(s, Int(i))
throw(MethodError(isvalid, (s, i))) : isvalid(s, Int(i)::Int)

"""
iterate(s::AbstractString, i::Integer)::Union{Tuple{<:AbstractChar, Int}, Nothing}
Expand All @@ -154,7 +154,7 @@ of the iteration protocol may assume that `i` is the start of a character in `s`
See also [`getindex`](@ref), [`checkbounds`](@ref).
"""
@propagate_inbounds iterate(s::AbstractString, i::Integer) = i isa Int ?
throw(MethodError(iterate, (s, i))) : iterate(s, Int(i))
throw(MethodError(iterate, (s, i))) : iterate(s, Int(i)::Int)

## basic generic definitions ##

Expand Down
33 changes: 25 additions & 8 deletions test/faulty_constructor_method_should_not_cause_stack_overflows.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# new types with invalid constructors
for (typ, sup) in (
(:Char, :AbstractChar),
(:String, :AbstractString),
Expand All @@ -9,6 +10,18 @@ for (typ, sup) in (
@eval function Base.$typ(x::$fau) x end
end

# valid new subtype of `AbstractString`
struct MyString <: AbstractString
str::String
end
Base.lastindex(s::MyString) = lastindex(s.str)
Base.iterate(s::MyString) = iterate(s, 1)
Base.iterate(s::MyString, state) = iterate(s, Int(state)::Int)
Base.iterate(s::MyString, state::Integer) = iterate(s, Int(state)::Int)
Base.iterate(s::MyString, state::Int) = iterate(s.str, state)
Base.isequal(a::MyString, b::MyString) = isequal(a.str, b.str)
Base.:(==)(a::MyString, b::MyString) = (a.str == b.str)

using Test
using Unicode: Unicode

Expand Down Expand Up @@ -39,14 +52,18 @@ using Unicode: Unicode
end
@testset let x = FaultyInt()
@test_throws exc readbytes!(IOBuffer(), Vector{UInt8}(undef, 0), x)
@test_throws exc length("", x, x)
@test_throws exc thisind("", x)
@test_throws exc prevind("", x)
@test_throws exc prevind("", x, x)
@test_throws exc nextind("", x)
@test_throws exc nextind("", x, x)
@test_throws exc codeunit("", x)
@test_throws exc SubString("", x, x)
for s in ("", MyString(""))
@test_throws exc iterate(s, x)
@test_throws exc isvalid(s, x)
@test_throws exc length(s, x, x)
@test_throws exc thisind(s, x)
@test_throws exc prevind(s, x)
@test_throws exc prevind(s, x, x)
@test_throws exc nextind(s, x)
@test_throws exc nextind(s, x, x)
@test_throws exc codeunit(s, x)
@test_throws exc SubString(s, x, x)
end
end
@testset let x = FaultyUInt32()
@test_throws exc Char(x)
Expand Down