safe slices

This commit is contained in:
Josh Baker 2016-09-09 15:49:48 -07:00
parent 7c631e9868
commit 2dec1c4e7b
1 changed files with 19 additions and 8 deletions

View File

@ -1141,28 +1141,39 @@ func GetBytes(json []byte, path string) Result {
if json != nil { if json != nil {
// unsafe cast to string // unsafe cast to string
result = Get(*(*string)(unsafe.Pointer(&json)), path) result = Get(*(*string)(unsafe.Pointer(&json)), path)
// copy of string data for safety. // safely get the string headers
rawh := *(*reflect.SliceHeader)(unsafe.Pointer(&result.Raw)) rawhi := *(*reflect.StringHeader)(unsafe.Pointer(&result.Raw))
strh := *(*reflect.SliceHeader)(unsafe.Pointer(&result.Str)) strhi := *(*reflect.StringHeader)(unsafe.Pointer(&result.Str))
// create byte slice headers
rawh := reflect.SliceHeader{Data: rawhi.Data, Len: rawhi.Len}
strh := reflect.SliceHeader{Data: strhi.Data, Len: strhi.Len}
if strh.Data == 0 { if strh.Data == 0 {
// str is nil
if rawh.Data == 0 { if rawh.Data == 0 {
// raw is nil
result.Raw = "" result.Raw = ""
} else { } else {
result.Raw = string(*(*[]byte)(unsafe.Pointer(&result.Raw))) // raw has data, safely copy the slice header to a string
result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
} }
result.Str = "" result.Str = ""
} else if rawh.Data == 0 { } else if rawh.Data == 0 {
// raw is nil
result.Raw = "" result.Raw = ""
result.Str = string(*(*[]byte)(unsafe.Pointer(&result.Str))) // str has data, safely copy the slice header to a string
result.Str = string(*(*[]byte)(unsafe.Pointer(&strh)))
} else if strh.Data >= rawh.Data && } else if strh.Data >= rawh.Data &&
int(strh.Data)+strh.Len <= int(rawh.Data)+rawh.Len { int(strh.Data)+strh.Len <= int(rawh.Data)+rawh.Len {
// Str is a substring of Raw. // Str is a substring of Raw.
start := int(strh.Data - rawh.Data) start := int(strh.Data - rawh.Data)
result.Raw = string(*(*[]byte)(unsafe.Pointer(&result.Raw))) // safely copy the raw slice header
result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
// substring the raw
result.Str = result.Raw[start : start+strh.Len] result.Str = result.Raw[start : start+strh.Len]
} else { } else {
result.Raw = string(*(*[]byte)(unsafe.Pointer(&result.Raw))) // safely copy both the raw and str slice headers to strings
result.Str = string(*(*[]byte)(unsafe.Pointer(&result.Str))) result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
result.Str = string(*(*[]byte)(unsafe.Pointer(&strh)))
} }
} }
return result return result