0
# Configuration and Error Handling
1
2
YARA-Python provides configuration options for the YARA engine and a comprehensive exception hierarchy for handling various error conditions during rule compilation and scanning operations.
3
4
## Capabilities
5
6
### Engine Configuration
7
8
Configure YARA engine parameters to optimize performance and resource usage for specific use cases.
9
10
```python { .api }
11
def set_config(stack_size=None, max_strings_per_rule=None):
12
"""
13
Set YARA configuration variables.
14
15
Parameters:
16
- stack_size (int, optional): Maximum stack size for YARA engine
17
- max_strings_per_rule (int, optional): Maximum number of strings per rule
18
19
Notes:
20
Configuration changes affect all subsequent rule compilation and matching operations.
21
"""
22
```
23
24
**Stack size configuration:**
25
26
```python
27
import yara
28
29
# Set maximum stack size (in bytes)
30
yara.set_config(stack_size=65536) # 64KB stack
31
32
# This affects recursion depth in complex rules
33
rules = yara.compile(source='''
34
rule DeepRecursion {
35
condition:
36
// Complex nested conditions that may require more stack space
37
true
38
}
39
''')
40
```
41
42
**String limit configuration:**
43
44
```python
45
# Set maximum strings per rule
46
yara.set_config(max_strings_per_rule=10000)
47
48
# Allows compilation of rules with many strings
49
rules = yara.compile(source='''
50
rule ManyStrings {
51
strings:
52
$s1 = "pattern1"
53
$s2 = "pattern2"
54
// ... many more strings up to the limit
55
condition:
56
any of them
57
}
58
''')
59
```
60
61
**Combined configuration:**
62
63
```python
64
# Configure multiple parameters
65
yara.set_config(
66
stack_size=131072, # 128KB stack
67
max_strings_per_rule=5000 # Up to 5000 strings per rule
68
)
69
```
70
71
### Exception Hierarchy
72
73
YARA-Python provides a structured exception hierarchy for handling different error conditions.
74
75
```python { .api }
76
class Error(Exception):
77
"""Base exception class for all YARA-related errors."""
78
79
class SyntaxError(Error):
80
"""Raised when YARA rules contain syntax errors."""
81
82
class TimeoutError(Error):
83
"""Raised when scanning operations exceed timeout limits."""
84
85
class WarningError(Error):
86
"""Raised for warning conditions when error_on_warning is enabled."""
87
```
88
89
### Syntax Error Handling
90
91
Handle rule compilation errors with detailed error information.
92
93
**Basic syntax error handling:**
94
95
```python
96
import yara
97
98
try:
99
# Invalid rule syntax
100
rules = yara.compile(source='''
101
rule InvalidRule {
102
strings:
103
$missing_quote = "unclosed string
104
condition:
105
$missing_quote
106
}
107
''')
108
except yara.SyntaxError as e:
109
print(f"Rule compilation failed: {e}")
110
# Handle syntax error - perhaps show user-friendly message
111
```
112
113
**Advanced syntax error handling:**
114
115
```python
116
def compile_rules_safely(rule_source, rule_name="Unknown"):
117
"""Safely compile rules with detailed error reporting."""
118
try:
119
return yara.compile(source=rule_source)
120
except yara.SyntaxError as e:
121
print(f"Syntax error in rule '{rule_name}':")
122
print(f" Error: {e}")
123
print(f" Rule source preview:")
124
for i, line in enumerate(rule_source.split('\n')[:5], 1):
125
print(f" {i}: {line}")
126
return None
127
except yara.Error as e:
128
print(f"General YARA error in rule '{rule_name}': {e}")
129
return None
130
131
# Usage
132
rules = compile_rules_safely(invalid_rule_source, "MyRule")
133
if rules is None:
134
print("Rule compilation failed, using fallback rules")
135
```
136
137
### Timeout Error Handling
138
139
Handle scanning timeout conditions gracefully.
140
141
**Timeout handling with fallback:**
142
143
```python
144
def scan_with_timeout(rules, target_file, max_timeout=60):
145
"""Scan file with timeout and fallback strategies."""
146
try:
147
return rules.match(filepath=target_file, timeout=max_timeout)
148
except yara.TimeoutError:
149
print(f"Scan of {target_file} timed out after {max_timeout}s")
150
151
# Try with fast mode as fallback
152
try:
153
print("Retrying with fast mode...")
154
return rules.match(filepath=target_file, timeout=30, fast=True)
155
except yara.TimeoutError:
156
print("Fast mode scan also timed out")
157
return [] # Return empty results
158
except yara.Error as e:
159
print(f"Scan error: {e}")
160
return []
161
162
# Usage
163
matches = scan_with_timeout(rules, "/path/to/large_file.bin")
164
```
165
166
### Warning Error Handling
167
168
Handle warning conditions when strict error checking is enabled.
169
170
**Warning as error handling:**
171
172
```python
173
def compile_strict_rules(rule_source):
174
"""Compile rules with warnings treated as errors."""
175
try:
176
return yara.compile(
177
source=rule_source,
178
error_on_warning=True
179
)
180
except yara.WarningError as e:
181
print(f"Rule warning (treated as error): {e}")
182
print("Consider revising rule to eliminate warnings")
183
return None
184
except yara.SyntaxError as e:
185
print(f"Rule syntax error: {e}")
186
return None
187
188
# Usage with potentially problematic rule
189
rule_with_warnings = '''
190
rule PotentialWarning {
191
strings:
192
$unused = "never_referenced" // May generate warning
193
condition:
194
true // Doesn't use $unused
195
}
196
'''
197
198
rules = compile_strict_rules(rule_with_warnings)
199
```
200
201
### Comprehensive Error Handling
202
203
A complete error handling strategy for production use.
204
205
**Production-ready error handling:**
206
207
```python
208
import yara
209
import logging
210
211
class YaraManager:
212
"""Production YARA rule manager with comprehensive error handling."""
213
214
def __init__(self, stack_size=65536, max_strings=10000):
215
"""Initialize with custom configuration."""
216
try:
217
yara.set_config(
218
stack_size=stack_size,
219
max_strings_per_rule=max_strings
220
)
221
logging.info(f"YARA configured: stack={stack_size}, max_strings={max_strings}")
222
except Exception as e:
223
logging.error(f"YARA configuration failed: {e}")
224
raise
225
226
def compile_rules(self, rule_sources, externals=None):
227
"""Compile rules with comprehensive error handling."""
228
try:
229
if isinstance(rule_sources, str):
230
# Single rule source
231
return yara.compile(source=rule_sources, externals=externals)
232
elif isinstance(rule_sources, dict):
233
# Multiple sources with namespaces
234
return yara.compile(sources=rule_sources, externals=externals)
235
else:
236
raise ValueError("rule_sources must be string or dict")
237
238
except yara.SyntaxError as e:
239
logging.error(f"Rule syntax error: {e}")
240
raise
241
except yara.Error as e:
242
logging.error(f"YARA compilation error: {e}")
243
raise
244
except Exception as e:
245
logging.error(f"Unexpected error during compilation: {e}")
246
raise
247
248
def scan_target(self, rules, target, scan_timeout=120):
249
"""Scan target with comprehensive error handling."""
250
try:
251
if isinstance(target, str):
252
if target.startswith('/') or '\\' in target:
253
# File path
254
return rules.match(filepath=target, timeout=scan_timeout)
255
else:
256
# String data
257
return rules.match(data=target, timeout=scan_timeout)
258
elif isinstance(target, bytes):
259
# Binary data
260
return rules.match(data=target, timeout=scan_timeout)
261
elif isinstance(target, int):
262
# Process ID
263
return rules.match(pid=target, timeout=scan_timeout)
264
else:
265
raise ValueError("Unsupported target type")
266
267
except yara.TimeoutError:
268
logging.warning(f"Scan timed out after {scan_timeout}s")
269
return [] # Return empty results instead of raising
270
except yara.Error as e:
271
logging.error(f"YARA scan error: {e}")
272
raise
273
except PermissionError as e:
274
logging.error(f"Permission denied during scan: {e}")
275
return []
276
except Exception as e:
277
logging.error(f"Unexpected error during scan: {e}")
278
raise
279
280
# Usage example
281
if __name__ == "__main__":
282
logging.basicConfig(level=logging.INFO)
283
284
manager = YaraManager()
285
286
try:
287
# Compile rules
288
rules = manager.compile_rules('''
289
rule TestRule {
290
strings:
291
$test = "malicious"
292
condition:
293
$test
294
}
295
''')
296
297
# Scan various targets
298
results1 = manager.scan_target(rules, "test malicious data")
299
results2 = manager.scan_target(rules, "/path/to/file.bin")
300
results3 = manager.scan_target(rules, 1234) # Process ID
301
302
print(f"Scan results: {len(results1 + results2 + results3)} total matches")
303
304
except Exception as e:
305
logging.error(f"YARA operation failed: {e}")
306
```
307
308
### Error Recovery Strategies
309
310
Implement robust error recovery for mission-critical applications.
311
312
**Graceful degradation:**
313
314
```python
315
def resilient_scan(rule_files, target_files):
316
"""Perform scanning with graceful degradation on errors."""
317
successful_scans = 0
318
total_matches = []
319
320
for rule_file in rule_files:
321
try:
322
# Try to compile each rule file
323
rules = yara.compile(filepath=rule_file)
324
325
for target_file in target_files:
326
try:
327
# Try to scan each target
328
matches = rules.match(filepath=target_file, timeout=30)
329
total_matches.extend(matches)
330
successful_scans += 1
331
332
except yara.TimeoutError:
333
# Try fast mode on timeout
334
try:
335
fast_matches = rules.match(filepath=target_file, fast=True, timeout=10)
336
total_matches.extend(fast_matches)
337
successful_scans += 1
338
except:
339
logging.warning(f"Failed to scan {target_file} with {rule_file}")
340
341
except Exception as e:
342
logging.warning(f"Scan error {target_file}: {e}")
343
continue
344
345
except yara.SyntaxError as e:
346
logging.error(f"Invalid rule file {rule_file}: {e}")
347
continue
348
except Exception as e:
349
logging.error(f"Failed to load {rule_file}: {e}")
350
continue
351
352
logging.info(f"Completed {successful_scans} successful scans")
353
return total_matches
354
```