diff --git a/src/Tar.jl b/src/Tar.jl index 5b4f5a9..8452233 100644 --- a/src/Tar.jl +++ b/src/Tar.jl @@ -20,6 +20,19 @@ function Base.skip(io::Union{Base.Process, Base.ProcessChain}, n::Integer) end const skip_buffer = UInt8[] +# method for this exists in Base since Julia 1.4 but not before +!hasmethod(read!, Tuple{IO, AbstractArray}) && +function Base.read!(s::IO, a::AbstractArray{T}) where T + if isbitstype(T) && (a isa Array || a isa Base.FastContiguousSubArray{T,<:Any,<:Array{T}}) + GC.@preserve a unsafe_read(s, pointer(a), sizeof(a)) + else + for i in eachindex(a) + a[i] = read(s, T) + end + end + return a +end + function can_symlink(dir::AbstractString) # guaranteed to be an empty directory link_path = joinpath(dir, "link") diff --git a/src/extract.jl b/src/extract.jl index 54db73e..f8b3770 100644 --- a/src/extract.jl +++ b/src/extract.jl @@ -1,11 +1,5 @@ import SHA -@static if VERSION < v"1.4.0-DEV" - view_read!(io, buf::SubArray{UInt8}) = readbytes!(io, buf, sizeof(buf)) -else - view_read!(io, buf::SubArray{UInt8}) = read!(io, buf) -end - function iterate_headers( callback::Function, tar::IO; @@ -301,10 +295,10 @@ function git_file_hash( # where you write data to an IO object and it maintains a hash padded_size = round_up(size) while padded_size > 0 - max_read_len = min(padded_size, length(buf)) + max_read_len = Int(min(padded_size, length(buf))) read_len = readbytes!(tar, buf, max_read_len) read_len < max_read_len && eof(tar) && throw(EOFError()) - nonpadded_view = view(buf, 1:min(read_len, size)) + nonpadded_view = view(buf, 1:Int(min(read_len, size))) SHA.update!(ctx, nonpadded_view) size -= length(nonpadded_view) padded_size -= read_len @@ -433,7 +427,7 @@ function read_header( metadata = copy(globals) while true if hdr.type in (:g, :x) # POSIX extended headers - let hdr=hdr #15276 + let hdr=hdr # https://github.com/JuliaLang/julia/issues/15276 read_extended_metadata(io, hdr.size, buf=buf, tee=tee) do key, val if key in ("size", "path", "linkpath") if hdr.type == :g @@ -480,6 +474,9 @@ function read_extended_metadata( buf::Vector{UInt8} = Vector{UInt8}(undef, DEFAULT_BUFFER_SIZE), tee::IO = devnull, ) + size > typemax(Int32) && + error("read_extended_metadata called with too large size: $size") + size = Int(size) data = read_data(io, size=size, buf=buf, tee=tee) malformed() = error("malformed extended header metadata: $(repr(String(data)))") i = 0 @@ -553,9 +550,7 @@ function read_standard_header( buf::Vector{UInt8} = Vector{UInt8}(undef, DEFAULT_BUFFER_SIZE), tee::IO = devnull, ) - header_view = view(buf, 1:512) - view_read!(io, header_view) - write(tee, header_view) + header_view = read_data(io, size=512, buf=buf, tee=tee) if all(iszero, header_view) if tee !== devnull while !eof(io) @@ -637,11 +632,11 @@ function read_data( )::Nothing padded_size = round_up(size) while padded_size > 0 - max_read_len = min(padded_size, length(buf)) + max_read_len = Int(min(padded_size, length(buf))) read_len = readbytes!(tar, buf, max_read_len) write(tee, view(buf, 1:read_len)) read_len < max_read_len && eof(tar) && throw(EOFError()) - size -= write(file, view(buf, 1:min(read_len, size))) + size -= write(file, view(buf, 1:Int(min(read_len, size)))) padded_size -= read_len end @assert size == padded_size == 0 @@ -668,10 +663,11 @@ function read_data( buf::Vector{UInt8} = Vector{UInt8}(undef, DEFAULT_BUFFER_SIZE), tee::IO = devnull, )::AbstractVector{UInt8} - n = round_up(size) - length(buf) < n && resize!(buf, nextpow(2, n)) - r = readbytes!(tar, buf, n) - write(tee, view(buf, 1:r)) - r < n && throw(EOFError()) + padded_size = round_up(size) + padded_size > typemax(Int32) && + throw(ArgumentError("read_data(tar; size) called with too large size: $size")) + padded_size = Int(padded_size) + length(buf) < padded_size && resize!(buf, nextpow(2, padded_size)) + write(tee, read!(tar, view(buf, 1:padded_size))) return view(buf, 1:size) end diff --git a/test/runtests.jl b/test/runtests.jl index e12bd94..b76fc6e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -189,7 +189,6 @@ end end end - VERSION ≥ v"1.4" && # no EOFError due to 1.3 bug @testset "header truncated" begin for h in [511, 256, 1] open(tarball, "a") do io