Skip to content

Commit f0ece4a

Browse files
authored
prevent stack overflows from faulty user-defined constructor methods (#59506)
`Base` code often assumes that a constructor will return a value of the stated type. This is false, cross-reference issue #42372. This change prevents several stack overflows that arise when a generic method is called with a newly-defined type with such a weird constructor for some `Base`-defined type.
1 parent e0d49ac commit f0ece4a

File tree

14 files changed

+87
-32
lines changed

14 files changed

+87
-32
lines changed

base/char.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ represents a valid Unicode character.
4747
"""
4848
Char
4949

50-
@constprop :aggressive (::Type{T})(x::Number) where {T<:AbstractChar} = T(UInt32(x))
50+
@constprop :aggressive (::Type{T})(x::Number) where {T<:AbstractChar} = T(UInt32(x)::UInt32)
5151
@constprop :aggressive AbstractChar(x::Number) = Char(x)
5252
@constprop :aggressive (::Type{T})(x::AbstractChar) where {T<:Union{Number,AbstractChar}} = T(codepoint(x))
5353
@constprop :aggressive (::Type{T})(x::AbstractChar) where {T<:Union{Int32,Int64}} = codepoint(x) % T
@@ -225,9 +225,9 @@ hash(x::Char, h::UInt) =
225225
hash_finalizer(((bitcast(UInt32, x) + UInt64(0xd4d64234)) << 32) UInt64(h)) % UInt
226226

227227
# fallbacks:
228-
isless(x::AbstractChar, y::AbstractChar) = isless(Char(x), Char(y))
229-
==(x::AbstractChar, y::AbstractChar) = Char(x) == Char(y)
230-
hash(x::AbstractChar, h::UInt) = hash(Char(x), h)
228+
isless(x::AbstractChar, y::AbstractChar) = isless(Char(x)::Char, Char(y)::Char)
229+
==(x::AbstractChar, y::AbstractChar) = Char(x)::Char == Char(y)::Char
230+
hash(x::AbstractChar, h::UInt) = hash(Char(x)::Char, h)
231231
widen(::Type{T}) where {T<:AbstractChar} = T
232232

233233
@inline -(x::AbstractChar, y::AbstractChar) = Int(x) - Int(y)
@@ -257,7 +257,7 @@ end
257257
# (Packages may implement other IO subtypes to specify different encodings.)
258258
# In contrast, `write(io, c)` outputs a `c` in an encoding determined by typeof(c).
259259
print(io::IO, c::Char) = (write(io, c); nothing)
260-
print(io::IO, c::AbstractChar) = print(io, Char(c)) # fallback: convert to output UTF-8
260+
print(io::IO, c::AbstractChar) = print(io, Char(c)::Char) # fallback: convert to output UTF-8
261261

262262
const hex_chars = UInt8['0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
263263
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',

base/filesystem.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ function isexecutable(path::String)
390390
X_OK = 0x01
391391
return ccall(:jl_fs_access, Cint, (Cstring, Cint), path, X_OK) == 0
392392
end
393-
isexecutable(path::AbstractString) = isexecutable(String(path))
393+
isexecutable(path::AbstractString) = isexecutable(String(path)::String)
394394

395395
"""
396396
isreadable(path::String)
@@ -417,7 +417,7 @@ function isreadable(path::String)
417417
R_OK = 0x04
418418
return ccall(:jl_fs_access, Cint, (Cstring, Cint), path, R_OK) == 0
419419
end
420-
isreadable(path::AbstractString) = isreadable(String(path))
420+
isreadable(path::AbstractString) = isreadable(String(path)::String)
421421

422422
"""
423423
iswritable(path::String)
@@ -444,7 +444,7 @@ function iswritable(path::String)
444444
W_OK = 0x02
445445
return ccall(:jl_fs_access, Cint, (Cstring, Cint), path, W_OK) == 0
446446
end
447-
iswritable(path::AbstractString) = iswritable(String(path))
447+
iswritable(path::AbstractString) = iswritable(String(path)::String)
448448

449449

450450
end

base/iobuffer.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -953,7 +953,7 @@ end
953953
return sizeof(UInt8)
954954
end
955955

956-
readbytes!(io::GenericIOBuffer, b::MutableDenseArrayType{UInt8}, nb=length(b)) = readbytes!(io, b, Int(nb))
956+
readbytes!(io::GenericIOBuffer, b::MutableDenseArrayType{UInt8}, nb=length(b)) = readbytes!(io, b, Int(nb)::Int)
957957

958958
function readbytes!(io::GenericIOBuffer, b::MutableDenseArrayType{UInt8}, nb::Int)
959959
io.readable || _throw_not_readable()

base/parse.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ function tryparse_internal(::Type{Float32}, s::SubString{String}, startpos::Int,
299299
(Ptr{UInt8},Csize_t,Csize_t), s.string, s.offset+startpos-1, endpos-startpos+1)
300300
hasvalue ? val : nothing
301301
end
302-
tryparse(::Type{T}, s::AbstractString) where {T<:Union{Float32,Float64}} = tryparse(T, String(s))
302+
tryparse(::Type{T}, s::AbstractString) where {T<:Union{Float32,Float64}} = tryparse(T, String(s)::String)
303303
tryparse(::Type{Float16}, s::AbstractString) =
304304
convert(Union{Float16, Nothing}, tryparse(Float32, s))
305305
tryparse_internal(::Type{Float16}, s::AbstractString, startpos::Int, endpos::Int) =

base/path.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ julia> splitpath("/home/myuser/example.jl")
253253
"example.jl"
254254
```
255255
"""
256-
splitpath(p::AbstractString) = splitpath(String(p))
256+
splitpath(p::AbstractString) = splitpath(String(p)::String)
257257

258258
function splitpath(p::String)
259259
drive, p = splitdrive(p)
@@ -608,10 +608,10 @@ function relpath(path::String, startpath::String = ".")
608608
return isempty(relpath_) ? curdir : relpath_
609609
end
610610
relpath(path::AbstractString, startpath::AbstractString) =
611-
relpath(String(path), String(startpath))
611+
relpath(String(path)::String, String(startpath)::String)
612612

613613
for f in (:isdirpath, :splitdir, :splitdrive, :splitext, :normpath, :abspath)
614-
@eval $f(path::AbstractString) = $f(String(path))
614+
@eval $f(path::AbstractString) = $f(String(path)::String)
615615
end
616616

617617
# RFC3986 Section 2.1
@@ -665,4 +665,4 @@ else
665665
end
666666
end
667667

668-
uripath(path::AbstractString) = uripath(String(path))
668+
uripath(path::AbstractString) = uripath(String(path)::String)

base/stat.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ function ispath(path::String)
380380
end
381381
return r == 0
382382
end
383-
ispath(path::AbstractString) = ispath(String(path))
383+
ispath(path::AbstractString) = ispath(String(path)::String)
384384

385385
"""
386386
isfifo(path)::Bool

base/strings/basic.jl

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ Vector{UInt8}(s::AbstractString) = unsafe_wrap(Vector{UInt8}, String(s))
221221
Array{UInt8}(s::AbstractString) = unsafe_wrap(Vector{UInt8}, String(s))
222222
Vector{T}(s::AbstractString) where {T<:AbstractChar} = collect(T, s)
223223

224-
Symbol(s::AbstractString) = Symbol(String(s))
224+
Symbol(s::AbstractString) = Symbol(String(s)::String)
225225
Symbol(x...) = Symbol(string(x...))
226226

227227
convert(::Type{T}, s::T) where {T<:AbstractString} = s
@@ -364,7 +364,7 @@ isless(a::Symbol, b::Symbol) = cmp(a, b) < 0
364364

365365
# hashing
366366

367-
hash(s::AbstractString, h::UInt) = hash(String(s), h)
367+
hash(s::AbstractString, h::UInt) = hash(String(s)::String, h)
368368

369369
## character index arithmetic ##
370370

@@ -412,7 +412,7 @@ function length(s::AbstractString, i::Int, j::Int)
412412
end
413413

414414
@propagate_inbounds length(s::AbstractString, i::Integer, j::Integer) =
415-
length(s, Int(i), Int(j))
415+
length(s, Int(i)::Int, Int(j)::Int)
416416

417417
"""
418418
thisind(s::AbstractString, i::Integer)::Int
@@ -446,7 +446,7 @@ ERROR: BoundsError: attempt to access 2-codeunit String at index [-1]
446446
[...]
447447
```
448448
"""
449-
thisind(s::AbstractString, i::Integer) = thisind(s, Int(i))
449+
thisind(s::AbstractString, i::Integer) = thisind(s, Int(i)::Int)
450450

451451
function thisind(s::AbstractString, i::Int)
452452
z = ncodeunits(s)::Int + 1
@@ -502,8 +502,8 @@ julia> prevind("α", 2, 3)
502502
-1
503503
```
504504
"""
505-
prevind(s::AbstractString, i::Integer, n::Integer) = prevind(s, Int(i), Int(n))
506-
prevind(s::AbstractString, i::Integer) = prevind(s, Int(i))
505+
prevind(s::AbstractString, i::Integer, n::Integer) = prevind(s, Int(i)::Int, Int(n)::Int)
506+
prevind(s::AbstractString, i::Integer) = prevind(s, Int(i)::Int)
507507
prevind(s::AbstractString, i::Int) = prevind(s, i, 1)
508508

509509
function prevind(s::AbstractString, i::Int, n::Int)
@@ -561,8 +561,8 @@ julia> nextind("α", 1, 2)
561561
4
562562
```
563563
"""
564-
nextind(s::AbstractString, i::Integer, n::Integer) = nextind(s, Int(i), Int(n))
565-
nextind(s::AbstractString, i::Integer) = nextind(s, Int(i))
564+
nextind(s::AbstractString, i::Integer, n::Integer) = nextind(s, Int(i)::Int, Int(n)::Int)
565+
nextind(s::AbstractString, i::Integer) = nextind(s, Int(i)::Int)
566566
nextind(s::AbstractString, i::Int) = nextind(s, i, 1)
567567

568568
function nextind(s::AbstractString, i::Int, n::Int)
@@ -757,7 +757,7 @@ julia> repeat("ha", 3)
757757
"hahaha"
758758
```
759759
"""
760-
repeat(s::AbstractString, r::Integer) = repeat(String(s), r)
760+
repeat(s::AbstractString, r::Integer) = repeat(String(s)::String, r)
761761

762762
"""
763763
^(s::Union{AbstractString,AbstractChar}, n::Integer)::AbstractString

base/strings/string.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ pointer(s::String, i::Integer) = pointer(s) + Int(i)::Int - 1
158158
ncodeunits(s::String) = Core.sizeof(s)
159159
codeunit(s::String) = UInt8
160160

161-
codeunit(s::String, i::Integer) = codeunit(s, Int(i))
161+
codeunit(s::String, i::Integer) = codeunit(s, Int(i)::Int)
162162
@assume_effects :foldable @inline function codeunit(s::String, i::Int)
163163
@boundscheck checkbounds(s, i)
164164
b = GC.@preserve s unsafe_load(pointer(s, i))

base/strings/substring.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ end
4848

4949
@propagate_inbounds SubString(s::T, i::Int, j::Int) where {T<:AbstractString} = SubString{T}(s, i, j)
5050
@propagate_inbounds SubString(s::T, i::Int, j::Int, v::Val{:noshift}) where {T<:AbstractString} = SubString{T}(s, i, j, v)
51-
@propagate_inbounds SubString(s::AbstractString, i::Integer, j::Integer=lastindex(s)) = SubString(s, Int(i), Int(j))
51+
@propagate_inbounds SubString(s::AbstractString, i::Integer, j::Integer=lastindex(s)) = SubString(s, Int(i)::Int, Int(j)::Int)
5252
@propagate_inbounds SubString(s::AbstractString, r::AbstractUnitRange{<:Integer}) = SubString(s, first(r), last(r))
5353

5454
@propagate_inbounds function SubString(s::SubString, i::Int, j::Int)

base/strings/unicode.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ const _julia_charmap = Dict{UInt32,UInt32}(
191191
0x210F => 0x0127, # hbar -> small letter h with stroke (#48870)
192192
)
193193

194-
utf8proc_map(s::AbstractString, flags::Integer, chartransform::F = identity) where F = utf8proc_map(String(s), flags, chartransform)
194+
utf8proc_map(s::AbstractString, flags::Integer, chartransform::F = identity) where F = utf8proc_map(String(s)::String, flags, chartransform)
195195

196196
# Documented in Unicode module
197197
function normalize(

0 commit comments

Comments
 (0)