mirror of https://github.com/goccy/go-json.git
Remove all usages of reflect.SliceHeader
There're some problem with current usage of reflect.SliceHeader. First, it violates the unsafe pointer conversion (rule 6th), that said, reflect.SliceHeader must not used as plain struct. Second, the lowest version that go-json supports, go1.12, reflect package did not use SliceHeader in typedslicecopy, but use the safety version. There's no reason that go-json continue using them. See: - https://golang.org/pkg/unsafe/#Pointer - https://github.com/golang/go/blob/release-branch.go1.12/src/reflect/value.go#L2702
This commit is contained in:
parent
71cddb3168
commit
e58b1eabaf
|
@ -1,7 +1,6 @@
|
|||
package json
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
@ -51,7 +50,7 @@ func (d *sliceDecoder) releaseSlice(p *sliceHeader) {
|
|||
}
|
||||
|
||||
//go:linkname copySlice reflect.typedslicecopy
|
||||
func copySlice(elemType *rtype, dst, src reflect.SliceHeader) int
|
||||
func copySlice(elemType *rtype, dst, src sliceHeader) int
|
||||
|
||||
//go:linkname newArray reflect.unsafe_NewArray
|
||||
func newArray(*rtype, int) unsafe.Pointer
|
||||
|
@ -71,10 +70,10 @@ func (d *sliceDecoder) decodeStream(s *stream, p uintptr) error {
|
|||
s.cursor++
|
||||
s.skipWhiteSpace()
|
||||
if s.char() == ']' {
|
||||
*(*reflect.SliceHeader)(unsafe.Pointer(p)) = reflect.SliceHeader{
|
||||
Data: uintptr(newArray(d.elemType, 0)),
|
||||
Len: 0,
|
||||
Cap: 0,
|
||||
*(*sliceHeader)(unsafe.Pointer(p)) = sliceHeader{
|
||||
data: newArray(d.elemType, 0),
|
||||
len: 0,
|
||||
cap: 0,
|
||||
}
|
||||
s.cursor++
|
||||
return nil
|
||||
|
@ -85,10 +84,10 @@ func (d *sliceDecoder) decodeStream(s *stream, p uintptr) error {
|
|||
data := slice.data
|
||||
for {
|
||||
if cap <= idx {
|
||||
src := reflect.SliceHeader{Data: uintptr(data), Len: idx, Cap: cap}
|
||||
src := sliceHeader{data: data, len: idx, cap: cap}
|
||||
cap *= 2
|
||||
data = newArray(d.elemType, cap)
|
||||
dst := reflect.SliceHeader{Data: uintptr(data), Len: idx, Cap: cap}
|
||||
dst := sliceHeader{data: data, len: idx, cap: cap}
|
||||
copySlice(d.elemType, dst, src)
|
||||
}
|
||||
if err := d.valueDecoder.decodeStream(s, uintptr(data)+uintptr(idx)*d.size); err != nil {
|
||||
|
@ -102,17 +101,17 @@ func (d *sliceDecoder) decodeStream(s *stream, p uintptr) error {
|
|||
slice.len = idx + 1
|
||||
slice.data = data
|
||||
dstCap := idx + 1
|
||||
dst := reflect.SliceHeader{
|
||||
Data: uintptr(newArray(d.elemType, dstCap)),
|
||||
Len: idx + 1,
|
||||
Cap: dstCap,
|
||||
dst := sliceHeader{
|
||||
data: newArray(d.elemType, dstCap),
|
||||
len: idx + 1,
|
||||
cap: dstCap,
|
||||
}
|
||||
copySlice(d.elemType, dst, reflect.SliceHeader{
|
||||
Data: uintptr(slice.data),
|
||||
Len: slice.len,
|
||||
Cap: slice.cap,
|
||||
copySlice(d.elemType, dst, sliceHeader{
|
||||
data: slice.data,
|
||||
len: slice.len,
|
||||
cap: slice.cap,
|
||||
})
|
||||
*(*reflect.SliceHeader)(unsafe.Pointer(p)) = dst
|
||||
*(*sliceHeader)(unsafe.Pointer(p)) = dst
|
||||
d.releaseSlice(slice)
|
||||
s.cursor++
|
||||
return nil
|
||||
|
@ -171,10 +170,10 @@ func (d *sliceDecoder) decode(buf []byte, cursor int64, p uintptr) (int64, error
|
|||
cursor++
|
||||
cursor = skipWhiteSpace(buf, cursor)
|
||||
if buf[cursor] == ']' {
|
||||
*(*reflect.SliceHeader)(unsafe.Pointer(p)) = reflect.SliceHeader{
|
||||
Data: uintptr(newArray(d.elemType, 0)),
|
||||
Len: 0,
|
||||
Cap: 0,
|
||||
*(*sliceHeader)(unsafe.Pointer(p)) = sliceHeader{
|
||||
data: newArray(d.elemType, 0),
|
||||
len: 0,
|
||||
cap: 0,
|
||||
}
|
||||
cursor++
|
||||
return cursor, nil
|
||||
|
@ -185,10 +184,10 @@ func (d *sliceDecoder) decode(buf []byte, cursor int64, p uintptr) (int64, error
|
|||
data := slice.data
|
||||
for {
|
||||
if cap <= idx {
|
||||
src := reflect.SliceHeader{Data: uintptr(data), Len: idx, Cap: cap}
|
||||
src := sliceHeader{data: data, len: idx, cap: cap}
|
||||
cap *= 2
|
||||
data = newArray(d.elemType, cap)
|
||||
dst := reflect.SliceHeader{Data: uintptr(data), Len: idx, Cap: cap}
|
||||
dst := sliceHeader{data: data, len: idx, cap: cap}
|
||||
copySlice(d.elemType, dst, src)
|
||||
}
|
||||
c, err := d.valueDecoder.decode(buf, cursor, uintptr(data)+uintptr(idx)*d.size)
|
||||
|
@ -203,17 +202,17 @@ func (d *sliceDecoder) decode(buf []byte, cursor int64, p uintptr) (int64, error
|
|||
slice.len = idx + 1
|
||||
slice.data = data
|
||||
dstCap := idx + 1
|
||||
dst := reflect.SliceHeader{
|
||||
Data: uintptr(newArray(d.elemType, dstCap)),
|
||||
Len: idx + 1,
|
||||
Cap: dstCap,
|
||||
dst := sliceHeader{
|
||||
data: newArray(d.elemType, dstCap),
|
||||
len: idx + 1,
|
||||
cap: dstCap,
|
||||
}
|
||||
copySlice(d.elemType, dst, reflect.SliceHeader{
|
||||
Data: uintptr(slice.data),
|
||||
Len: slice.len,
|
||||
Cap: slice.cap,
|
||||
copySlice(d.elemType, dst, sliceHeader{
|
||||
data: slice.data,
|
||||
len: slice.len,
|
||||
cap: slice.cap,
|
||||
})
|
||||
*(*reflect.SliceHeader)(unsafe.Pointer(p)) = dst
|
||||
*(*sliceHeader)(unsafe.Pointer(p)) = dst
|
||||
d.releaseSlice(slice)
|
||||
cursor++
|
||||
return cursor, nil
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package json
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
|
@ -95,6 +94,6 @@ func (c *encodeRuntimeContext) init(p uintptr) {
|
|||
}
|
||||
|
||||
func (c *encodeRuntimeContext) ptr() uintptr {
|
||||
header := (*reflect.SliceHeader)(unsafe.Pointer(&c.ptrs))
|
||||
return header.Data
|
||||
header := (*sliceHeader)(unsafe.Pointer(&c.ptrs))
|
||||
return uintptr(header.data)
|
||||
}
|
||||
|
|
60
encode_vm.go
60
encode_vm.go
|
@ -175,8 +175,8 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
|
|||
code = code.next
|
||||
case opBytes:
|
||||
ptr := load(ctxptr, code.idx)
|
||||
header := (*reflect.SliceHeader)(unsafe.Pointer(ptr))
|
||||
if ptr == 0 || header.Data == 0 {
|
||||
header := (*sliceHeader)(unsafe.Pointer(ptr))
|
||||
if ptr == 0 || uintptr(header.data) == 0 {
|
||||
e.encodeNull()
|
||||
} else {
|
||||
e.encodeByteSlice(e.ptrToBytes(ptr))
|
||||
|
@ -498,19 +498,19 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
|
|||
code = code.next
|
||||
case opSliceHead:
|
||||
p := load(ctxptr, code.idx)
|
||||
header := (*reflect.SliceHeader)(unsafe.Pointer(p))
|
||||
if p == 0 || header.Data == 0 {
|
||||
header := (*sliceHeader)(unsafe.Pointer(p))
|
||||
if p == 0 || uintptr(header.data) == 0 {
|
||||
e.encodeNull()
|
||||
e.encodeByte(',')
|
||||
code = code.end.next
|
||||
} else {
|
||||
store(ctxptr, code.elemIdx, 0)
|
||||
store(ctxptr, code.length, uintptr(header.Len))
|
||||
store(ctxptr, code.idx, header.Data)
|
||||
if header.Len > 0 {
|
||||
store(ctxptr, code.length, uintptr(header.len))
|
||||
store(ctxptr, code.idx, uintptr(header.data))
|
||||
if header.len > 0 {
|
||||
e.encodeByte('[')
|
||||
code = code.next
|
||||
store(ctxptr, code.idx, header.Data)
|
||||
store(ctxptr, code.idx, uintptr(header.data))
|
||||
} else {
|
||||
e.encodeBytes([]byte{'[', ']', ','})
|
||||
code = code.end.next
|
||||
|
@ -540,15 +540,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
|
|||
e.encodeBytes([]byte{',', '\n'})
|
||||
code = code.end.next
|
||||
} else {
|
||||
header := (*reflect.SliceHeader)(unsafe.Pointer(p))
|
||||
header := (*sliceHeader)(unsafe.Pointer(p))
|
||||
store(ctxptr, code.elemIdx, 0)
|
||||
store(ctxptr, code.length, uintptr(header.Len))
|
||||
store(ctxptr, code.idx, header.Data)
|
||||
if header.Len > 0 {
|
||||
store(ctxptr, code.length, uintptr(header.len))
|
||||
store(ctxptr, code.idx, uintptr(header.data))
|
||||
if header.len > 0 {
|
||||
e.encodeBytes([]byte{'[', '\n'})
|
||||
e.encodeIndent(code.indent + 1)
|
||||
code = code.next
|
||||
store(ctxptr, code.idx, header.Data)
|
||||
store(ctxptr, code.idx, uintptr(header.data))
|
||||
} else {
|
||||
e.encodeIndent(code.indent)
|
||||
e.encodeBytes([]byte{'[', ']', '\n'})
|
||||
|
@ -563,15 +563,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
|
|||
e.encodeBytes([]byte{',', '\n'})
|
||||
code = code.end.next
|
||||
} else {
|
||||
header := (*reflect.SliceHeader)(unsafe.Pointer(p))
|
||||
header := (*sliceHeader)(unsafe.Pointer(p))
|
||||
store(ctxptr, code.elemIdx, 0)
|
||||
store(ctxptr, code.length, uintptr(header.Len))
|
||||
store(ctxptr, code.idx, header.Data)
|
||||
if header.Len > 0 {
|
||||
store(ctxptr, code.length, uintptr(header.len))
|
||||
store(ctxptr, code.idx, uintptr(header.data))
|
||||
if header.len > 0 {
|
||||
e.encodeBytes([]byte{'[', '\n'})
|
||||
e.encodeIndent(code.indent + 1)
|
||||
code = code.next
|
||||
store(ctxptr, code.idx, header.Data)
|
||||
store(ctxptr, code.idx, uintptr(header.data))
|
||||
} else {
|
||||
e.encodeIndent(code.indent)
|
||||
e.encodeBytes([]byte{'[', ']', ',', '\n'})
|
||||
|
@ -5229,8 +5229,8 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
|
|||
e.encodeByte(' ')
|
||||
ptr := load(ctxptr, code.headIdx)
|
||||
p := ptr + code.offset
|
||||
header := (*reflect.SliceHeader)(unsafe.Pointer(p))
|
||||
if p == 0 || header.Data == 0 {
|
||||
header := (*sliceHeader)(unsafe.Pointer(p))
|
||||
if p == 0 || uintptr(header.data) == 0 {
|
||||
e.encodeNull()
|
||||
e.encodeBytes([]byte{',', '\n'})
|
||||
code = code.nextField
|
||||
|
@ -5243,8 +5243,8 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
|
|||
e.encodeByte(' ')
|
||||
ptr := load(ctxptr, code.headIdx)
|
||||
p := ptr + code.offset
|
||||
header := (*reflect.SliceHeader)(unsafe.Pointer(p))
|
||||
if p == 0 || header.Data == 0 {
|
||||
header := (*sliceHeader)(unsafe.Pointer(p))
|
||||
if p == 0 || uintptr(header.data) == 0 {
|
||||
e.encodeNull()
|
||||
e.encodeBytes([]byte{',', '\n'})
|
||||
code = code.nextField
|
||||
|
@ -5509,8 +5509,8 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
|
|||
case opStructFieldOmitEmptyArray:
|
||||
ptr := load(ctxptr, code.headIdx)
|
||||
p := ptr + code.offset
|
||||
header := (*reflect.SliceHeader)(unsafe.Pointer(p))
|
||||
if p == 0 || header.Data == 0 {
|
||||
header := (*sliceHeader)(unsafe.Pointer(p))
|
||||
if p == 0 || uintptr(header.data) == 0 {
|
||||
code = code.nextField
|
||||
} else {
|
||||
code = code.next
|
||||
|
@ -5518,8 +5518,8 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
|
|||
case opStructFieldOmitEmptySlice:
|
||||
ptr := load(ctxptr, code.headIdx)
|
||||
p := ptr + code.offset
|
||||
header := (*reflect.SliceHeader)(unsafe.Pointer(p))
|
||||
if p == 0 || header.Data == 0 {
|
||||
header := (*sliceHeader)(unsafe.Pointer(p))
|
||||
if p == 0 || uintptr(header.data) == 0 {
|
||||
code = code.nextField
|
||||
} else {
|
||||
code = code.next
|
||||
|
@ -5740,8 +5740,8 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
|
|||
case opStructFieldOmitEmptyArrayIndent:
|
||||
ptr := load(ctxptr, code.headIdx)
|
||||
p := ptr + code.offset
|
||||
header := (*reflect.SliceHeader)(unsafe.Pointer(p))
|
||||
if p == 0 || header.Data == 0 {
|
||||
header := (*sliceHeader)(unsafe.Pointer(p))
|
||||
if p == 0 || uintptr(header.data) == 0 {
|
||||
code = code.nextField
|
||||
} else {
|
||||
e.encodeIndent(code.indent)
|
||||
|
@ -5752,8 +5752,8 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, code *opcode) error {
|
|||
case opStructFieldOmitEmptySliceIndent:
|
||||
ptr := load(ctxptr, code.headIdx)
|
||||
p := ptr + code.offset
|
||||
header := (*reflect.SliceHeader)(unsafe.Pointer(p))
|
||||
if p == 0 || header.Data == 0 {
|
||||
header := (*sliceHeader)(unsafe.Pointer(p))
|
||||
if p == 0 || uintptr(header.data) == 0 {
|
||||
code = code.nextField
|
||||
} else {
|
||||
e.encodeIndent(code.indent)
|
||||
|
|
Loading…
Reference in New Issue