Skip to content

Commit

Permalink
fix cgo array to slice casting
Browse files Browse the repository at this point in the history
Instead of using a type of array of size 1 << 30, manipulate fields of slice
header.

Fix error on i686-w64-mingw32:
compile.go:407:30: type [1073741824]*_Ctype_char larger than address space
  • Loading branch information
starius committed Dec 31, 2024
1 parent c15d8d5 commit 6b2bbdd
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 11 deletions.
16 changes: 13 additions & 3 deletions internal/ch/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,16 @@ func CompileMulti(p Patterns, mode CompileMode, info *hs.PlatformInfo) (Database
return CompileExtMulti(p, mode, info, 0, 0)
}

func castCArrayToSlice[T any](c *T, count int) []T {
var list []T
sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&list)))

Check failure on line 134 in internal/ch/compile.go

View workflow job for this annotation

GitHub Actions / Go stable @ ubuntu-24.04 for hyperscan 5.4.2

undefined: reflect
sliceHeader.Cap = count
sliceHeader.Len = count
sliceHeader.Data = uintptr(unsafe.Pointer(c))

return list
}

// The multiple regular expression compiler.
func CompileExtMulti(p Patterns, mode CompileMode, info *hs.PlatformInfo,
matchLimit, matchLimitRecursion uint,
Expand All @@ -144,13 +154,13 @@ func CompileExtMulti(p Patterns, mode CompileMode, info *hs.PlatformInfo,
patterns := p.Patterns()

cexprs := (**C.char)(C.calloc(C.size_t(len(patterns)), C.size_t(unsafe.Sizeof(uintptr(0)))))
exprs := (*[1 << 30]*C.char)(unsafe.Pointer(cexprs))[:len(patterns):len(patterns)]
exprs := castCArrayToSlice[*C.char](cexprs, len(patterns))

cflags := (*C.uint)(C.calloc(C.size_t(len(patterns)), C.size_t(unsafe.Sizeof(C.uint(0)))))
flags := (*[1 << 30]C.uint)(unsafe.Pointer(cflags))[:len(patterns):len(patterns)]
flags := castCArrayToSlice[C.uint](cflags, len(patterns))

cids := (*C.uint)(C.calloc(C.size_t(len(patterns)), C.size_t(unsafe.Sizeof(C.uint(0)))))
ids := (*[1 << 30]C.uint)(unsafe.Pointer(cids))[:len(patterns):len(patterns)]
ids := castCArrayToSlice[C.uint](cids, len(patterns))

for i, pattern := range patterns {
exprs[i] = C.CString(pattern.Expression)
Expand Down
19 changes: 15 additions & 4 deletions internal/hs/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import "C"
import (
"errors"
"fmt"
"reflect"
"runtime"
"sort"
"strings"
Expand Down Expand Up @@ -391,6 +392,16 @@ type Patterns interface {
Patterns() []*Pattern
}

func castCArrayToSlice[T any](c *T, count int) []T {
var list []T
sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&list)))
sliceHeader.Cap = count
sliceHeader.Len = count
sliceHeader.Data = uintptr(unsafe.Pointer(c))

return list
}

func CompileMulti(input Patterns, mode ModeFlag, info *PlatformInfo) (Database, error) {
var db *C.hs_database_t
var err *C.hs_compile_error_t
Expand All @@ -404,16 +415,16 @@ func CompileMulti(input Patterns, mode ModeFlag, info *PlatformInfo) (Database,
count := len(patterns)

cexprs := (**C.char)(C.calloc(C.size_t(count), C.size_t(unsafe.Sizeof(uintptr(0)))))
exprs := (*[1 << 30]*C.char)(unsafe.Pointer(cexprs))[:count:count]
exprs := castCArrayToSlice[*C.char](cexprs, count)

cflags := (*C.uint)(C.calloc(C.size_t(count), C.size_t(unsafe.Sizeof(C.uint(0)))))
flags := (*[1 << 30]C.uint)(unsafe.Pointer(cflags))[:count:count]
flags := castCArrayToSlice[C.uint](cflags, count)

cids := (*C.uint)(C.calloc(C.size_t(count), C.size_t(unsafe.Sizeof(C.uint(0)))))
ids := (*[1 << 30]C.uint)(unsafe.Pointer(cids))[:count:count]
ids := castCArrayToSlice[C.uint](cids, count)

cexts := (**C.hs_expr_ext_t)(C.calloc(C.size_t(count), C.size_t(unsafe.Sizeof(uintptr(0)))))
exts := (*[1 << 30]*C.hs_expr_ext_t)(unsafe.Pointer(cexts))[:count:count]
exts := castCArrayToSlice[*C.hs_expr_ext_t](cexts, count)

for i, pattern := range patterns {
exprs[i] = C.CString(pattern.Expr)
Expand Down
8 changes: 4 additions & 4 deletions internal/hs/compile_v52.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,16 @@ func CompileLitMulti(input Literals, mode ModeFlag, info *PlatformInfo) (Databas
count := len(literals)

cexprs := (**C.char)(C.calloc(C.size_t(len(literals)), C.size_t(unsafe.Sizeof(uintptr(0)))))
exprs := (*[1 << 30]*C.char)(unsafe.Pointer(cexprs))[:len(literals):len(literals)]
exprs := castCArrayToSlice[*C.char](cexprs, len(literals))

clens := (*C.size_t)(C.calloc(C.size_t(len(literals)), C.size_t(unsafe.Sizeof(uintptr(0)))))
lens := (*[1 << 30]C.size_t)(unsafe.Pointer(clens))[:len(literals):len(literals)]
lens := castCArrayToSlice[C.size_t](clens, len(literals))

cflags := (*C.uint)(C.calloc(C.size_t(len(literals)), C.size_t(unsafe.Sizeof(C.uint(0)))))
flags := (*[1 << 30]C.uint)(unsafe.Pointer(cflags))[:len(literals):len(literals)]
flags := castCArrayToSlice[C.uint](cflags, len(literals))

cids := (*C.uint)(C.calloc(C.size_t(len(literals)), C.size_t(unsafe.Sizeof(C.uint(0)))))
ids := (*[1 << 30]C.uint)(unsafe.Pointer(cids))[:len(literals):len(literals)]
ids := castCArrayToSlice[C.uint](cids, len(literals))

for i, lit := range literals {
exprs[i] = C.CString(lit.Expr)
Expand Down

0 comments on commit 6b2bbdd

Please sign in to comment.