mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-04 11:07:46 +00:00
reflect: fix (u)int -> string conversions for invalid code points
This commit is contained in:
committed by
Damian Gryski
parent
e111b489ec
commit
364ac2dcb2
@@ -1690,20 +1690,27 @@ func makeComplex(flags valueFlags, f complex128, t *RawType) Value {
|
||||
func stringFromUnicode(x rune) string
|
||||
|
||||
func cvtIntString(v Value, t *RawType) Value {
|
||||
b := stringFromUnicode(rune(v.Int()))
|
||||
s := "\uFFFD"
|
||||
if x := v.Int(); int64(rune(x)) == x {
|
||||
s = string(rune(x))
|
||||
}
|
||||
return Value{
|
||||
typecode: t,
|
||||
value: unsafe.Pointer(&b),
|
||||
flags: v.flags,
|
||||
value: unsafe.Pointer(&s),
|
||||
flags: v.flags | valueFlagRO,
|
||||
}
|
||||
}
|
||||
|
||||
func cvtUintString(v Value, t *RawType) Value {
|
||||
b := stringFromUnicode(rune(v.Uint()))
|
||||
s := "\uFFFD"
|
||||
if x := v.Uint(); uint64(rune(x)) == x {
|
||||
s = string(rune(x))
|
||||
}
|
||||
|
||||
return Value{
|
||||
typecode: t,
|
||||
value: unsafe.Pointer(&b),
|
||||
flags: v.flags,
|
||||
value: unsafe.Pointer(&s),
|
||||
flags: v.flags | valueFlagRO,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -189,6 +189,86 @@ func TestTinyConvert(t *testing.T) {
|
||||
{V(complex64(2i)), V(complex128(2i))},
|
||||
{V(complex128(3i)), V(complex64(3i))},
|
||||
{V(complex128(4i)), V(complex128(4i))},
|
||||
|
||||
// string
|
||||
{V(string("hello")), V(string("hello"))},
|
||||
{V(string("bytes1")), V([]byte("bytes1"))},
|
||||
{V([]byte("bytes2")), V(string("bytes2"))},
|
||||
{V([]byte("bytes3")), V([]byte("bytes3"))},
|
||||
{V(string("runes♝")), V([]rune("runes♝"))},
|
||||
{V([]rune("runes♕")), V(string("runes♕"))},
|
||||
{V([]rune("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))},
|
||||
{V(int('a')), V(string("a"))},
|
||||
{V(int8('a')), V(string("a"))},
|
||||
{V(int16('a')), V(string("a"))},
|
||||
{V(int32('a')), V(string("a"))},
|
||||
{V(int64('a')), V(string("a"))},
|
||||
{V(uint('a')), V(string("a"))},
|
||||
{V(uint8('a')), V(string("a"))},
|
||||
{V(uint16('a')), V(string("a"))},
|
||||
{V(uint32('a')), V(string("a"))},
|
||||
{V(uint64('a')), V(string("a"))},
|
||||
{V(uintptr('a')), V(string("a"))},
|
||||
{V(int(-1)), V(string("\uFFFD"))},
|
||||
{V(int8(-2)), V(string("\uFFFD"))},
|
||||
{V(int16(-3)), V(string("\uFFFD"))},
|
||||
{V(int32(-4)), V(string("\uFFFD"))},
|
||||
{V(int64(-5)), V(string("\uFFFD"))},
|
||||
{V(int64(-1 << 32)), V(string("\uFFFD"))},
|
||||
{V(int64(1 << 32)), V(string("\uFFFD"))},
|
||||
{V(uint(0x110001)), V(string("\uFFFD"))},
|
||||
{V(uint32(0x110002)), V(string("\uFFFD"))},
|
||||
{V(uint64(0x110003)), V(string("\uFFFD"))},
|
||||
{V(uint64(1 << 32)), V(string("\uFFFD"))},
|
||||
{V(uintptr(0x110004)), V(string("\uFFFD"))},
|
||||
|
||||
// named string
|
||||
{V(MyString("hello")), V(string("hello"))},
|
||||
{V(string("hello")), V(MyString("hello"))},
|
||||
{V(string("hello")), V(string("hello"))},
|
||||
{V(MyString("hello")), V(MyString("hello"))},
|
||||
{V(MyString("bytes1")), V([]byte("bytes1"))},
|
||||
{V([]byte("bytes2")), V(MyString("bytes2"))},
|
||||
{V([]byte("bytes3")), V([]byte("bytes3"))},
|
||||
{V(MyString("runes♝")), V([]rune("runes♝"))},
|
||||
{V([]rune("runes♕")), V(MyString("runes♕"))},
|
||||
{V([]rune("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))},
|
||||
{V([]rune("runes🙈🙉🙊")), V(MyRunes("runes🙈🙉🙊"))},
|
||||
{V(MyRunes("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))},
|
||||
{V(int('a')), V(MyString("a"))},
|
||||
{V(int8('a')), V(MyString("a"))},
|
||||
{V(int16('a')), V(MyString("a"))},
|
||||
{V(int32('a')), V(MyString("a"))},
|
||||
{V(int64('a')), V(MyString("a"))},
|
||||
{V(uint('a')), V(MyString("a"))},
|
||||
{V(uint8('a')), V(MyString("a"))},
|
||||
{V(uint16('a')), V(MyString("a"))},
|
||||
{V(uint32('a')), V(MyString("a"))},
|
||||
{V(uint64('a')), V(MyString("a"))},
|
||||
{V(uintptr('a')), V(MyString("a"))},
|
||||
{V(int(-1)), V(MyString("\uFFFD"))},
|
||||
{V(int8(-2)), V(MyString("\uFFFD"))},
|
||||
{V(int16(-3)), V(MyString("\uFFFD"))},
|
||||
{V(int32(-4)), V(MyString("\uFFFD"))},
|
||||
{V(int64(-5)), V(MyString("\uFFFD"))},
|
||||
{V(uint(0x110001)), V(MyString("\uFFFD"))},
|
||||
{V(uint32(0x110002)), V(MyString("\uFFFD"))},
|
||||
{V(uint64(0x110003)), V(MyString("\uFFFD"))},
|
||||
{V(uintptr(0x110004)), V(MyString("\uFFFD"))},
|
||||
|
||||
// named []byte
|
||||
{V(string("bytes1")), V(MyBytes("bytes1"))},
|
||||
{V(MyBytes("bytes2")), V(string("bytes2"))},
|
||||
{V(MyBytes("bytes3")), V(MyBytes("bytes3"))},
|
||||
{V(MyString("bytes1")), V(MyBytes("bytes1"))},
|
||||
{V(MyBytes("bytes2")), V(MyString("bytes2"))},
|
||||
|
||||
// named []rune
|
||||
{V(string("runes♝")), V(MyRunes("runes♝"))},
|
||||
{V(MyRunes("runes♕")), V(string("runes♕"))},
|
||||
{V(MyRunes("runes🙈🙉🙊")), V(MyRunes("runes🙈🙉🙊"))},
|
||||
{V(MyString("runes♝")), V(MyRunes("runes♝"))},
|
||||
{V(MyRunes("runes♕")), V(MyString("runes♕"))},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
@@ -153,7 +153,9 @@ func stringNext(s string, it *stringIterator) (bool, int, rune) {
|
||||
}
|
||||
|
||||
// Convert a Unicode code point into an array of bytes and its length.
|
||||
func encodeUTF8(x rune) ([4]byte, uintptr) {
|
||||
func encodeUTF8(r rune) ([4]byte, uintptr) {
|
||||
x := uint32(r)
|
||||
|
||||
// https://stackoverflow.com/questions/6240055/manually-converting-unicode-codepoints-into-utf-8-and-utf-16
|
||||
// Note: this code can probably be optimized (in size and speed).
|
||||
switch {
|
||||
|
||||
Reference in New Issue
Block a user