Skip to content

Commit

Permalink
fix reinterpret(Char, ::UInt32) for "unnatural" values (fix #29181) (#…
Browse files Browse the repository at this point in the history
…29192)

This code was assuming that character values only have bit-patterns
that decoding a string can produce, but of course `reinterpret` can
produce any bit pattern in a `Char` whatsoever. The fix doesn't use
that assumption and only uses the cache for actual ASCII characters.
  • Loading branch information
StefanKarpinski authored Sep 17, 2018
1 parent 1324ceb commit 88f74b7
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 9 deletions.
5 changes: 3 additions & 2 deletions src/datatype.c
Original file line number Diff line number Diff line change
Expand Up @@ -689,8 +689,9 @@ static jl_value_t *boxed_char_cache[128];
JL_DLLEXPORT jl_value_t *jl_box_char(uint32_t x)
{
jl_ptls_t ptls = jl_get_ptls_states();
if (0 < (int32_t)x)
return boxed_char_cache[x >> 24];
uint32_t u = bswap_32(x);
if (u < 128)
return boxed_char_cache[(uint8_t)u];
jl_value_t *v = jl_gc_alloc(ptls, sizeof(void*), jl_char_type);
*(uint32_t*)jl_data_ptr(v) = x;
return v;
Expand Down
21 changes: 14 additions & 7 deletions test/char.jl
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,18 @@ end
@test ncodeunits('\U10ffff') == 4
# invalid encodings
@test ncodeunits(reinterpret(Char, 0x80_00_00_00)) == 1
@test ncodeunits(reinterpret(Char, 0x81_00_00_00)) == 1
@test ncodeunits(reinterpret(Char, 0x80_80_00_00)) == 2
@test ncodeunits(reinterpret(Char, 0x80_01_00_00)) == 2
@test ncodeunits(reinterpret(Char, 0x80_00_80_00)) == 3
@test ncodeunits(reinterpret(Char, 0x80_00_01_00)) == 3
@test ncodeunits(reinterpret(Char, 0x80_00_00_80)) == 4
@test ncodeunits(reinterpret(Char, 0x80_00_00_01)) == 4
@test ncodeunits(reinterpret(Char, 0x01_00_00_00)) == 1
@test ncodeunits(reinterpret(Char, 0x00_80_00_00)) == 2
@test ncodeunits(reinterpret(Char, 0x00_01_00_00)) == 2
@test ncodeunits(reinterpret(Char, 0x00_00_80_00)) == 3
@test ncodeunits(reinterpret(Char, 0x00_00_01_00)) == 3
@test ncodeunits(reinterpret(Char, 0x00_00_00_80)) == 4
@test ncodeunits(reinterpret(Char, 0x00_00_00_01)) == 4
end

@testset "reinterpret(Char, ::UInt32)" begin
for s = 0:31
u = one(UInt32) << s
@test reinterpret(UInt32, reinterpret(Char, u)) === u
end
end

0 comments on commit 88f74b7

Please sign in to comment.