New upstream version 4.2.1
Sascha Steinbiss
2 years ago
61 | 61 | |
62 | 62 | This version of _go-yara_ can only be used with YARA 4.2 or later. |
63 | 63 | |
64 | Version of _go-yara_ compatible with YARA 4.0.x are available via the | |
64 | Version of _go-yara_ compatible with YARA 4.1.x are available via the | |
65 | 65 | `v4.1.x` branch or tagged `v4.1.*` releases. |
66 | 66 | |
67 | 67 | Version of _go-yara_ compatible with YARA 4.0.x are available via the |
0 | // Copyright © 2015-2020 Hilko Bengen <bengen@hilluzination.de> | |
1 | // All rights reserved. | |
2 | // | |
3 | // Use of this source code is governed by the license that can be | |
4 | // found in the LICENSE file. | |
5 | ||
6 | package yara | |
7 | ||
8 | import ( | |
9 | "reflect" | |
10 | "runtime" | |
11 | "sync" | |
12 | "unsafe" | |
13 | ) | |
14 | ||
15 | // #include <stdlib.h> | |
16 | import "C" | |
17 | ||
18 | // cbPoolPool implements a key/value store for data that is safe | |
19 | // to pass as callback data through CGO functions. | |
20 | // | |
21 | // The keys are pointers which do not directly reference the stored | |
22 | // values, therefore any "Go pointer to Go pointer" errors are avoided. | |
23 | type cbPool struct { | |
24 | indices []int | |
25 | objects []interface{} | |
26 | m sync.RWMutex | |
27 | } | |
28 | ||
29 | // MakePool creates a Pool that can hold n elements. | |
30 | func makecbPool(n int) *cbPool { | |
31 | p := &cbPool{ | |
32 | indices: make([]int, 0), | |
33 | objects: make([]interface{}, n), | |
34 | } | |
35 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&p.indices)) | |
36 | hdr.Data = uintptr(C.calloc(C.size_t(n), C.size_t(unsafe.Sizeof(int(0))))) | |
37 | hdr.Len = n | |
38 | runtime.SetFinalizer(p, (*cbPool).Finalize) | |
39 | return p | |
40 | } | |
41 | ||
42 | // Put adds an element to the cbPool, returning a stable pointer | |
43 | // suitable for passing through CGO. It panics if the pool is full. | |
44 | func (p *cbPool) Put(obj interface{}) unsafe.Pointer { | |
45 | p.m.Lock() | |
46 | defer p.m.Unlock() | |
47 | for id, val := range p.indices { | |
48 | if val != 0 { | |
49 | continue | |
50 | } | |
51 | p.indices[id] = id + 1 | |
52 | p.objects[id] = obj | |
53 | return unsafe.Pointer(&p.indices[id]) | |
54 | } | |
55 | panic("cbPool storage exhausted") | |
56 | } | |
57 | ||
58 | func (p *cbPool) checkPointer(ptr unsafe.Pointer) { | |
59 | if uintptr(ptr) < uintptr(unsafe.Pointer(&p.indices[0])) || | |
60 | uintptr(unsafe.Pointer(&p.indices[len(p.indices)-1])) < uintptr(ptr) { | |
61 | panic("Attempt to access pool using invalid pointer") | |
62 | } | |
63 | } | |
64 | ||
65 | // Get accesses an element stored in the cbPool, using a pointer | |
66 | // previously returned by Put. It panics if the pointer is invalid or | |
67 | // if it references an empty slot. | |
68 | func (p *cbPool) Get(ptr unsafe.Pointer) interface{} { | |
69 | p.m.RLock() | |
70 | defer p.m.RUnlock() | |
71 | p.checkPointer(ptr) | |
72 | id := *(*int)(ptr) - 1 | |
73 | if id == -1 { | |
74 | panic("Attempt to get nonexistent value from pool") | |
75 | } | |
76 | return p.objects[id] | |
77 | } | |
78 | ||
79 | // Delete removes an element from the cbPool, using a pointer previously | |
80 | // returned by Put. It panics if the pointer is invalid or if it | |
81 | // references an empty slot. | |
82 | func (p *cbPool) Delete(ptr unsafe.Pointer) { | |
83 | p.m.Lock() | |
84 | defer p.m.Unlock() | |
85 | p.checkPointer(ptr) | |
86 | id := *(*int)(ptr) - 1 | |
87 | if id == -1 { | |
88 | panic("Attempt to delete nonexistent value from pool") | |
89 | } | |
90 | p.indices[id] = 0 | |
91 | p.objects[id] = nil | |
92 | return | |
93 | } | |
94 | ||
95 | func (p *cbPool) Finalize() { | |
96 | p.m.Lock() | |
97 | defer p.m.Unlock() | |
98 | if p.indices != nil { | |
99 | C.free(unsafe.Pointer(&p.indices[0])) | |
100 | p.indices = nil | |
101 | } | |
102 | } |
0 | // Copyright © 2015-2020 Hilko Bengen <bengen@hilluzination.de> | |
1 | // All rights reserved. | |
2 | // | |
3 | // Use of this source code is governed by the license that can be | |
4 | // found in the LICENSE file. | |
5 | ||
6 | package yara | |
7 | ||
8 | import ( | |
9 | "testing" | |
10 | ) | |
11 | ||
12 | func TestBasic(t *testing.T) { | |
13 | pool := makecbPool(32) | |
14 | p1 := pool.Put("asdf") | |
15 | p2 := pool.Put("ghjk") | |
16 | s1, ok := pool.Get(p1).(string) | |
17 | if !ok || s1 != "asdf" { | |
18 | t.Errorf("s1: expected 'asdf', got '%v'", s1) | |
19 | } | |
20 | pool.Delete(p1) | |
21 | i := func() interface{} { | |
22 | defer func() { | |
23 | if x := recover(); x != nil { | |
24 | t.Logf("Get: Got expected panic: %v", x) | |
25 | } | |
26 | }() | |
27 | x := pool.Get(p1) | |
28 | t.Error("Get: No panic was triggered.") | |
29 | return x | |
30 | }() | |
31 | if s1, ok := i.(string); ok || s1 == "asdf" { | |
32 | t.Errorf("s1: expected nil, got '%v'", s1) | |
33 | } | |
34 | s2, ok := pool.Get(p2).(string) | |
35 | if !ok || s2 != "ghjk" { | |
36 | t.Errorf("s1: expected 'hjkl', got '%v'", s1) | |
37 | } | |
38 | pool.Delete(p2) | |
39 | func() { | |
40 | defer func() { | |
41 | if x := recover(); x != nil { | |
42 | t.Logf("Delete: Got expected panic: %v", x) | |
43 | } | |
44 | }() | |
45 | pool.Delete(p2) | |
46 | t.Error("Delete: No panic was triggered.") | |
47 | }() | |
48 | ||
49 | // Fill pool | |
50 | for i := 0; i < 32; i++ { | |
51 | pool.Put(i) | |
52 | } | |
53 | func() { | |
54 | defer func() { | |
55 | if x := recover(); x != nil { | |
56 | t.Logf("full pool: Got expected panic: %v", x) | |
57 | } | |
58 | }() | |
59 | pool.Put(100) | |
60 | t.Error("full pool: No panic was triggered.") | |
61 | }() | |
62 | } |
0 | #include <yara.h> | |
1 | ||
2 | /* | |
3 | Wrappers functions whose sole purpose is converting uintptr as | |
4 | returned by (*os.File).Fd() to HANDLE on Windows systems | |
5 | */ | |
6 | ||
7 | #ifdef _WIN32 | |
8 | ||
9 | int _yr_compiler_add_fd( | |
10 | YR_COMPILER* compiler, | |
11 | int rules_fd, | |
12 | const char* namespace_, | |
13 | const char* file_name) | |
14 | { | |
15 | return yr_compiler_add_fd(compiler, (YR_FILE_DESCRIPTOR)(intptr_t)rules_fd, namespace_, file_name); | |
16 | } | |
17 | ||
18 | int _yr_rules_scan_fd( | |
19 | YR_RULES* rules, | |
20 | int fd, | |
21 | int flags, | |
22 | YR_CALLBACK_FUNC callback, | |
23 | void* user_data, | |
24 | int timeout) | |
25 | { | |
26 | return yr_rules_scan_fd(rules, (YR_FILE_DESCRIPTOR)(intptr_t)fd, flags, callback, user_data, timeout); | |
27 | } | |
28 | ||
29 | int _yr_scanner_scan_fd( | |
30 | YR_SCANNER* scanner, | |
31 | int fd) | |
32 | { | |
33 | return yr_scanner_scan_fd(scanner, (YR_FILE_DESCRIPTOR)(intptr_t)fd); | |
34 | } | |
35 | ||
36 | #endif |
0 | #ifndef _COMPAT_H | |
1 | #define _COMPAT_H | |
2 | ||
3 | #ifdef _WIN32 | |
4 | #define fdopen _fdopen | |
5 | #define dup _dup | |
6 | #endif | |
7 | ||
8 | #ifdef _WIN32 | |
9 | int _yr_compiler_add_fd( | |
10 | YR_COMPILER* compiler, | |
11 | int rules_fd, | |
12 | const char* namespace_, | |
13 | const char* file_name); | |
14 | #else | |
15 | #define _yr_compiler_add_fd yr_compiler_add_fd | |
16 | #endif | |
17 | ||
18 | #ifdef _WIN32 | |
19 | int _yr_rules_scan_fd( | |
20 | YR_RULES* rules, | |
21 | int fd, | |
22 | int flags, | |
23 | YR_CALLBACK_FUNC callback, | |
24 | void* user_data, | |
25 | int timeout); | |
26 | #else | |
27 | #define _yr_rules_scan_fd yr_rules_scan_fd | |
28 | #endif | |
29 | ||
30 | #ifdef _WIN32 | |
31 | #include <stdint.h> | |
32 | int _yr_scanner_scan_fd( | |
33 | YR_SCANNER* scanner, | |
34 | int fd); | |
35 | #else | |
36 | #define _yr_scanner_scan_fd yr_scanner_scan_fd | |
37 | #endif | |
38 | ||
39 | #endif /* _COMPAT_H */ |
6 | 6 | package yara |
7 | 7 | |
8 | 8 | /* |
9 | #ifdef _WIN32 | |
10 | #define fdopen _fdopen | |
11 | #define dup _dup | |
12 | #endif | |
13 | #include <stdio.h> | |
14 | #include <unistd.h> | |
15 | ||
16 | 9 | #include <yara.h> |
10 | #include "compat.h" | |
17 | 11 | |
18 | 12 | void compilerCallback(int, char*, int, YR_RULE*, char*, void*); |
19 | 13 | char* includeCallback(char*, char*, char*, void*); |
30 | 24 | |
31 | 25 | //export compilerCallback |
32 | 26 | func compilerCallback(errorLevel C.int, filename *C.char, linenumber C.int, rule *C.YR_RULE, message *C.char, userData unsafe.Pointer) { |
33 | c := callbackData.Get(userData).(*Compiler) | |
27 | c := cgoHandle(userData).Value().(*Compiler) | |
34 | 28 | msg := CompilerMessage{ |
35 | 29 | Filename: C.GoString(filename), |
36 | 30 | Line: int(linenumber), |
59 | 53 | Errors []CompilerMessage |
60 | 54 | Warnings []CompilerMessage |
61 | 55 | // used for include callback |
62 | callbackData unsafe.Pointer | |
56 | callbackData cgoHandle | |
63 | 57 | cptr *C.YR_COMPILER |
64 | 58 | } |
65 | 59 | |
94 | 88 | runtime.SetFinalizer(c, nil) |
95 | 89 | } |
96 | 90 | |
97 | func (c *Compiler) setCallbackData(ptr unsafe.Pointer) { | |
98 | if c.callbackData != nil { | |
99 | callbackData.Delete(c.callbackData) | |
91 | func (c *Compiler) setCallbackData(ptr cgoHandle) { | |
92 | if c.callbackData != 0 { | |
93 | c.callbackData.Delete() | |
100 | 94 | } |
101 | 95 | c.callbackData = ptr |
102 | 96 | } |
117 | 111 | } |
118 | 112 | filename := C.CString(file.Name()) |
119 | 113 | defer C.free(unsafe.Pointer(filename)) |
120 | id := callbackData.Put(c) | |
121 | defer callbackData.Delete(id) | |
122 | C.yr_compiler_set_callback(c.cptr, C.YR_COMPILER_CALLBACK_FUNC(C.compilerCallback), id) | |
123 | numErrors := int(C.yr_compiler_add_fd(c.cptr, (C.YR_FILE_DESCRIPTOR)(file.Fd()), ns, filename)) | |
114 | id := cgoNewHandle(c) | |
115 | defer id.Delete() | |
116 | C.yr_compiler_set_callback(c.cptr, C.YR_COMPILER_CALLBACK_FUNC(C.compilerCallback), unsafe.Pointer(id)) | |
117 | numErrors := int(C._yr_compiler_add_fd(c.cptr, C.int(file.Fd()), ns, filename)) | |
124 | 118 | if numErrors > 0 { |
125 | 119 | var buf [1024]C.char |
126 | 120 | msg := C.GoString(C.yr_compiler_get_error_message( |
147 | 141 | } |
148 | 142 | crules := C.CString(rules) |
149 | 143 | defer C.free(unsafe.Pointer(crules)) |
150 | id := callbackData.Put(c) | |
151 | defer callbackData.Delete(id) | |
152 | C.yr_compiler_set_callback(c.cptr, C.YR_COMPILER_CALLBACK_FUNC(C.compilerCallback), id) | |
144 | id := cgoNewHandle(c) | |
145 | defer id.Delete() | |
146 | C.yr_compiler_set_callback(c.cptr, C.YR_COMPILER_CALLBACK_FUNC(C.compilerCallback), unsafe.Pointer(id)) | |
153 | 147 | numErrors := int(C.yr_compiler_add_string(c.cptr, crules, ns)) |
154 | 148 | if numErrors > 0 { |
155 | 149 | var buf [1024]C.char |
210 | 204 | |
211 | 205 | //export includeCallback |
212 | 206 | func includeCallback(name, filename, namespace *C.char, userData unsafe.Pointer) *C.char { |
213 | callbackFunc := callbackData.Get(userData).(CompilerIncludeFunc) | |
207 | callbackFunc := cgoHandle(userData).Value().(CompilerIncludeFunc) | |
214 | 208 | if buf := callbackFunc( |
215 | 209 | C.GoString(name), C.GoString(filename), C.GoString(namespace), |
216 | 210 | ); buf != nil { |
254 | 248 | c.DisableIncludes() |
255 | 249 | return |
256 | 250 | } |
257 | id := callbackData.Put(cb) | |
251 | id := cgoNewHandle(cb) | |
258 | 252 | c.setCallbackData(id) |
259 | 253 | C.yr_compiler_set_include_callback( |
260 | 254 | c.cptr, |
261 | 255 | C.YR_COMPILER_INCLUDE_CALLBACK_FUNC(C.includeCallback), |
262 | 256 | C.YR_COMPILER_INCLUDE_FREE_FUNC(C.freeCallback), |
263 | id, | |
257 | unsafe.Pointer(id), | |
264 | 258 | ) |
265 | 259 | runtime.KeepAlive(c) |
266 | 260 | return |
270 | 264 | // See yr_compiler_set_include_callbacks. |
271 | 265 | func (c *Compiler) DisableIncludes() { |
272 | 266 | C.yr_compiler_set_include_callback(c.cptr, nil, nil, nil) |
273 | c.setCallbackData(nil) | |
267 | c.setCallbackData(0) | |
274 | 268 | runtime.KeepAlive(c) |
275 | 269 | return |
276 | 270 | } |
0 | //+build go1.17 | |
1 | ||
2 | // This variant contains a trivial wrapper around "runtime/cgo".Handle. | |
3 | ||
4 | package yara | |
5 | ||
6 | import "runtime/cgo" | |
7 | ||
8 | type cgoHandle cgo.Handle | |
9 | ||
10 | func (h cgoHandle) Value() interface{} { return cgo.Handle(h).Value() } | |
11 | ||
12 | func (h cgoHandle) Delete() { cgo.Handle(h).Delete() } | |
13 | ||
14 | func cgoNewHandle(v interface{}) cgoHandle { return cgoHandle(cgo.NewHandle(v)) } |
0 | //+build !go1.17 | |
1 | ||
2 | // This variant contains a backport of go 1.18's "runtime/cgo".Handle. | |
3 | ||
4 | package yara | |
5 | ||
6 | import ( | |
7 | "sync" | |
8 | "sync/atomic" | |
9 | ) | |
10 | ||
11 | type cgoHandle uintptr | |
12 | ||
13 | func cgoNewHandle(v interface{}) cgoHandle { | |
14 | h := atomic.AddUintptr(&handleIdx, 1) | |
15 | if h == 0 { | |
16 | panic("cgoNewHandle: ran out of handle space") | |
17 | } | |
18 | ||
19 | handles.Store(h, v) | |
20 | return cgoHandle(h) | |
21 | } | |
22 | ||
23 | func (h cgoHandle) Value() interface{} { | |
24 | v, ok := handles.Load(uintptr(h)) | |
25 | if !ok { | |
26 | panic("cgoHandle: misuse of an invalid Handle") | |
27 | } | |
28 | return v | |
29 | } | |
30 | ||
31 | func (h cgoHandle) Delete() { | |
32 | _, ok := handles.LoadAndDelete(uintptr(h)) | |
33 | if !ok { | |
34 | panic("cgoHandle: misuse of an invalid Handle") | |
35 | } | |
36 | } | |
37 | ||
38 | var ( | |
39 | handles = sync.Map{} | |
40 | handleIdx uintptr | |
41 | ) |
61 | 61 | return |
62 | 62 | } |
63 | 63 | |
64 | // The caller is responsible to remove cmbi.context from callbackData | |
65 | // pool. | |
64 | // The caller is responsible to delete the cgoHandle cmbi.context. | |
66 | 65 | func makeCMemoryBlockIterator(c *memoryBlockIteratorContainer) (cmbi *C.YR_MEMORY_BLOCK_ITERATOR) { |
67 | 66 | cmbi = &C.YR_MEMORY_BLOCK_ITERATOR{ |
68 | context: callbackData.Put(c), | |
69 | first: C.YR_MEMORY_BLOCK_ITERATOR_FUNC(C.memoryBlockIteratorFirst), | |
70 | next: C.YR_MEMORY_BLOCK_ITERATOR_FUNC(C.memoryBlockIteratorNext), | |
67 | context: unsafe.Pointer(cgoNewHandle(c)), | |
68 | first: C.YR_MEMORY_BLOCK_ITERATOR_FUNC(C.memoryBlockIteratorFirst), | |
69 | next: C.YR_MEMORY_BLOCK_ITERATOR_FUNC(C.memoryBlockIteratorNext), | |
71 | 70 | } |
72 | 71 | if _, implementsFilesize := c.MemoryBlockIterator.(MemoryBlockIteratorWithFilesize); implementsFilesize { |
73 | 72 | cmbi.file_size = C.YR_MEMORY_BLOCK_ITERATOR_SIZE_FUNC(C.memoryBlockIteratorFilesize) |
108 | 107 | // |
109 | 108 | //export memoryBlockFetch |
110 | 109 | func memoryBlockFetch(cblock *C.YR_MEMORY_BLOCK) *C.uint8_t { |
111 | c := callbackData.Get(cblock.context).(*memoryBlockIteratorContainer) | |
110 | c := cgoHandle(cblock.context).Value().(*memoryBlockIteratorContainer) | |
112 | 111 | c.realloc(int(cblock.size)) |
113 | 112 | c.MemoryBlock.FetchData(c.buf) |
114 | 113 | return (*C.uint8_t)(unsafe.Pointer(&c.buf[0])) |
143 | 142 | // |
144 | 143 | //export memoryBlockIteratorFirst |
145 | 144 | func memoryBlockIteratorFirst(cmbi *C.YR_MEMORY_BLOCK_ITERATOR) *C.YR_MEMORY_BLOCK { |
146 | c := callbackData.Get(cmbi.context).(*memoryBlockIteratorContainer) | |
145 | c := cgoHandle(cmbi.context).Value().(*memoryBlockIteratorContainer) | |
147 | 146 | c.MemoryBlock = c.MemoryBlockIterator.First() |
148 | 147 | return memoryBlockIteratorCommon(cmbi, c) |
149 | 148 | } |
153 | 152 | // |
154 | 153 | //export memoryBlockIteratorNext |
155 | 154 | func memoryBlockIteratorNext(cmbi *C.YR_MEMORY_BLOCK_ITERATOR) *C.YR_MEMORY_BLOCK { |
156 | c := callbackData.Get(cmbi.context).(*memoryBlockIteratorContainer) | |
155 | c := cgoHandle(cmbi.context).Value().(*memoryBlockIteratorContainer) | |
157 | 156 | c.MemoryBlock = c.MemoryBlockIterator.Next() |
158 | 157 | return memoryBlockIteratorCommon(cmbi, c) |
159 | 158 | } |
160 | 159 | |
161 | 160 | //export memoryBlockIteratorFilesize |
162 | 161 | func memoryBlockIteratorFilesize(cmbi *C.YR_MEMORY_BLOCK_ITERATOR) C.uint64_t { |
163 | c := callbackData.Get(cmbi.context).(*memoryBlockIteratorContainer) | |
162 | c := cgoHandle(cmbi.context).Value().(*memoryBlockIteratorContainer) | |
164 | 163 | return C.uint64_t(c.MemoryBlockIterator.(MemoryBlockIteratorWithFilesize).Filesize()) |
165 | 164 | } |
7 | 7 | |
8 | 8 | /* |
9 | 9 | #include <yara.h> |
10 | ||
11 | #ifdef _WIN32 | |
12 | #include <stdint.h> | |
13 | // Helper function that is merely used to cast fd from int to HANDLE. | |
14 | // CGO treats HANDLE (void*) to an unsafe.Pointer. This confuses the | |
15 | // go1.4 garbage collector, leading to runtime errors such as: | |
16 | // | |
17 | // runtime: garbage collector found invalid heap pointer *(0x5b80ff14+0x4)=0xa0 s=nil | |
18 | int _yr_rules_scan_fd( | |
19 | YR_RULES* rules, | |
20 | int fd, | |
21 | int flags, | |
22 | YR_CALLBACK_FUNC callback, | |
23 | void* user_data, | |
24 | int timeout) | |
25 | { | |
26 | return yr_rules_scan_fd(rules, (YR_FILE_DESCRIPTOR)(intptr_t)fd, flags, callback, user_data, timeout); | |
27 | } | |
28 | #else | |
29 | #define _yr_rules_scan_fd yr_rules_scan_fd | |
30 | #endif | |
10 | #include "compat.h" | |
31 | 11 | |
32 | 12 | size_t streamRead(void* ptr, size_t size, size_t nmemb, void* user_data); |
33 | 13 | size_t streamWrite(void* ptr, size_t size, size_t nmemb, void* user_data); |
96 | 76 | if len(buf) > 0 { |
97 | 77 | ptr = (*C.uint8_t)(unsafe.Pointer(&(buf[0]))) |
98 | 78 | } |
99 | id := callbackData.Put(makeScanCallbackContainer(cb, r)) | |
100 | defer callbackData.Delete(id) | |
79 | id := cgoNewHandle(makeScanCallbackContainer(cb, r)) | |
80 | defer id.Delete() | |
101 | 81 | err = newError(C.yr_rules_scan_mem( |
102 | 82 | r.cptr, |
103 | 83 | ptr, |
104 | 84 | C.size_t(len(buf)), |
105 | 85 | flags.withReportFlags(cb), |
106 | 86 | C.YR_CALLBACK_FUNC(C.scanCallbackFunc), |
107 | id, | |
87 | unsafe.Pointer(id), | |
108 | 88 | C.int(timeout/time.Second))) |
109 | 89 | runtime.KeepAlive(r) |
110 | 90 | return |
116 | 96 | func (r *Rules) ScanFile(filename string, flags ScanFlags, timeout time.Duration, cb ScanCallback) (err error) { |
117 | 97 | cfilename := C.CString(filename) |
118 | 98 | defer C.free(unsafe.Pointer(cfilename)) |
119 | id := callbackData.Put(makeScanCallbackContainer(cb, r)) | |
120 | defer callbackData.Delete(id) | |
99 | id := cgoNewHandle(makeScanCallbackContainer(cb, r)) | |
100 | defer id.Delete() | |
121 | 101 | err = newError(C.yr_rules_scan_file( |
122 | 102 | r.cptr, |
123 | 103 | cfilename, |
124 | 104 | flags.withReportFlags(cb), |
125 | 105 | C.YR_CALLBACK_FUNC(C.scanCallbackFunc), |
126 | id, | |
106 | unsafe.Pointer(id), | |
127 | 107 | C.int(timeout/time.Second))) |
128 | 108 | runtime.KeepAlive(r) |
129 | 109 | return |
133 | 113 | // emitted by libyara, the corresponding method on the ScanCallback |
134 | 114 | // object is called. |
135 | 115 | func (r *Rules) ScanFileDescriptor(fd uintptr, flags ScanFlags, timeout time.Duration, cb ScanCallback) (err error) { |
136 | id := callbackData.Put(makeScanCallbackContainer(cb, r)) | |
137 | defer callbackData.Delete(id) | |
116 | id := cgoNewHandle(makeScanCallbackContainer(cb, r)) | |
117 | defer id.Delete() | |
138 | 118 | err = newError(C._yr_rules_scan_fd( |
139 | 119 | r.cptr, |
140 | 120 | C.int(fd), |
141 | 121 | flags.withReportFlags(cb), |
142 | 122 | C.YR_CALLBACK_FUNC(C.scanCallbackFunc), |
143 | id, | |
123 | unsafe.Pointer(id), | |
144 | 124 | C.int(timeout/time.Second))) |
145 | 125 | runtime.KeepAlive(r) |
146 | 126 | return |
150 | 130 | // every event emitted by libyara, the corresponding method on the |
151 | 131 | // ScanCallback object is called. |
152 | 132 | func (r *Rules) ScanProc(pid int, flags ScanFlags, timeout time.Duration, cb ScanCallback) (err error) { |
153 | id := callbackData.Put(makeScanCallbackContainer(cb, r)) | |
154 | defer callbackData.Delete(id) | |
133 | id := cgoNewHandle(makeScanCallbackContainer(cb, r)) | |
134 | defer id.Delete() | |
155 | 135 | err = newError(C.yr_rules_scan_proc( |
156 | 136 | r.cptr, |
157 | 137 | C.int(pid), |
158 | 138 | flags.withReportFlags(cb), |
159 | 139 | C.YR_CALLBACK_FUNC(C.scanCallbackFunc), |
160 | id, | |
140 | unsafe.Pointer(id), | |
161 | 141 | C.int(timeout/time.Second))) |
162 | 142 | runtime.KeepAlive(r) |
163 | 143 | return |
170 | 150 | c := makeMemoryBlockIteratorContainer(mbi) |
171 | 151 | defer c.free() |
172 | 152 | cmbi := makeCMemoryBlockIterator(c) |
173 | defer callbackData.Delete(cmbi.context) | |
174 | id := callbackData.Put(makeScanCallbackContainer(cb, r)) | |
175 | defer callbackData.Delete(id) | |
153 | defer cgoHandle(cmbi.context).Delete() | |
154 | id := cgoNewHandle(makeScanCallbackContainer(cb, r)) | |
155 | defer id.Delete() | |
176 | 156 | err = newError(C.yr_rules_scan_mem_blocks( |
177 | 157 | r.cptr, |
178 | 158 | cmbi, |
179 | 159 | flags.withReportFlags(cb), |
180 | 160 | C.YR_CALLBACK_FUNC(C.scanCallbackFunc), |
181 | id, | |
161 | unsafe.Pointer(id), | |
182 | 162 | C.int(timeout/time.Second))) |
183 | 163 | runtime.KeepAlive(r) |
184 | 164 | return |
207 | 187 | |
208 | 188 | // Write writes a compiled ruleset to an io.Writer. |
209 | 189 | func (r *Rules) Write(wr io.Writer) (err error) { |
210 | id := callbackData.Put(wr) | |
211 | defer callbackData.Delete(id) | |
190 | id := cgoNewHandle(wr) | |
191 | defer id.Delete() | |
212 | 192 | |
213 | 193 | stream := C.YR_STREAM{ |
214 | 194 | write: C.YR_STREAM_WRITE_FUNC(C.streamWrite), |
215 | 195 | // The complaint from go vet about possible misuse of |
216 | 196 | // unsafe.Pointer is wrong: user_data will be interpreted as |
217 | 197 | // an uintptr on the other side of the callback |
218 | user_data: id, | |
198 | user_data: unsafe.Pointer(id), | |
219 | 199 | } |
220 | 200 | err = newError(C.yr_rules_save_stream(r.cptr, &stream)) |
221 | 201 | runtime.KeepAlive(r) |
224 | 204 | |
225 | 205 | // ReadRules retrieves a compiled ruleset from an io.Reader. |
226 | 206 | func ReadRules(rd io.Reader) (*Rules, error) { |
227 | id := callbackData.Put(rd) | |
228 | defer callbackData.Delete(id) | |
207 | id := cgoNewHandle(rd) | |
208 | defer id.Delete() | |
229 | 209 | |
230 | 210 | stream := C.YR_STREAM{ |
231 | 211 | read: C.YR_STREAM_READ_FUNC(C.streamRead), |
232 | 212 | // The complaint from go vet about possible misuse of |
233 | 213 | // unsafe.Pointer is wrong, see above. |
234 | user_data: id, | |
214 | user_data: unsafe.Pointer(id), | |
235 | 215 | } |
236 | 216 | r := &Rules{} |
237 | 217 | if err := newError(C.yr_rules_load_stream(&stream, &(r.cptr))); err != nil { |
102 | 102 | |
103 | 103 | //export scanCallbackFunc |
104 | 104 | func scanCallbackFunc(ctx *C.YR_SCAN_CONTEXT, message C.int, messageData, userData unsafe.Pointer) C.int { |
105 | cbc, ok := callbackData.Get(userData).(*scanCallbackContainer) | |
105 | cbc, ok := cgoHandle(userData).Value().(*scanCallbackContainer) | |
106 | 106 | s := &ScanContext{cptr: ctx} |
107 | 107 | if !ok { |
108 | 108 | return C.CALLBACK_ERROR |
7 | 7 | |
8 | 8 | /* |
9 | 9 | #include <yara.h> |
10 | ||
11 | #ifdef _WIN32 | |
12 | #include <stdint.h> | |
13 | int _yr_scanner_scan_fd( | |
14 | YR_SCANNER* scanner, | |
15 | int fd) | |
16 | { | |
17 | return yr_scanner_scan_fd(scanner, (YR_FILE_DESCRIPTOR)(intptr_t)fd); | |
18 | } | |
19 | #else | |
20 | #define _yr_scanner_scan_fd yr_scanner_scan_fd | |
21 | #endif | |
10 | #include "compat.h" | |
22 | 11 | |
23 | 12 | int scanCallbackFunc(YR_SCAN_CONTEXT*, int, void*, void*); |
24 | 13 | */ |
126 | 115 | } |
127 | 116 | |
128 | 117 | // putCallbackData stores the scanner's callback object in |
129 | // callbackData, returning a pointer. If no callback object has been | |
118 | // a cgoHandle. If no callback object has been | |
130 | 119 | // set, it is initialized with the pointer to an empty ScanRules |
131 | // object. The object must be removed from callbackData by the calling | |
132 | // ScanXxxx function. | |
133 | func (s *Scanner) putCallbackData() unsafe.Pointer { | |
120 | // object. The handle must be deleted by the calling ScanXxxx function. | |
121 | func (s *Scanner) putCallbackData() cgoHandle { | |
134 | 122 | if _, ok := s.Callback.(ScanCallback); !ok { |
135 | 123 | s.Callback = &MatchRules{} |
136 | 124 | } |
137 | ptr := callbackData.Put(makeScanCallbackContainer(s.Callback, s.rules)) | |
138 | C.yr_scanner_set_callback(s.cptr, C.YR_CALLBACK_FUNC(C.scanCallbackFunc), ptr) | |
125 | ptr := cgoNewHandle(makeScanCallbackContainer(s.Callback, s.rules)) | |
126 | C.yr_scanner_set_callback(s.cptr, C.YR_CALLBACK_FUNC(C.scanCallbackFunc), unsafe.Pointer(ptr)) | |
139 | 127 | return ptr |
140 | 128 | } |
141 | 129 | |
150 | 138 | } |
151 | 139 | |
152 | 140 | cbPtr := s.putCallbackData() |
153 | defer callbackData.Delete(cbPtr) | |
141 | defer cbPtr.Delete() | |
154 | 142 | |
155 | 143 | C.yr_scanner_set_flags(s.cptr, s.flags.withReportFlags(s.Callback)) |
156 | 144 | err = newError(C.yr_scanner_scan_mem( |
170 | 158 | defer C.free(unsafe.Pointer(cfilename)) |
171 | 159 | |
172 | 160 | cbPtr := s.putCallbackData() |
173 | defer callbackData.Delete(cbPtr) | |
161 | defer cbPtr.Delete() | |
174 | 162 | |
175 | 163 | C.yr_scanner_set_flags(s.cptr, s.flags.withReportFlags(s.Callback)) |
176 | 164 | err = newError(C.yr_scanner_scan_file( |
187 | 175 | // SetCAllback, it is initialized with an empty MatchRules object. |
188 | 176 | func (s *Scanner) ScanFileDescriptor(fd uintptr) (err error) { |
189 | 177 | cbPtr := s.putCallbackData() |
190 | defer callbackData.Delete(cbPtr) | |
178 | defer cbPtr.Delete() | |
191 | 179 | |
192 | 180 | C.yr_scanner_set_flags(s.cptr, s.flags.withReportFlags(s.Callback)) |
193 | 181 | err = newError(C._yr_scanner_scan_fd( |
204 | 192 | // SetCAllback, it is initialized with an empty MatchRules object. |
205 | 193 | func (s *Scanner) ScanProc(pid int) (err error) { |
206 | 194 | cbPtr := s.putCallbackData() |
207 | defer callbackData.Delete(cbPtr) | |
195 | defer cbPtr.Delete() | |
208 | 196 | |
209 | 197 | C.yr_scanner_set_flags(s.cptr, s.flags.withReportFlags(s.Callback)) |
210 | 198 | err = newError(C.yr_scanner_scan_proc( |
223 | 211 | c := makeMemoryBlockIteratorContainer(mbi) |
224 | 212 | defer c.free() |
225 | 213 | cmbi := makeCMemoryBlockIterator(c) |
226 | defer callbackData.Delete(cmbi.context) | |
227 | ||
228 | cbPtr := s.putCallbackData() | |
229 | defer callbackData.Delete(cbPtr) | |
214 | defer cgoHandle(cmbi.context).Delete() | |
215 | ||
216 | cbPtr := s.putCallbackData() | |
217 | defer cbPtr.Delete() | |
230 | 218 | |
231 | 219 | C.yr_scanner_set_flags(s.cptr, s.flags.withReportFlags(s.Callback)) |
232 | 220 | err = newError(C.yr_scanner_scan_mem_blocks( |
19 | 19 | if size == 0 || nmemb == 0 { |
20 | 20 | return nmemb |
21 | 21 | } |
22 | reader := callbackData.Get(userData).(io.Reader) | |
22 | reader := cgoHandle(userData).Value().(io.Reader) | |
23 | 23 | buf := make([]byte, 0) |
24 | 24 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf)) |
25 | 25 | hdr.Data = uintptr(ptr) |
52 | 52 | if size == 0 || nmemb == 0 { |
53 | 53 | return nmemb |
54 | 54 | } |
55 | writer := callbackData.Get(userData).(io.Writer) | |
55 | writer := cgoHandle(userData).Value().(io.Writer) | |
56 | 56 | buf := make([]byte, 0) |
57 | 57 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf)) |
58 | 58 | hdr.Data = uintptr(ptr) |