Skip to content

Commit

Permalink
check overflow in hex2num (fix #22031)
Browse files Browse the repository at this point in the history
  • Loading branch information
rfourquet committed May 23, 2017
1 parent cfa1999 commit eedbb7a
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 62 deletions.
49 changes: 0 additions & 49 deletions base/docs/helpdb/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -76,21 +76,6 @@ Subtraction operator.
"""
-(x, y)

"""
bits(n)
A string giving the literal bit representation of a number.
```jldoctest
julia> bits(4)
"0000000000000000000000000000000000000000000000000000000000000100"
julia> bits(2.2)
"0100000000000001100110011001100110011001100110011001100110011010"
```
"""
bits

"""
getindex(type[, elements...])
Expand Down Expand Up @@ -565,18 +550,6 @@ original string, otherwise they must be from distinct character ranges.
"""
eachmatch

"""
num2hex(f)
Get a hexadecimal string of the binary representation of a floating point number.
```jldoctest
julia> num2hex(2.2)
"400199999999999a"
```
"""
num2hex

"""
truncate(file,n)
Expand Down Expand Up @@ -1121,13 +1094,6 @@ julia> bin(bswap(1))
"""
bswap

"""
maxintfloat(T)
The largest integer losslessly representable by the given floating-point DataType `T`.
"""
maxintfloat

"""
delete!(collection, key)
Expand Down Expand Up @@ -1360,13 +1326,6 @@ false
"""
isempty

"""
hex2num(str)
Convert a hexadecimal string to the floating point number it represents.
"""
hex2num

"""
InexactError()
Expand Down Expand Up @@ -2177,14 +2136,6 @@ Values for `String` can be of that type, or `Vector{UInt8}`.
"""
isvalid(T,value)

"""
unsigned(x) -> Unsigned
Convert a number to an unsigned integer. If the argument is signed, it is reinterpreted as
unsigned without checking for negative values.
"""
unsigned

"""
reverseind(v, i)
Expand Down
18 changes: 18 additions & 0 deletions base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,24 @@ convert(::Type{T}, x::T) where {T<:Tuple{Any,Vararg{Any}}} = x

oftype(x,c) = convert(typeof(x),c)

"""
unsigned(x) -> Unsigned
Convert a number to an unsigned integer. If the argument is signed, it is reinterpreted as
unsigned without checking for negative values.
unsigned(T::Type) -> UnsignedType
Return the return-type of unsigned(x::T).
```jldoctest
julia> unsigned(12)
0x000000000000000c
julia> unsigned(Int)
UInt64
```
"""
unsigned(x::Int) = reinterpret(UInt, x)
signed(x::UInt) = reinterpret(Int, x)

Expand Down
19 changes: 8 additions & 11 deletions base/floatfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ signbit(x::Float64) = signbit(bitcast(Int64, x))
signbit(x::Float32) = signbit(bitcast(Int32, x))
signbit(x::Float16) = signbit(bitcast(Int16, x))

"""
maxintfloat(T)
The largest integer losslessly representable by the given floating-point DataType `T`.
"""
maxintfloat(::Type{Float64}) = 9007199254740992.
maxintfloat(::Type{Float32}) = Float32(16777216.)
maxintfloat(::Type{Float16}) = Float16(2048f0)
Expand All @@ -24,18 +29,10 @@ maxintfloat() = maxintfloat(Float64)

isinteger(x::AbstractFloat) = (x - trunc(x) == 0)

num2hex(x::Float16) = hex(bitcast(UInt16, x), 4)
num2hex(x::Float32) = hex(bitcast(UInt32, x), 8)
num2hex(x::Float64) = hex(bitcast(UInt64, x), 16)

function hex2num(s::AbstractString)
if length(s) <= 4
return bitcast(Float16, parse(UInt16, s, 16))
end
if length(s) <= 8
return bitcast(Float32, parse(UInt32, s, 16))
end
return bitcast(Float64, parse(UInt64, s, 16))
l = length(s)
l > 16 && throw(ArgumentError("the passed string must be of length <= 16, got $l"))
hex2num(l <= 4 ? Float16 : l <= 8 ? Float32 : Float64, s)
end

"""
Expand Down
8 changes: 8 additions & 0 deletions base/int.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ const BitInteger = Union{BitInteger_types...}
const BitSigned64T = Union{Type{Int8}, Type{Int16}, Type{Int32}, Type{Int64}}
const BitUnsigned64T = Union{Type{UInt8}, Type{UInt16}, Type{UInt32}, Type{UInt64}}

const BitFloat_types = (Float16, Float32, Float64)
const BitFloat = Union{BitFloat_types...}
const BitReal_types = (BitInteger_types..., BitFloat_types...)
const BitReal = Union{BitReal_types...}

reinterpret(::Type{Unsigned}, x::BitInteger) = unsigned(x)


## integer comparisons ##

(<)(x::T, y::T) where {T<:BitSigned} = slt_int(x, y)
Expand Down
58 changes: 57 additions & 1 deletion base/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,48 @@ function hex(x::Unsigned, pad::Int, neg::Bool)
String(a)
end

num2hex(n::Integer) = hex(n, sizeof(n)*2)
"""
num2hex(f)
An hexadecimal string of the binary representation of a number.
See also the [`bits`](@ref) function, which is similar but gives
a binary string.
```jldoctest
julia> num2hex(Int64(4))
"0000000000000004"
julia> num2hex(2.2)
"400199999999999a"
```
"""
num2hex(n::BitReal) = hex(reinterpret(Unsigned, n), sizeof(n)*2)
num2hex(n::Bool) = hex(n)

"""
hex2num(T::Type, str)
Interprets a hexadecimal string as the bit representation of a
number of type `T`. See also [`num2hex`](@ref).
```jldoctest
julia> hex2num(Float64, "400199999999999a")
2.2
julia> hex2num(Int32, "fffffffe")
-2
```
hex2num(str)
Convert a hexadecimal string to the floating point number it represents.
This function, which is inherently type-unstable, returns a `Float16`,
a `Float32`, or a `Float64` depending on the length of the string `str`
(note that this length must hence be no greater than 16).
"""
hex2num(::Type{T}, s::AbstractString) where {T<:BitReal} =
reinterpret(T, parse(unsigned(T), s, 16))

const base36digits = ['0':'9';'a':'z']
const base62digits = ['0':'9';'A':'Z';'a':'z']
Expand Down Expand Up @@ -573,6 +614,21 @@ Convert an integer to a decimal string, optionally specifying a number of digits
"""
dec

"""
bits(n)
A string giving the literal bit representation of a number.
See also the [`num2hex`](@ref) function, which is similar but
gives an hexadecimal string.
```jldoctest
julia> bits(4)
"0000000000000000000000000000000000000000000000000000000000000100"
julia> bits(2.2)
"0100000000000001100110011001100110011001100110011001100110011010"
```
"""
bits(x::Union{Bool,Int8,UInt8}) = bin(reinterpret(UInt8,x),8)
bits(x::Union{Int16,UInt16,Float16}) = bin(reinterpret(UInt16,x),16)
bits(x::Union{Char,Int32,UInt32,Float32}) = bin(reinterpret(UInt32,x),32)
Expand Down
5 changes: 4 additions & 1 deletion base/multinverses.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ unsigned(::Type{Int16}) = UInt16
unsigned(::Type{Int32}) = UInt32
unsigned(::Type{Int64}) = UInt64
unsigned(::Type{Int128}) = UInt128
unsigned{T<:Unsigned}(::Type{T}) = T
unsigned(::Type{T}) where {T<:Unsigned} = T
unsigned(::Type{Float16}) = UInt16
unsigned(::Type{Float32}) = UInt32
unsigned(::Type{Float64}) = UInt64

abstract type MultiplicativeInverse{T} end

Expand Down
2 changes: 2 additions & 0 deletions test/floatfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ end
for elty in (Float16,Float32,Float64), _ = 1:10
x = rand(elty)
@test hex2num(num2hex(x)) x
@test hex2num(elty, num2hex(x)) x
end
@test_throws ArgumentError hex2num(String(rand('a':'f', rand(17:100))))

# round
for elty in (Float32,Float64)
Expand Down
8 changes: 8 additions & 0 deletions test/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,14 @@ end
@test hex(12) == "c"
@test hex(-12, 3) == "-00c"
@test num2hex(1243) == (Int == Int32 ? "000004db" : "00000000000004db")
@test num2hex(-1243) == (Int == Int32 ? "fffffb25" : "fffffffffffffb25")
@test num2hex(true) == "1"
@test num2hex(false) == "0"

for elty in Base.BitInteger_types, _ = 1:10
x = rand(elty)
@test hex2num(elty, num2hex(x)) == x
end

@test base(2, 5, 7) == "0000101"

Expand Down

0 comments on commit eedbb7a

Please sign in to comment.