Skip to content

unsafe read/write #14766

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 26, 2016
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
2 changes: 1 addition & 1 deletion base/LineEdit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1125,7 +1125,7 @@ end

function refresh_multi_line(termbuf::TerminalBuffer, s::SearchState)
buf = IOBuffer()
write(buf, pointer(s.query_buffer.data), s.query_buffer.ptr-1)
unsafe_write(buf, pointer(s.query_buffer.data), s.query_buffer.ptr-1)
write(buf, "': ")
offset = buf.ptr
ptr = s.response_buffer.ptr
Expand Down
52 changes: 12 additions & 40 deletions base/Terminals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,34 +22,30 @@ export
getY,
hascolor,
pos,
raw!,
writepos
raw!

import Base:
check_open, # stream.jl
displaysize,
flush,
pipe_reader,
pipe_writer,
read,
readuntil,
displaysize,
start_reading,
stop_reading,
write,
writemime,
reseteof,
eof,
check_open # stream.jl
writemime

## TextTerminal ##

abstract TextTerminal <: Base.IO
abstract TextTerminal <: Base.AbstractPipe

# INTERFACE
pipe_reader(::TextTerminal) = error("Unimplemented")
pipe_writer(::TextTerminal) = error("Unimplemented")
displaysize(::TextTerminal) = error("Unimplemented")
writepos(t::TextTerminal, x, y, s::Array{UInt8,1}) = error("Unimplemented")
cmove(t::TextTerminal, x, y) = error("Unimplemented")
getX(t::TextTerminal) = error("Unimplemented")
getY(t::TextTerminal) = error("Unimplemented")
pos(t::TextTerminal) = (getX(t), getY(t))
reseteof(t::TextTerminal) = nothing

# Relative moves (Absolute position fallbacks)
cmove_up(t::TextTerminal, n) = cmove(getX(t), max(1, getY(t)-n))
Expand All @@ -76,18 +72,6 @@ cmove_col(t::TextTerminal, c) = cmove(c, getY(t))
hascolor(::TextTerminal) = false

# Utility Functions
function writepos{T}(t::TextTerminal, x, y, b::Array{T})
if isbits(T)
writepos(t, x, y, reinterpret(UInt8, b))
else
cmove(t, x, y)
invoke(write, Tuple{IO, Array}, s, a)
end
end
function writepos(t::TextTerminal, x, y, args...)
cmove(t, x, y)
write(t, args...)
end
width(t::TextTerminal) = displaysize(t)[2]
height(t::TextTerminal) = displaysize(t)[1]

Expand All @@ -108,6 +92,9 @@ disable_bracketed_paste(t::TextTerminal) = nothing

abstract UnixTerminal <: TextTerminal

pipe_reader(t::UnixTerminal) = t.in_stream
pipe_writer(t::UnixTerminal) = t.out_stream

type TerminalBuffer <: UnixTerminal
out_stream::Base.IO
end
Expand All @@ -119,8 +106,6 @@ type TTYTerminal <: UnixTerminal
err_stream::Base.TTY
end

reseteof(t::TTYTerminal) = reseteof(t.in_stream)

const CSI = "\x1b["

cmove_up(t::UnixTerminal, n) = write(t.out_stream, "$(CSI)$(n)A")
Expand Down Expand Up @@ -166,19 +151,6 @@ clear(t::UnixTerminal) = write(t.out_stream, "\x1b[H\x1b[2J")
clear_line(t::UnixTerminal) = write(t.out_stream, "\x1b[0G\x1b[0K")
#beep(t::UnixTerminal) = write(t.err_stream,"\x7")

write{T,N}(t::UnixTerminal, a::Array{T,N}) = write(t.out_stream, a)
write(t::UnixTerminal, p::Ptr{UInt8}) = write(t.out_stream, p)
write(t::UnixTerminal, p::Ptr{UInt8}, x::Integer) = write(t.out_stream, p, x)
write(t::UnixTerminal, x::UInt8) = write(t.out_stream, x)
read{T,N}(t::UnixTerminal, x::Array{T,N}) = read(t.in_stream, x)
readuntil(t::UnixTerminal, s::AbstractString) = readuntil(t.in_stream, s)
readuntil(t::UnixTerminal, c::Char) = readuntil(t.in_stream, c)
readuntil(t::UnixTerminal, s) = readuntil(t.in_stream, s)
read(t::UnixTerminal, ::Type{UInt8}) = read(t.in_stream, UInt8)
start_reading(t::UnixTerminal) = start_reading(t.in_stream)
stop_reading(t::UnixTerminal) = stop_reading(t.in_stream)
eof(t::UnixTerminal) = eof(t.in_stream)

@unix_only function hascolor(t::TTYTerminal)
startswith(t.term_type, "xterm") && return true
try
Expand Down
17 changes: 8 additions & 9 deletions base/base64.jl
Original file line number Diff line number Diff line change
Expand Up @@ -85,41 +85,40 @@ end

#############################################################################

function write(b::Base64EncodePipe, x::AbstractVector{UInt8})
n = length(x)
function unsafe_write(b::Base64EncodePipe, x::Ptr{UInt8}, n::UInt)
s = 1 # starting index
# finish any cached data to write:
if b.nb == 1
if n >= 2
write(b.io, b64(b.b0, x[1], x[2])...)
write(b.io, b64(b.b0, unsafe_load(x, 1), unsafe_load(x, 2))...)
s = 3
elseif n == 1
b.b1 = x[1]
b.b1 = unsafe_load(x, 1)
b.nb = 2
return
else
return
end
elseif b.nb == 2
if n >= 1
write(b.io, b64(b.b0, b.b1, x[1])...)
write(b.io, b64(b.b0, b.b1, unsafe_load(x, 1))...)
s = 2
else
return
end
end
# write all groups of three bytes:
while s + 2 <= n
write(b.io, b64(x[s], x[s+1], x[s+2])...)
write(b.io, b64(unsafe_load(x, s), unsafe_load(x, s + 1), unsafe_load(x, s + 2))...)
s += 3
end
# cache any leftover bytes:
if s + 1 == n
b.b0 = x[s]
b.b1 = x[s+1]
b.b0 = unsafe_load(x, s)
b.b1 = unsafe_load(x, s + 1)
b.nb = 2
elseif s == n
b.b0 = x[s]
b.b0 = unsafe_load(x, s)
b.nb = 1
else
b.nb = 0
Expand Down
3 changes: 3 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -978,3 +978,6 @@ end
end
return offsets
end

# 14766
@deprecate write(io::IO, p::Ptr, nb::Integer) unsafe_write(io, p, nb)
2 changes: 2 additions & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1333,7 +1333,9 @@ export
unsafe_copy!,
unsafe_load,
unsafe_pointer_to_objref,
unsafe_read,
unsafe_store!,
unsafe_write,

# nullable types
isnull,
Expand Down
25 changes: 6 additions & 19 deletions base/filesystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -105,23 +105,15 @@ function sendfile(dst::File, src::File, src_offset::Int64, bytes::Int)
nothing
end

function write(f::File, buf::Ptr{UInt8}, len::Integer, offset::Integer=-1)
function unsafe_write(f::File, buf::Ptr{UInt8}, len::UInt, offset::Int64=Int64(-1))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this need to be tightened from Integer? this might break packages that are hitting code paths not tested in base

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i also renamed it.....

i'll attempt to put in a deprecations for this. the problem is that write(io, p, l) is supposed to be the same as write(io, p); write(io, l), but many IO streams were abusing some variant of this method signature to express the unsafe_write concept.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right but the renamed version is getting called elsewhere. It looks like you have a more generic method that calls convert below.

check_open(f)
err = ccall(:jl_fs_write, Int32, (Int32, Ptr{UInt8}, Csize_t, Int64),
f.handle, buf, len, offset)
uv_error("write", err)
return len
end

write(f::File, c::UInt8) = write(f, UInt8[c])

function write{T}(f::File, a::Array{T})
if isbits(T)
write(f, pointer(a), sizeof(a))
else
invoke(write, Tuple{IO, Array}, f, a)
end
end
write(f::File, c::UInt8) = write(f, Ref{UInt8}(c))

function truncate(f::File, n::Integer)
check_open(f)
Expand Down Expand Up @@ -152,18 +144,13 @@ function read(f::File, ::Type{UInt8})
return ret % UInt8
end

function read!(f::File, a::Vector{UInt8}, nel=length(a))
function unsafe_read(f::File, p::Ptr{UInt8}, nel::UInt)
check_open(f)
if nel < 0 || nel > length(a)
throw(BoundsError())
end
ret = ccall(:jl_fs_read, Int32, (Int32, Ptr{Void}, Csize_t),
f.handle, a, nel)
if ret < nel
throw(EOFError())
end
f.handle, p, nel)
uv_error("read",ret)
return a
ret == nel || throw(EOFError())
nothing
end

nb_available(f::File) = filesize(f) - position(f)
Expand Down
22 changes: 11 additions & 11 deletions base/grisu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,10 @@ function _show(io::IO, x::AbstractFloat, mode, n::Int, typed, nanstr, infstr)
exp_form = exp_form || (pt >= len && abs(mod(x + 0.05, 10^(pt - len)) - 0.05) > 0.05) # see issue #6608
if exp_form # .00001 to 100000.
# => #.#######e###
write(io, pdigits, 1)
unsafe_write(io, pdigits, 1)
write(io, '.')
if len > 1
write(io, pdigits+1, len-1)
unsafe_write(io, pdigits+1, len-1)
else
write(io, '0')
end
Expand All @@ -97,19 +97,19 @@ function _show(io::IO, x::AbstractFloat, mode, n::Int, typed, nanstr, infstr)
write(io, '0')
pt += 1
end
write(io, pdigits, len)
unsafe_write(io, pdigits, len)
elseif pt >= len
# => ########00.0
write(io, pdigits, len)
unsafe_write(io, pdigits, len)
while pt > len
write(io, '0')
len += 1
end
write(io, ".0")
else # => ####.####
write(io, pdigits, pt)
unsafe_write(io, pdigits, pt)
write(io, '.')
write(io, pdigits+pt, len-pt)
unsafe_write(io, pdigits+pt, len-pt)
end
typed && isa(x,Float32) && write(io, "f0")
typed && isa(x,Float16) && write(io, ")")
Expand Down Expand Up @@ -144,7 +144,7 @@ function _print_shortest(io::IO, x::AbstractFloat, dot::Bool, mode, n::Int)
k = -9<=e<=9 ? 1 : 2
if -pt > k+1 || e+dot > k+1
# => ########e###
write(io, pdigits+0, len)
unsafe_write(io, pdigits+0, len)
write(io, 'e')
write(io, dec(e))
return
Expand All @@ -155,10 +155,10 @@ function _print_shortest(io::IO, x::AbstractFloat, dot::Bool, mode, n::Int)
write(io, '0')
pt += 1
end
write(io, pdigits+0, len)
unsafe_write(io, pdigits+0, len)
elseif e >= dot
# => ########000.
write(io, pdigits+0, len)
unsafe_write(io, pdigits+0, len)
while e > 0
write(io, '0')
e -= 1
Expand All @@ -167,9 +167,9 @@ function _print_shortest(io::IO, x::AbstractFloat, dot::Bool, mode, n::Int)
write(io, '.')
end
else # => ####.####
write(io, pdigits+0, pt)
unsafe_write(io, pdigits+0, pt)
write(io, '.')
write(io, pdigits+pt, len-pt)
unsafe_write(io, pdigits+pt, len-pt)
end
nothing
end
Expand Down
Loading