Skip to content

Commit

Permalink
[convert] Critical Fix :
Browse files Browse the repository at this point in the history
- Fix bad usage of reflect package to convert unsafe!
- checked by `go build -gcflags=-m` show all `req does not escape`
- read more : golang/go#40701
  • Loading branch information
OmidHekayati committed Jun 9, 2021
1 parent bd22e21 commit cc5c867
Show file tree
Hide file tree
Showing 9 changed files with 259 additions and 254 deletions.
48 changes: 16 additions & 32 deletions convert/array-slice-unsafe.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,55 +10,39 @@ import (
// Unsafe16ByteArraySliceToByteSlice returns ...
func Unsafe16ByteArraySliceToByteSlice(req [][16]byte) (res []byte) {
var reqStruct = (*reflect.SliceHeader)(unsafe.Pointer(&req))
var resStruct = reflect.SliceHeader{
Data: reqStruct.Data,
Len: reqStruct.Len * 16,
Cap: reqStruct.Cap * 16,
}

res = *(*[]byte)(unsafe.Pointer(&resStruct))
var resStruct = (*reflect.SliceHeader)(unsafe.Pointer(&res))
resStruct.Data = reqStruct.Data
resStruct.Len = reqStruct.Len * 16
resStruct.Cap = reqStruct.Cap * 16
return
}

// UnsafeByteSliceTo16ByteArraySlice returns ...
func UnsafeByteSliceTo16ByteArraySlice(req []byte) (res [][16]byte) {
var reqStruct = (*reflect.SliceHeader)(unsafe.Pointer(&req))
var resStruct = reflect.SliceHeader{
Data: reqStruct.Data,
Len: reqStruct.Len / 16,
Cap: reqStruct.Cap / 16,
}

res = *(*[][16]byte)(unsafe.Pointer(&resStruct))
// TODO::: really need do this here??
// runtime.KeepAlive(req)
var resStruct = (*reflect.SliceHeader)(unsafe.Pointer(&res))
resStruct.Data = reqStruct.Data
resStruct.Len = reqStruct.Len / 16
resStruct.Cap = reqStruct.Cap / 16
return
}

// Unsafe32ByteArraySliceToByteSlice returns ...
func Unsafe32ByteArraySliceToByteSlice(req [][32]byte) (res []byte) {
var reqStruct = (*reflect.SliceHeader)(unsafe.Pointer(&req))
var resStruct = reflect.SliceHeader{
Data: reqStruct.Data,
Len: reqStruct.Len * 32,
Cap: reqStruct.Cap * 32,
}

res = *(*[]byte)(unsafe.Pointer(&resStruct))
var resStruct = (*reflect.SliceHeader)(unsafe.Pointer(&res))
resStruct.Data = reqStruct.Data
resStruct.Len = reqStruct.Len * 32
resStruct.Cap = reqStruct.Cap * 32
return
}

// UnsafeByteSliceTo32ByteArraySlice returns ...
func UnsafeByteSliceTo32ByteArraySlice(req []byte) (res [][32]byte) {
var reqStruct = (*reflect.SliceHeader)(unsafe.Pointer(&req))
var resStruct = reflect.SliceHeader{
Data: reqStruct.Data,
Len: reqStruct.Len / 32,
Cap: reqStruct.Cap / 32,
}

res = *(*[][32]byte)(unsafe.Pointer(&resStruct))
// TODO::: really need do this here??
// runtime.KeepAlive(req)
var resStruct = (*reflect.SliceHeader)(unsafe.Pointer(&res))
resStruct.Data = reqStruct.Data
resStruct.Len = reqStruct.Len / 32
resStruct.Cap = reqStruct.Cap / 32
return
}
107 changes: 107 additions & 0 deletions convert/base10-integer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/* For license and copyright information please see LEGAL file in repository */

package convert

import "../giti"

const (
maxUint8Value uint8 = 255
maxUint16Value uint16 = 65535
maxUint32Value uint32 = 4294967295
)

// Base10StringToUint8 Parse given string and returns uint8
func Base10StringToUint8(str string) (num uint8, err giti.Error) {
if str == "" {
return 0, ErrEmptyValue
}

var n uint16
for _, char := range []byte(str) {
var numSegment byte
// var char = strAsByteSlice[i]
switch {
case '0' <= char && char <= '9':
numSegment = char - '0'
default:
return 0, ErrBadValue
}
n *= 10
n += uint16(numSegment)
if n > uint16(maxUint8Value) {
return 0, ErrBadValue
}
}
return uint8(n), nil
}

// Base10StringToUint16 Parse given string and returns uint16
func Base10StringToUint16(str string) (num uint16, err giti.Error) {
if str == "" {
return 0, ErrEmptyValue
}

var n uint32
for _, char := range []byte(str) {
var numSegment byte
// var char = strAsByteSlice[i]
switch {
case '0' <= char && char <= '9':
numSegment = char - '0'
default:
return 0, ErrBadValue
}
n *= 10
n += uint32(numSegment)
if n > uint32(maxUint16Value) {
return 0, ErrBadValue
}
}
return uint16(n), nil
}

// Base10StringToUint32 Parse given string and returns uint32
func Base10StringToUint32(str string) (num uint32, err giti.Error) {
if str == "" {
return 0, ErrEmptyValue
}

var n uint64
for _, char := range []byte(str) {
var numSegment byte
// var char = strAsByteSlice[i]
switch {
case '0' <= char && char <= '9':
numSegment = char - '0'
default:
return 0, ErrBadValue
}
n *= 10
n += uint64(numSegment)
if n > uint64(maxUint32Value) {
return 0, ErrBadValue
}
}
return uint32(n), nil
}

// Base10StringToUint64 Parse given string and returns uint64
func Base10StringToUint64(str string) (num uint64, err giti.Error) {
if str == "" {
return 0, ErrEmptyValue
}

for _, char := range []byte(str) {
var numSegment byte
// var char = strAsByteSlice[i]
switch {
case '0' <= char && char <= '9':
numSegment = char - '0'
default:
return 0, ErrBadValue
}
num *= 10
num += uint64(numSegment)
}
return
}
24 changes: 8 additions & 16 deletions convert/bool-slice-unsafe.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,19 @@ import (
// UnsafeBoolSliceToByteSlice returns ...
func UnsafeBoolSliceToByteSlice(req []bool) (res []byte) {
var reqStruct = (*reflect.SliceHeader)(unsafe.Pointer(&req))
var resStruct = reflect.SliceHeader{
Data: reqStruct.Data,
Len: reqStruct.Len,
Cap: reqStruct.Cap,
}

res = *(*[]byte)(unsafe.Pointer(&resStruct))
var resStruct = (*reflect.SliceHeader)(unsafe.Pointer(&res))
resStruct.Data = reqStruct.Data
resStruct.Len = reqStruct.Len
resStruct.Cap = reqStruct.Cap
return
}

// UnsafeByteSliceToBoolSlice returns ...
func UnsafeByteSliceToBoolSlice(req []byte) (res []bool) {
var reqStruct = (*reflect.SliceHeader)(unsafe.Pointer(&req))
var resStruct = reflect.SliceHeader{
Data: reqStruct.Data,
Len: reqStruct.Len,
Cap: reqStruct.Cap,
}

res = *(*[]bool)(unsafe.Pointer(&resStruct))
// TODO::: really need do this here??
// runtime.KeepAlive(req)
var resStruct = (*reflect.SliceHeader)(unsafe.Pointer(&res))
resStruct.Data = reqStruct.Data
resStruct.Len = reqStruct.Len
resStruct.Cap = reqStruct.Cap
return
}
48 changes: 16 additions & 32 deletions convert/complex-slice-unsafe.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,55 +10,39 @@ import (
// UnsafeComplex64SliceToByteSlice returns ...
func UnsafeComplex64SliceToByteSlice(req []complex64) (res []byte) {
var reqStruct = (*reflect.SliceHeader)(unsafe.Pointer(&req))
var resStruct = reflect.SliceHeader{
Data: reqStruct.Data,
Len: reqStruct.Len * 8,
Cap: reqStruct.Cap * 8,
}

res = *(*[]byte)(unsafe.Pointer(&resStruct))
var resStruct = (*reflect.SliceHeader)(unsafe.Pointer(&res))
resStruct.Data = reqStruct.Data
resStruct.Len = reqStruct.Len * 8
resStruct.Cap = reqStruct.Cap * 8
return
}

// UnsafeByteSliceToComplex64Slice returns ...
func UnsafeByteSliceToComplex64Slice(req []byte) (res []complex64) {
var reqStruct = (*reflect.SliceHeader)(unsafe.Pointer(&req))
var resStruct = reflect.SliceHeader{
Data: reqStruct.Data,
Len: reqStruct.Len / 8,
Cap: reqStruct.Cap / 8,
}

res = *(*[]complex64)(unsafe.Pointer(&resStruct))
// TODO::: really need do this here??
// runtime.KeepAlive(req)
var resStruct = (*reflect.SliceHeader)(unsafe.Pointer(&res))
resStruct.Data = reqStruct.Data
resStruct.Len = reqStruct.Len / 8
resStruct.Cap = reqStruct.Cap / 8
return
}

// UnsafeComplex128SliceToByteSlice returns ...
func UnsafeComplex128SliceToByteSlice(req []complex128) (res []byte) {
var reqStruct = (*reflect.SliceHeader)(unsafe.Pointer(&req))
var resStruct = reflect.SliceHeader{
Data: reqStruct.Data,
Len: reqStruct.Len * 16,
Cap: reqStruct.Cap * 16,
}

res = *(*[]byte)(unsafe.Pointer(&resStruct))
var resStruct = (*reflect.SliceHeader)(unsafe.Pointer(&res))
resStruct.Data = reqStruct.Data
resStruct.Len = reqStruct.Len * 16
resStruct.Cap = reqStruct.Cap * 16
return
}

// UnsafeByteSliceToComplex128Slice returns ...
func UnsafeByteSliceToComplex128Slice(req []byte) (res []complex128) {
var reqStruct = (*reflect.SliceHeader)(unsafe.Pointer(&req))
var resStruct = reflect.SliceHeader{
Data: reqStruct.Data,
Len: reqStruct.Len / 16,
Cap: reqStruct.Cap / 16,
}

res = *(*[]complex128)(unsafe.Pointer(&resStruct))
// TODO::: really need do this here??
// runtime.KeepAlive(req)
var resStruct = (*reflect.SliceHeader)(unsafe.Pointer(&res))
resStruct.Data = reqStruct.Data
resStruct.Len = reqStruct.Len / 16
resStruct.Cap = reqStruct.Cap / 16
return
}
24 changes: 24 additions & 0 deletions convert/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* For license and copyright information please see LEGAL file in repository */

package convert

import (
er "../error"
lang "../language"
)

const errorEnglishDomain = "Convert"
const errorPersianDomain = "تبدیل"

// Errors
var (
ErrEmptyValue = er.New("urn:giti:convert.libgo:error:empty-value").SetDetail(lang.LanguageEnglish, errorEnglishDomain, "Empty Value",
"Empty value pass to convert function that it is illegal",
"",
"").Save()

ErrBadValue = er.New("urn:giti:convert.libgo:error:bad-value").SetDetail(lang.LanguageEnglish, errorEnglishDomain, "Bad Value",
"Bad value pass to convert function that it is illegal e.g. pass '1b2' to convert to number",
"",
"").Save()
)
48 changes: 16 additions & 32 deletions convert/float-slice-unsafe.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,55 +10,39 @@ import (
// UnsafeFloat32SliceToByteSlice returns ...
func UnsafeFloat32SliceToByteSlice(req []float32) (res []byte) {
var reqStruct = (*reflect.SliceHeader)(unsafe.Pointer(&req))
var resStruct = reflect.SliceHeader{
Data: reqStruct.Data,
Len: reqStruct.Len * 4,
Cap: reqStruct.Cap * 4,
}

res = *(*[]byte)(unsafe.Pointer(&resStruct))
var resStruct = (*reflect.SliceHeader)(unsafe.Pointer(&res))
resStruct.Data = reqStruct.Data
resStruct.Len = reqStruct.Len * 4
resStruct.Cap = reqStruct.Cap * 4
return
}

// UnsafeByteSliceToFloat32Slice returns ...
func UnsafeByteSliceToFloat32Slice(req []byte) (res []float32) {
var reqStruct = (*reflect.SliceHeader)(unsafe.Pointer(&req))
var resStruct = reflect.SliceHeader{
Data: reqStruct.Data,
Len: reqStruct.Len / 4,
Cap: reqStruct.Cap / 4,
}

res = *(*[]float32)(unsafe.Pointer(&resStruct))
// TODO::: really need do this here??
// runtime.KeepAlive(req)
var resStruct = (*reflect.SliceHeader)(unsafe.Pointer(&res))
resStruct.Data = reqStruct.Data
resStruct.Len = reqStruct.Len / 4
resStruct.Cap = reqStruct.Cap / 4
return
}

// UnsafeFloat64SliceToByteSlice returns ...
func UnsafeFloat64SliceToByteSlice(req []float64) (res []byte) {
var reqStruct = (*reflect.SliceHeader)(unsafe.Pointer(&req))
var resStruct = reflect.SliceHeader{
Data: reqStruct.Data,
Len: reqStruct.Len * 8,
Cap: reqStruct.Cap * 8,
}

res = *(*[]byte)(unsafe.Pointer(&resStruct))
var resStruct = (*reflect.SliceHeader)(unsafe.Pointer(&res))
resStruct.Data = reqStruct.Data
resStruct.Len = reqStruct.Len * 8
resStruct.Cap = reqStruct.Cap * 8
return
}

// UnsafeByteSliceToFloat64Slice returns ...
func UnsafeByteSliceToFloat64Slice(req []byte) (res []float64) {
var reqStruct = (*reflect.SliceHeader)(unsafe.Pointer(&req))
var resStruct = reflect.SliceHeader{
Data: reqStruct.Data,
Len: reqStruct.Len / 8,
Cap: reqStruct.Cap / 8,
}

res = *(*[]float64)(unsafe.Pointer(&resStruct))
// TODO::: really need do this here??
// runtime.KeepAlive(req)
var resStruct = (*reflect.SliceHeader)(unsafe.Pointer(&res))
resStruct.Data = reqStruct.Data
resStruct.Len = reqStruct.Len / 8
resStruct.Cap = reqStruct.Cap / 8
return
}
Loading

0 comments on commit cc5c867

Please sign in to comment.