Skip to content

Commit 99286f9

Browse files
committed
Do not reinterpret to wrong alignment
This is undefined behavior in LLVM and can actually segfault on real hardware including x86 in certain cases. Also add missing endianess test since it is changed in this commit.
1 parent cff2d75 commit 99286f9

File tree

6 files changed

+63
-28
lines changed

6 files changed

+63
-28
lines changed

base/bitarray.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,11 +283,12 @@ function copy_to_bitarray_chunks!(Bc::Vector{UInt64}, pos_d::Int, C::Array{Bool}
283283
nc8 = (nc >>> 3) << 3
284284
if nc8 > 0
285285
ind8 = 1
286-
C8 = reinterpret(UInt64, unsafe_wrap(Array, pointer(C, ind), nc8 << 6))
286+
P8 = Ptr{UInt64}(pointer(C, ind)) # unaligned i64 pointer
287287
@inbounds for i = 1:nc8
288288
c = UInt64(0)
289289
for j = 0:7
290-
c |= (pack8bools(C8[ind8]) << (j<<3))
290+
# unaligned load
291+
c |= (pack8bools(unsafe_load(P8, ind8)) << (j<<3))
291292
ind8 += 1
292293
end
293294
Bc[bind] = c

base/dSFMT.jl

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,13 @@ end
8989

9090
# dSFMT jump
9191
function dsfmt_jump(s::DSFMT_state, jp::AbstractString)
92-
index = s.val[end-1]
93-
work = zeros(UInt64, JN32>>1)
94-
dsfmt = reinterpret(UInt64, copy(s.val))
92+
val = s.val
93+
nval = length(val)
94+
index = val[nval - 1]
95+
work = zeros(UInt64, JN32 >> 1)
96+
dsfmt = Vector{UInt64}(nval >> 1)
97+
ccall(:memcpy, Ptr{Void}, (Ptr{UInt64}, Ptr{Int32}, Csize_t),
98+
dsfmt, val, (nval - 1) * sizeof(Int32))
9599
dsfmt[end] = UInt64(N*2)
96100

97101
for c in jp

base/io.jl

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -215,29 +215,33 @@ readlines(s=STDIN; chomp::Bool=true) = collect(eachline(s, chomp=chomp))
215215

216216
## byte-order mark, ntoh & hton ##
217217

218+
let endian_boms = reinterpret(UInt8, UInt32[0x01020304])
219+
global ntoh, hton, ltoh, htol
220+
if endian_boms == UInt8[1:4;]
221+
ntoh(x) = x
222+
hton(x) = x
223+
ltoh(x) = bswap(x)
224+
htol(x) = bswap(x)
225+
const global ENDIAN_BOM = 0x01020304
226+
elseif endian_boms == UInt8[4:-1:1;]
227+
ntoh(x) = bswap(x)
228+
hton(x) = bswap(x)
229+
ltoh(x) = x
230+
htol(x) = x
231+
const global ENDIAN_BOM = 0x04030201
232+
else
233+
error("seriously? what is this machine?")
234+
end
235+
end
236+
218237
"""
219238
ENDIAN_BOM
220239
221240
The 32-bit byte-order-mark indicates the native byte order of the host machine.
222241
Little-endian machines will contain the value `0x04030201`. Big-endian machines will contain
223242
the value `0x01020304`.
224243
"""
225-
const ENDIAN_BOM = reinterpret(UInt32,UInt8[1:4;])[1]
226-
227-
if ENDIAN_BOM == 0x01020304
228-
ntoh(x) = x
229-
hton(x) = x
230-
ltoh(x) = bswap(x)
231-
htol(x) = bswap(x)
232-
elseif ENDIAN_BOM == 0x04030201
233-
ntoh(x) = bswap(x)
234-
hton(x) = bswap(x)
235-
ltoh(x) = x
236-
htol(x) = x
237-
else
238-
error("seriously? what is this machine?")
239-
end
240-
244+
ENDIAN_BOM
241245

242246
"""
243247
ntoh(x)

base/pcre.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,18 +69,18 @@ const OPTIONS_MASK = COMPILE_MASK | EXECUTE_MASK
6969

7070
const UNSET = ~Csize_t(0) # Indicates that an output vector element is unset
7171

72-
function info(regex::Ptr{Void}, what::Integer, T)
73-
buf = zeros(UInt8,sizeof(T))
72+
function info(regex::Ptr{Void}, what::Integer, ::Type{T}) where T
73+
buf = Ref{T}()
7474
ret = ccall((:pcre2_pattern_info_8, PCRE_LIB), Int32,
75-
(Ptr{Void}, Int32, Ptr{UInt8}),
75+
(Ptr{Void}, Int32, Ptr{Void}),
7676
regex, what, buf)
7777
if ret != 0
7878
error(ret == ERROR_NULL ? "NULL regex object" :
7979
ret == ERROR_BADMAGIC ? "invalid regex object" :
8080
ret == ERROR_BADOPTION ? "invalid option flags" :
8181
"unknown error $ret")
8282
end
83-
reinterpret(T,buf)[1]
83+
buf[]
8484
end
8585

8686
function get_ovec(match_data)

test/core.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4848,12 +4848,15 @@ end
48484848
let ni128 = sizeof(FP128test) ÷ sizeof(Int),
48494849
ns128 = sizeof(FP128align) ÷ sizeof(Int),
48504850
nbit = sizeof(Int) * 8,
4851-
arr = reinterpret(FP128align, collect(Int, 1:(2 * ns128))),
4851+
arr = Vector{FP128align}(2),
48524852
offset = Base.datatype_alignment(FP128test) ÷ sizeof(Int),
48534853
little,
4854-
expected
4854+
expected,
4855+
arrint = reinterpret(Int, arr)
4856+
4857+
@test length(arrint) == 2 * ns128
4858+
arrint .= 1:(2 * ns128)
48554859
@test sizeof(FP128test) == 16
4856-
@test length(arr) == 2
48574860
@test arr[1].i == 1
48584861
@test arr[2].i == 1 + ns128
48594862
expected = UInt128(0)

test/misc.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,3 +678,26 @@ let foo() = begin
678678
end
679679
@test foo() == 2
680680
end
681+
682+
# Endian tests
683+
# For now, we only support little endian.
684+
# Add an `Sys.ARCH` test for big endian when/if we add support for that.
685+
# Do **NOT** use `ENDIAN_BOM` to figure out the endianess
686+
# since that's exactly what we want to test.
687+
@test ENDIAN_BOM == 0x04030201
688+
@test ntoh(0x1) == 0x1
689+
@test hton(0x1) == 0x1
690+
@test ltoh(0x1) == 0x1
691+
@test htol(0x1) == 0x1
692+
@test ntoh(0x102) == 0x201
693+
@test hton(0x102) == 0x201
694+
@test ltoh(0x102) == 0x102
695+
@test htol(0x102) == 0x102
696+
@test ntoh(0x1020304) == 0x4030201
697+
@test hton(0x1020304) == 0x4030201
698+
@test ltoh(0x1020304) == 0x1020304
699+
@test htol(0x1020304) == 0x1020304
700+
@test ntoh(0x102030405060708) == 0x807060504030201
701+
@test hton(0x102030405060708) == 0x807060504030201
702+
@test ltoh(0x102030405060708) == 0x102030405060708
703+
@test htol(0x102030405060708) == 0x102030405060708

0 commit comments

Comments
 (0)