Skip to content

Commit

Permalink
refactor: don't store a handle inScanner
Browse files Browse the repository at this point in the history
  • Loading branch information
plusvic committed Sep 15, 2024
1 parent c827c6d commit b4be0e1
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 26 deletions.
4 changes: 2 additions & 2 deletions capi/include/yara_x.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,8 @@ void yrx_metadata_destroy(struct YRX_METADATA *metadata);
// object that must be destroyed with [`yrx_patterns_destroy`] when not needed
// anymore.
//
// This function returns a null pointer when `rule` is null or when the rule
// doesn't have any patterns.
// This function returns a null pointer when `rule` is null or the rule doesn't
// have any patterns.
struct YRX_PATTERNS *yrx_rule_patterns(const struct YRX_RULE *rule);

// Destroys a [`YRX_PATTERNS`] object.
Expand Down
6 changes: 4 additions & 2 deletions go/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ func (r *Rules) Destroy() {

// This is the callback called by yrx_rules_iterate, when Rules.GetRules is
// called.
//
//export onRule
func onRule(rule *C.YRX_RULE, handle C.uintptr_t) {
h := cgo.Handle(handle)
Expand Down Expand Up @@ -208,6 +209,7 @@ func (r *Rules) Count() int {

// This is the callback called by yrx_rules_iterate_imports, when Rules.Imports
// is called.
//
//export onImport
func onImport(module_name *C.char, handle unsafe.Pointer) {
h := cgo.Handle(handle)
Expand All @@ -221,8 +223,8 @@ func onImport(module_name *C.char, handle unsafe.Pointer) {
// Count returns the total number of rules.
func (r *Rules) Imports() []string {
imports := make([]string, 0)
handle := cgo.NewHandle(&imports)
defer handle.Delete()
handle := cgo.NewHandle(&imports)
defer handle.Delete()

C._yrx_rules_iterate_imports(
r.cRules,
Expand Down
33 changes: 11 additions & 22 deletions go/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,6 @@ type Scanner struct {
// is garbage collected the associated C.YRX_RULES object is destroyed
// before the C.YRX_SCANNER object.
rules *Rules
// Handle to the scanner itself that is passed to C callbacks.
//
// Go 1.21 introduces https://pkg.go.dev/runtime#Pinner.Pin, which allows
// to pin a Go object in memory, guaranteeing that the garbage collector
// won't move it to another memory location. We could pin the Scanner
// struct and pass a pointer to the scanner to the C code, making this
// handle unnecessary. At this time (Feb 2024) Go 1.21 is only 6 months
// old, and we want to support older versions.
handle cgo.Handle

// Rules that matched during the last scan.
matchingRules []*Rule
}
Expand All @@ -64,11 +54,11 @@ func (s ScanResults) MatchingRules() []*Rule {
//export onMatchingRule
func onMatchingRule(rule *C.YRX_RULE, handle C.uintptr_t) {
h := cgo.Handle(handle)
scanner, ok := h.Value().(*Scanner)
matchingRules, ok := h.Value().(*[]*Rule)
if !ok {
panic("onMatchingRule didn't receive a Scanner")
}
scanner.matchingRules = append(scanner.matchingRules, newRule(rule))
*matchingRules = append(*matchingRules, newRule(rule))
}

// NewScanner creates a Scanner that will use the provided YARA rules.
Expand All @@ -81,14 +71,6 @@ func NewScanner(r *Rules) *Scanner {
if C.yrx_scanner_create(r.cRules, &s.cScanner) != C.SUCCESS {
panic("yrx_scanner_create failed")
}

s.handle = cgo.NewHandle(s)

C._yrx_scanner_on_matching_rule(
s.cScanner,
C.YRX_RULE_CALLBACK(C.onMatchingRule),
C.uintptr_t(s.handle))

runtime.SetFinalizer(s, (*Scanner).Destroy)
return s
}
Expand Down Expand Up @@ -218,9 +200,17 @@ func (s *Scanner) Scan(buf []byte) (*ScanResults, error) {
ptr = (*C.uint8_t)(unsafe.Pointer(&(buf[0])))
}

handle := cgo.NewHandle(&s.matchingRules)
defer handle.Delete()

runtime.LockOSThread()
defer runtime.UnlockOSThread()

C._yrx_scanner_on_matching_rule(
s.cScanner,
C.YRX_RULE_CALLBACK(C.onMatchingRule),
C.uintptr_t(handle))

var err error
switch r := C.yrx_scanner_scan(s.cScanner, ptr, C.size_t(len(buf))); r {
case C.SUCCESS:
Expand All @@ -242,11 +232,10 @@ func (s *Scanner) Scan(buf []byte) (*ScanResults, error) {
// Calling this method directly is not necessary, it will be invoked by the
// garbage collector when the scanner is not used anymore.
func (s *Scanner) Destroy() {
s.rules = nil
if s.cScanner != nil {
C.yrx_scanner_destroy(s.cScanner)
s.handle.Delete()
s.cScanner = nil
}
s.rules = nil
runtime.SetFinalizer(s, nil)
}

0 comments on commit b4be0e1

Please sign in to comment.