diff --git a/base/parse.jl b/base/parse.jl index 50b76e0577eb1..ecbfdbe3f92b1 100644 --- a/base/parse.jl +++ b/base/parse.jl @@ -73,7 +73,7 @@ function parseint_preamble(signed::Bool, base::Int, s::AbstractString, startpos: (j == 0) && (return 0, 0, 0) if base == 0 - if c == '0' && i <= ncodeunits(s) + if c == '0' && i <= endpos c, i = iterate(s,i)::Tuple{Char, Int} base = c=='b' ? 2 : c=='o' ? 8 : c=='x' ? 16 : 10 if base != 10 diff --git a/test/parse.jl b/test/parse.jl index c3b49ebdc7e1c..5bf3b806edca8 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -30,6 +30,16 @@ @test_throws ArgumentError parse(Int, 'a') @test_throws ArgumentError parse(Int,typemax(Char)) +# Issue 29451 +struct Issue29451String <: AbstractString end +Base.ncodeunits(::Issue29451String) = 12345 +Base.lastindex(::Issue29451String) = 1 +Base.isvalid(::Issue29451String, i::Integer) = i == 1 +Base.iterate(::Issue29451String, i::Integer=1) = i == 1 ? ('0', 2) : nothing + +@test Issue29451String() == "0" +@test parse(Int, Issue29451String()) == 0 + # Issue 20587 for T in Any[BigInt, Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8] T === BigInt && continue # TODO: make BigInt pass this test