/src/yara/libyara/compiler.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | Copyright (c) 2013-2018. The YARA Authors. All Rights Reserved. |
3 | | |
4 | | Redistribution and use in source and binary forms, with or without modification, |
5 | | are permitted provided that the following conditions are met: |
6 | | |
7 | | 1. Redistributions of source code must retain the above copyright notice, this |
8 | | list of conditions and the following disclaimer. |
9 | | |
10 | | 2. Redistributions in binary form must reproduce the above copyright notice, |
11 | | this list of conditions and the following disclaimer in the documentation and/or |
12 | | other materials provided with the distribution. |
13 | | |
14 | | 3. Neither the name of the copyright holder nor the names of its contributors |
15 | | may be used to endorse or promote products derived from this software without |
16 | | specific prior written permission. |
17 | | |
18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
19 | | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
20 | | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
21 | | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
22 | | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
23 | | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
24 | | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
25 | | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
26 | | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
27 | | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | | */ |
29 | | |
30 | | #include <assert.h> |
31 | | #include <fcntl.h> |
32 | | #include <stddef.h> |
33 | | #include <stdio.h> |
34 | | #include <string.h> |
35 | | #include <sys/stat.h> |
36 | | |
37 | | #ifdef _MSC_VER |
38 | | #include <io.h> |
39 | | #include <share.h> |
40 | | #else |
41 | | #include <unistd.h> |
42 | | #endif |
43 | | |
44 | | #include <yara/compiler.h> |
45 | | #include <yara/error.h> |
46 | | #include <yara/exec.h> |
47 | | #include <yara/lexer.h> |
48 | | #include <yara/libyara.h> |
49 | | #include <yara/mem.h> |
50 | | #include <yara/object.h> |
51 | | #include <yara/strutils.h> |
52 | | #include <yara/utils.h> |
53 | | |
54 | | static void _yr_compiler_default_include_free( |
55 | | const char* callback_result_ptr, |
56 | | void* user_data) |
57 | 0 | { |
58 | 0 | if (callback_result_ptr != NULL) |
59 | 0 | { |
60 | 0 | yr_free((void*) callback_result_ptr); |
61 | 0 | } |
62 | 0 | } |
63 | | |
64 | | const char* _yr_compiler_default_include_callback( |
65 | | const char* include_name, |
66 | | const char* calling_rule_filename, |
67 | | const char* calling_rule_namespace, |
68 | | void* user_data) |
69 | 613 | { |
70 | 613 | #ifndef _MSC_VER |
71 | 613 | struct stat stbuf; |
72 | 613 | #endif |
73 | | |
74 | 613 | char* file_buffer; |
75 | | |
76 | | #ifdef _MSC_VER |
77 | | long file_size; |
78 | | #else |
79 | 613 | off_t file_size; |
80 | 613 | #endif |
81 | | |
82 | 613 | int fd = -1; |
83 | | |
84 | | #if defined(_MSC_VER) |
85 | | _sopen_s(&fd, include_name, _O_RDONLY | _O_BINARY, _SH_DENYWR, _S_IREAD); |
86 | | #elif defined(_WIN32) || defined(__CYGWIN__) |
87 | | fd = open(include_name, O_RDONLY | O_BINARY); |
88 | | #else |
89 | 613 | fd = open(include_name, O_RDONLY); |
90 | 613 | #endif |
91 | | |
92 | 613 | if (fd == -1) |
93 | 347 | return NULL; |
94 | | |
95 | | #ifdef _MSC_VER |
96 | | file_size = _filelength(fd); |
97 | | if (file_size == -1) |
98 | | { |
99 | | _close(fd); |
100 | | return NULL; |
101 | | } |
102 | | #else |
103 | 266 | if ((fstat(fd, &stbuf) != 0) || (!S_ISREG(stbuf.st_mode))) |
104 | 266 | { |
105 | 266 | close(fd); |
106 | 266 | return NULL; |
107 | 266 | } |
108 | 0 | file_size = stbuf.st_size; |
109 | 0 | #endif |
110 | |
|
111 | 0 | file_buffer = (char*) yr_malloc((size_t) file_size + 1); |
112 | |
|
113 | 0 | if (file_buffer == NULL) |
114 | 0 | { |
115 | | #ifdef _MSC_VER |
116 | | _close(fd); |
117 | | #else |
118 | 0 | close(fd); |
119 | 0 | #endif |
120 | |
|
121 | 0 | return NULL; |
122 | 0 | } |
123 | | |
124 | 0 | if (file_size != read(fd, file_buffer, (size_t) file_size)) |
125 | 0 | { |
126 | 0 | yr_free(file_buffer); |
127 | |
|
128 | | #ifdef _MSC_VER |
129 | | _close(fd); |
130 | | #else |
131 | 0 | close(fd); |
132 | 0 | #endif |
133 | |
|
134 | 0 | return NULL; |
135 | 0 | } |
136 | 0 | else |
137 | 0 | { |
138 | 0 | file_buffer[file_size] = '\0'; |
139 | 0 | } |
140 | | |
141 | | #ifdef _MSC_VER |
142 | | _close(fd); |
143 | | #else |
144 | 0 | close(fd); |
145 | 0 | #endif |
146 | |
|
147 | 0 | return file_buffer; |
148 | 0 | } |
149 | | |
150 | | //////////////////////////////////////////////////////////////////////////////// |
151 | | // Returns a rule given its index in the rules table. |
152 | | // |
153 | | // The returned pointer is valid as long as no other rule is written to the |
154 | | // table. This is because the write operation may cause the table to be moved to |
155 | | // a different location in memory. Use the pointer only in a limited scope where |
156 | | // you can be sure that no other rule is being written during the pointer's |
157 | | // lifetime. |
158 | | // |
159 | | YR_RULE* _yr_compiler_get_rule_by_idx(YR_COMPILER* compiler, uint32_t rule_idx) |
160 | 42.4k | { |
161 | 42.4k | return (YR_RULE*) yr_arena_get_ptr( |
162 | 42.4k | compiler->arena, YR_RULES_TABLE, rule_idx * sizeof(YR_RULE)); |
163 | 42.4k | } |
164 | | |
165 | | //////////////////////////////////////////////////////////////////////////////// |
166 | | // Stores some data in the YR_SZ_POOL and returns a reference to it. |
167 | | // |
168 | | // If the same data was already stored in a previous call to this function the |
169 | | // data is not written again, a reference to the existing data is returned |
170 | | // instead. |
171 | | // |
172 | | int _yr_compiler_store_data( |
173 | | YR_COMPILER* compiler, |
174 | | const void* data, |
175 | | size_t data_length, |
176 | | YR_ARENA_REF* ref) |
177 | 48.8k | { |
178 | | // Check if the data is already in YR_SZ_POOL by using a hash table. |
179 | 48.8k | uint32_t offset = yr_hash_table_lookup_uint32_raw_key( |
180 | 48.8k | compiler->sz_table, data, data_length, NULL); |
181 | | |
182 | 48.8k | if (offset == UINT32_MAX) |
183 | 12.7k | { |
184 | | // The data was not previously written to YR_SZ_POOL, write it and store |
185 | | // the reference's offset in the hash table. Storing the buffer number |
186 | | // is not necessary, it's always YR_SZ_POOL. |
187 | 12.7k | FAIL_ON_ERROR(yr_arena_write_data( |
188 | 12.7k | compiler->arena, YR_SZ_POOL, data, data_length, ref)); |
189 | | |
190 | 12.7k | FAIL_ON_ERROR(yr_hash_table_add_uint32_raw_key( |
191 | 12.7k | compiler->sz_table, data, data_length, NULL, ref->offset)); |
192 | 12.7k | } |
193 | 36.1k | else |
194 | 36.1k | { |
195 | 36.1k | ref->buffer_id = YR_SZ_POOL; |
196 | 36.1k | ref->offset = offset; |
197 | 36.1k | } |
198 | | |
199 | 48.8k | return ERROR_SUCCESS; |
200 | 48.8k | } |
201 | | |
202 | | //////////////////////////////////////////////////////////////////////////////// |
203 | | // Similar to _yr_compiler_store_data, but receives a null-terminated string. |
204 | | // |
205 | | int _yr_compiler_store_string( |
206 | | YR_COMPILER* compiler, |
207 | | const char* string, |
208 | | YR_ARENA_REF* ref) |
209 | 32.7k | { |
210 | 32.7k | return _yr_compiler_store_data( |
211 | 32.7k | compiler, |
212 | 32.7k | (void*) string, |
213 | 32.7k | strlen(string) + 1, // include the null terminator |
214 | 32.7k | ref); |
215 | 32.7k | } |
216 | | |
217 | | YR_API int yr_compiler_create(YR_COMPILER** compiler) |
218 | 1.35k | { |
219 | 1.35k | int result; |
220 | 1.35k | YR_COMPILER* new_compiler; |
221 | | |
222 | 1.35k | new_compiler = (YR_COMPILER*) yr_calloc(1, sizeof(YR_COMPILER)); |
223 | | |
224 | 1.35k | if (new_compiler == NULL) |
225 | 0 | return ERROR_INSUFFICIENT_MEMORY; |
226 | | |
227 | 1.35k | new_compiler->current_rule_idx = UINT32_MAX; |
228 | 1.35k | new_compiler->next_rule_idx = 0; |
229 | 1.35k | new_compiler->current_string_idx = 0; |
230 | 1.35k | new_compiler->current_namespace_idx = 0; |
231 | 1.35k | new_compiler->current_meta_idx = 0; |
232 | 1.35k | new_compiler->num_namespaces = 0; |
233 | 1.35k | new_compiler->errors = 0; |
234 | 1.35k | new_compiler->callback = NULL; |
235 | 1.35k | new_compiler->rules = NULL; |
236 | 1.35k | new_compiler->include_callback = _yr_compiler_default_include_callback; |
237 | 1.35k | new_compiler->incl_clbk_user_data = NULL; |
238 | 1.35k | new_compiler->include_free = _yr_compiler_default_include_free; |
239 | 1.35k | new_compiler->re_ast_callback = NULL; |
240 | 1.35k | new_compiler->re_ast_clbk_user_data = NULL; |
241 | 1.35k | new_compiler->last_error = ERROR_SUCCESS; |
242 | 1.35k | new_compiler->last_error_line = 0; |
243 | 1.35k | new_compiler->strict_escape = false; |
244 | 1.35k | new_compiler->current_line = 0; |
245 | 1.35k | new_compiler->file_name_stack_ptr = 0; |
246 | 1.35k | new_compiler->fixup_stack_head = NULL; |
247 | 1.35k | new_compiler->loop_index = -1; |
248 | 1.35k | new_compiler->loop_for_of_var_index = -1; |
249 | | |
250 | 1.35k | new_compiler->atoms_config.get_atom_quality = yr_atoms_heuristic_quality; |
251 | 1.35k | new_compiler->atoms_config.quality_warning_threshold = |
252 | 1.35k | YR_ATOM_QUALITY_WARNING_THRESHOLD; |
253 | | |
254 | 1.35k | result = yr_hash_table_create(5000, &new_compiler->rules_table); |
255 | | |
256 | 1.35k | if (result == ERROR_SUCCESS) |
257 | 1.35k | result = yr_hash_table_create(1000, &new_compiler->objects_table); |
258 | | |
259 | 1.35k | if (result == ERROR_SUCCESS) |
260 | 1.35k | result = yr_hash_table_create(10000, &new_compiler->strings_table); |
261 | | |
262 | 1.35k | if (result == ERROR_SUCCESS) |
263 | 1.35k | result = yr_hash_table_create( |
264 | 1.35k | 1000, &new_compiler->wildcard_identifiers_table); |
265 | | |
266 | 1.35k | if (result == ERROR_SUCCESS) |
267 | 1.35k | result = yr_hash_table_create(10000, &new_compiler->sz_table); |
268 | | |
269 | 1.35k | if (result == ERROR_SUCCESS) |
270 | 1.35k | result = yr_arena_create(YR_NUM_SECTIONS, 1048576, &new_compiler->arena); |
271 | | |
272 | 1.35k | if (result == ERROR_SUCCESS) |
273 | 1.35k | result = yr_ac_automaton_create( |
274 | 1.35k | new_compiler->arena, &new_compiler->automaton); |
275 | | |
276 | 1.35k | if (result == ERROR_SUCCESS) |
277 | 1.35k | { |
278 | 1.35k | *compiler = new_compiler; |
279 | 1.35k | } |
280 | 0 | else // if error, do cleanup |
281 | 0 | { |
282 | 0 | yr_compiler_destroy(new_compiler); |
283 | 0 | } |
284 | | |
285 | 1.35k | return result; |
286 | 1.35k | } |
287 | | |
288 | | YR_API void yr_compiler_destroy(YR_COMPILER* compiler) |
289 | 1.35k | { |
290 | 1.35k | if (compiler->arena != NULL) |
291 | 1.35k | yr_arena_release(compiler->arena); |
292 | | |
293 | 1.35k | if (compiler->automaton != NULL) |
294 | 1.35k | yr_ac_automaton_destroy(compiler->automaton); |
295 | | |
296 | 1.35k | if (compiler->rules_table != NULL) |
297 | 1.35k | yr_hash_table_destroy(compiler->rules_table, NULL); |
298 | | |
299 | 1.35k | if (compiler->strings_table != NULL) |
300 | 1.35k | yr_hash_table_destroy(compiler->strings_table, NULL); |
301 | | |
302 | 1.35k | if (compiler->wildcard_identifiers_table != NULL) |
303 | 1.35k | yr_hash_table_destroy(compiler->wildcard_identifiers_table, NULL); |
304 | | |
305 | 1.35k | if (compiler->sz_table != NULL) |
306 | 1.35k | yr_hash_table_destroy(compiler->sz_table, NULL); |
307 | | |
308 | 1.35k | if (compiler->objects_table != NULL) |
309 | 1.35k | yr_hash_table_destroy( |
310 | 1.35k | compiler->objects_table, |
311 | 1.35k | (YR_HASH_TABLE_FREE_VALUE_FUNC) yr_object_destroy); |
312 | | |
313 | 1.35k | if (compiler->atoms_config.free_quality_table) |
314 | 0 | yr_free(compiler->atoms_config.quality_table); |
315 | | |
316 | 1.35k | for (int i = 0; i < compiler->file_name_stack_ptr; i++) |
317 | 0 | yr_free(compiler->file_name_stack[i]); |
318 | | |
319 | 1.35k | YR_FIXUP* fixup = compiler->fixup_stack_head; |
320 | | |
321 | 16.1k | while (fixup != NULL) |
322 | 14.7k | { |
323 | 14.7k | YR_FIXUP* next_fixup = fixup->next; |
324 | 14.7k | yr_free(fixup); |
325 | 14.7k | fixup = next_fixup; |
326 | 14.7k | } |
327 | | |
328 | 1.35k | yr_free(compiler); |
329 | 1.35k | } |
330 | | |
331 | | YR_API void yr_compiler_set_callback( |
332 | | YR_COMPILER* compiler, |
333 | | YR_COMPILER_CALLBACK_FUNC callback, |
334 | | void* user_data) |
335 | 0 | { |
336 | 0 | compiler->callback = callback; |
337 | 0 | compiler->user_data = user_data; |
338 | 0 | } |
339 | | |
340 | | YR_API void yr_compiler_set_include_callback( |
341 | | YR_COMPILER* compiler, |
342 | | YR_COMPILER_INCLUDE_CALLBACK_FUNC include_callback, |
343 | | YR_COMPILER_INCLUDE_FREE_FUNC include_free, |
344 | | void* user_data) |
345 | 0 | { |
346 | 0 | compiler->include_callback = include_callback; |
347 | 0 | compiler->include_free = include_free; |
348 | 0 | compiler->incl_clbk_user_data = user_data; |
349 | 0 | } |
350 | | |
351 | | YR_API void yr_compiler_set_re_ast_callback( |
352 | | YR_COMPILER* compiler, |
353 | | YR_COMPILER_RE_AST_CALLBACK_FUNC re_ast_callback, |
354 | | void* user_data) |
355 | 0 | { |
356 | 0 | compiler->re_ast_callback = re_ast_callback; |
357 | 0 | compiler->re_ast_clbk_user_data = user_data; |
358 | 0 | } |
359 | | |
360 | | //////////////////////////////////////////////////////////////////////////////// |
361 | | // This function allows to specify an atom quality table to be used by the |
362 | | // compiler for choosing the best atoms from regular expressions and strings. |
363 | | // When a quality table is set, the compiler uses yr_atoms_table_quality |
364 | | // instead of yr_atoms_heuristic_quality for computing atom quality. The table |
365 | | // has an arbitrary number of entries, each composed of YR_MAX_ATOM_LENGTH + 1 |
366 | | // bytes. The first YR_MAX_ATOM_LENGTH bytes from each entry are the atom's |
367 | | // ones, and the remaining byte is a value in the range 0-255 determining the |
368 | | // atom's quality. Entries must be lexicographically sorted by atom in ascending |
369 | | // order. |
370 | | // |
371 | | // [ atom (YR_MAX_ATOM_LENGTH bytes) ] [ quality (1 byte) ] |
372 | | // |
373 | | // [ 00 00 .. 00 00 ] [ 00 ] |
374 | | // [ 00 00 .. 00 01 ] [ 45 ] |
375 | | // [ 00 00 .. 00 02 ] [ 13 ] |
376 | | // ... |
377 | | // [ FF FF .. FF FF ] [ 03 ] |
378 | | // |
379 | | // The "table" argument must point to a buffer containing the quality in |
380 | | // the format explained above, and "entries" must contain the number of entries |
381 | | // in the table. The table can not be freed while the compiler is in use, the |
382 | | // caller is responsible for freeing the table. |
383 | | // |
384 | | // The "warning_threshold" argument must be a number between 0 and 255, if some |
385 | | // atom chosen for a string have a quality below the specified threshold a |
386 | | // warning like "<string> is slowing down scanning" is shown. |
387 | | // |
388 | | YR_API void yr_compiler_set_atom_quality_table( |
389 | | YR_COMPILER* compiler, |
390 | | const void* table, |
391 | | int entries, |
392 | | unsigned char warning_threshold) |
393 | 0 | { |
394 | 0 | compiler->atoms_config.free_quality_table = false; |
395 | 0 | compiler->atoms_config.quality_warning_threshold = warning_threshold; |
396 | 0 | compiler->atoms_config.get_atom_quality = yr_atoms_table_quality; |
397 | 0 | compiler->atoms_config.quality_table_entries = entries; |
398 | 0 | compiler->atoms_config.quality_table = (YR_ATOM_QUALITY_TABLE_ENTRY*) table; |
399 | 0 | } |
400 | | |
401 | | //////////////////////////////////////////////////////////////////////////////// |
402 | | // Load an atom quality table from a file. The file's content must have the |
403 | | // format explained in the description for yr_compiler_set_atom_quality_table. |
404 | | // |
405 | | YR_API int yr_compiler_load_atom_quality_table( |
406 | | YR_COMPILER* compiler, |
407 | | const char* filename, |
408 | | unsigned char warning_threshold) |
409 | 0 | { |
410 | 0 | long file_size; |
411 | 0 | int entries; |
412 | 0 | void* table; |
413 | |
|
414 | 0 | FILE* fh = fopen(filename, "rb"); |
415 | |
|
416 | 0 | if (fh == NULL) |
417 | 0 | return ERROR_COULD_NOT_OPEN_FILE; |
418 | | |
419 | 0 | fseek(fh, 0L, SEEK_END); |
420 | 0 | file_size = ftell(fh); |
421 | 0 | fseek(fh, 0L, SEEK_SET); |
422 | |
|
423 | 0 | if (file_size == -1L) |
424 | 0 | { |
425 | 0 | fclose(fh); |
426 | 0 | return ERROR_COULD_NOT_READ_FILE; |
427 | 0 | } |
428 | | |
429 | 0 | table = yr_malloc(file_size); |
430 | |
|
431 | 0 | if (table == NULL) |
432 | 0 | { |
433 | 0 | fclose(fh); |
434 | 0 | return ERROR_INSUFFICIENT_MEMORY; |
435 | 0 | } |
436 | | |
437 | 0 | entries = (int) file_size / sizeof(YR_ATOM_QUALITY_TABLE_ENTRY); |
438 | |
|
439 | 0 | if (fread(table, sizeof(YR_ATOM_QUALITY_TABLE_ENTRY), entries, fh) != entries) |
440 | 0 | { |
441 | 0 | fclose(fh); |
442 | 0 | yr_free(table); |
443 | 0 | return ERROR_COULD_NOT_READ_FILE; |
444 | 0 | } |
445 | | |
446 | 0 | fclose(fh); |
447 | |
|
448 | 0 | yr_compiler_set_atom_quality_table( |
449 | 0 | compiler, table, entries, warning_threshold); |
450 | |
|
451 | 0 | compiler->atoms_config.free_quality_table = true; |
452 | |
|
453 | 0 | return ERROR_SUCCESS; |
454 | 0 | } |
455 | | |
456 | | int _yr_compiler_push_file_name(YR_COMPILER* compiler, const char* file_name) |
457 | 0 | { |
458 | 0 | char* str; |
459 | 0 | int i; |
460 | |
|
461 | 0 | for (i = 0; i < compiler->file_name_stack_ptr; i++) |
462 | 0 | { |
463 | 0 | if (strcmp(file_name, compiler->file_name_stack[i]) == 0) |
464 | 0 | return ERROR_INCLUDES_CIRCULAR_REFERENCE; |
465 | 0 | } |
466 | | |
467 | 0 | if (compiler->file_name_stack_ptr == YR_MAX_INCLUDE_DEPTH) |
468 | 0 | return ERROR_INCLUDE_DEPTH_EXCEEDED; |
469 | | |
470 | 0 | str = yr_strdup(file_name); |
471 | |
|
472 | 0 | if (str == NULL) |
473 | 0 | return ERROR_INSUFFICIENT_MEMORY; |
474 | | |
475 | 0 | compiler->file_name_stack[compiler->file_name_stack_ptr] = str; |
476 | 0 | compiler->file_name_stack_ptr++; |
477 | |
|
478 | 0 | return ERROR_SUCCESS; |
479 | 0 | } |
480 | | |
481 | | void _yr_compiler_pop_file_name(YR_COMPILER* compiler) |
482 | 0 | { |
483 | 0 | if (compiler->file_name_stack_ptr > 0) |
484 | 0 | { |
485 | 0 | compiler->file_name_stack_ptr--; |
486 | 0 | yr_free(compiler->file_name_stack[compiler->file_name_stack_ptr]); |
487 | 0 | compiler->file_name_stack[compiler->file_name_stack_ptr] = NULL; |
488 | 0 | } |
489 | 0 | } |
490 | | |
491 | | int _yr_compiler_get_var_frame(YR_COMPILER* compiler) |
492 | 2.39k | { |
493 | 2.39k | int i, result = 0; |
494 | | |
495 | 3.63k | for (i = 0; i < compiler->loop_index; i++) |
496 | 1.24k | { |
497 | 1.24k | result += compiler->loop[i].vars_count + |
498 | 1.24k | compiler->loop[i].vars_internal_count; |
499 | 1.24k | } |
500 | | |
501 | 2.39k | return result; |
502 | 2.39k | } |
503 | | |
504 | | YR_API char* yr_compiler_get_current_file_name(YR_COMPILER* compiler) |
505 | 613 | { |
506 | 613 | if (compiler->file_name_stack_ptr > 0) |
507 | 0 | { |
508 | 0 | return compiler->file_name_stack[compiler->file_name_stack_ptr - 1]; |
509 | 0 | } |
510 | 613 | else |
511 | 613 | { |
512 | 613 | return NULL; |
513 | 613 | } |
514 | 613 | } |
515 | | |
516 | | static int _yr_compiler_set_namespace( |
517 | | YR_COMPILER* compiler, |
518 | | const char* namespace_) |
519 | 1.35k | { |
520 | 1.35k | YR_NAMESPACE* ns = (YR_NAMESPACE*) yr_arena_get_ptr( |
521 | 1.35k | compiler->arena, YR_NAMESPACES_TABLE, 0); |
522 | | |
523 | 1.35k | bool found = false; |
524 | | |
525 | 1.35k | for (int i = 0; i < compiler->num_namespaces; i++, ns++) |
526 | 0 | { |
527 | 0 | if (strcmp(ns->name, namespace_) == 0) |
528 | 0 | { |
529 | 0 | found = true; |
530 | 0 | compiler->current_namespace_idx = i; |
531 | 0 | break; |
532 | 0 | } |
533 | 0 | } |
534 | | |
535 | 1.35k | if (!found) |
536 | 1.35k | { |
537 | 1.35k | YR_ARENA_REF ref; |
538 | | |
539 | 1.35k | FAIL_ON_ERROR(yr_arena_allocate_struct( |
540 | 1.35k | compiler->arena, |
541 | 1.35k | YR_NAMESPACES_TABLE, |
542 | 1.35k | sizeof(YR_NAMESPACE), |
543 | 1.35k | &ref, |
544 | 1.35k | offsetof(YR_NAMESPACE, name), |
545 | 1.35k | EOL)); |
546 | | |
547 | 1.35k | ns = (YR_NAMESPACE*) yr_arena_ref_to_ptr(compiler->arena, &ref); |
548 | | |
549 | 1.35k | FAIL_ON_ERROR(_yr_compiler_store_string(compiler, namespace_, &ref)); |
550 | | |
551 | 1.35k | ns->name = (const char*) yr_arena_ref_to_ptr(compiler->arena, &ref); |
552 | 1.35k | ns->idx = compiler->num_namespaces; |
553 | | |
554 | 1.35k | compiler->current_namespace_idx = compiler->num_namespaces; |
555 | 1.35k | compiler->num_namespaces++; |
556 | 1.35k | } |
557 | | |
558 | 1.35k | return ERROR_SUCCESS; |
559 | 1.35k | } |
560 | | |
561 | | YR_API int yr_compiler_add_file( |
562 | | YR_COMPILER* compiler, |
563 | | FILE* rules_file, |
564 | | const char* namespace_, |
565 | | const char* file_name) |
566 | 0 | { |
567 | 0 | int result; |
568 | | |
569 | | // Don't allow yr_compiler_add_file() after |
570 | | // yr_compiler_get_rules() has been called. |
571 | |
|
572 | 0 | assert(compiler->rules == NULL); |
573 | | |
574 | | // Don't allow calls to yr_compiler_add_file() if a previous call to |
575 | | // yr_compiler_add_XXXX failed. |
576 | | |
577 | 0 | assert(compiler->errors == 0); |
578 | | |
579 | 0 | if (namespace_ != NULL) |
580 | 0 | compiler->last_error = _yr_compiler_set_namespace(compiler, namespace_); |
581 | 0 | else |
582 | 0 | compiler->last_error = _yr_compiler_set_namespace(compiler, "default"); |
583 | |
|
584 | 0 | if (compiler->last_error == ERROR_SUCCESS && file_name != NULL) |
585 | 0 | compiler->last_error = _yr_compiler_push_file_name(compiler, file_name); |
586 | |
|
587 | 0 | if (compiler->last_error != ERROR_SUCCESS) |
588 | 0 | return ++compiler->errors; |
589 | | |
590 | 0 | result = yr_lex_parse_rules_file(rules_file, compiler); |
591 | |
|
592 | 0 | if (file_name != NULL) |
593 | 0 | _yr_compiler_pop_file_name(compiler); |
594 | |
|
595 | 0 | return result; |
596 | 0 | } |
597 | | |
598 | | YR_API int yr_compiler_add_fd( |
599 | | YR_COMPILER* compiler, |
600 | | YR_FILE_DESCRIPTOR rules_fd, |
601 | | const char* namespace_, |
602 | | const char* file_name) |
603 | 0 | { |
604 | 0 | int result; |
605 | | |
606 | | // Don't allow yr_compiler_add_fd() after |
607 | | // yr_compiler_get_rules() has been called. |
608 | 0 | assert(compiler->rules == NULL); |
609 | | |
610 | | // Don't allow calls to yr_compiler_add_fd() if a previous call to |
611 | | // yr_compiler_add_XXXX failed. |
612 | 0 | assert(compiler->errors == 0); |
613 | | |
614 | 0 | if (namespace_ != NULL) |
615 | 0 | compiler->last_error = _yr_compiler_set_namespace(compiler, namespace_); |
616 | 0 | else |
617 | 0 | compiler->last_error = _yr_compiler_set_namespace(compiler, "default"); |
618 | |
|
619 | 0 | if (compiler->last_error == ERROR_SUCCESS && file_name != NULL) |
620 | 0 | compiler->last_error = _yr_compiler_push_file_name(compiler, file_name); |
621 | |
|
622 | 0 | if (compiler->last_error != ERROR_SUCCESS) |
623 | 0 | return ++compiler->errors; |
624 | | |
625 | 0 | result = yr_lex_parse_rules_fd(rules_fd, compiler); |
626 | |
|
627 | 0 | if (file_name != NULL) |
628 | 0 | _yr_compiler_pop_file_name(compiler); |
629 | |
|
630 | 0 | return result; |
631 | 0 | } |
632 | | |
633 | | YR_API int yr_compiler_add_bytes( |
634 | | YR_COMPILER* compiler, |
635 | | const void* rules_data, |
636 | | size_t rules_size, |
637 | | const char* namespace_) |
638 | 0 | { |
639 | | // Don't allow calls to yr_compiler_add_bytes() after |
640 | | // yr_compiler_get_rules() has been called. |
641 | 0 | assert(compiler->rules == NULL); |
642 | | |
643 | | // Don't allow calls to yr_compiler_add_bytes() if a previous call to |
644 | | // yr_compiler_add_XXXX failed. |
645 | 0 | assert(compiler->errors == 0); |
646 | | |
647 | 0 | if (namespace_ != NULL) |
648 | 0 | compiler->last_error = _yr_compiler_set_namespace(compiler, namespace_); |
649 | 0 | else |
650 | 0 | compiler->last_error = _yr_compiler_set_namespace(compiler, "default"); |
651 | |
|
652 | 0 | if (compiler->last_error != ERROR_SUCCESS) |
653 | 0 | return ++compiler->errors; |
654 | | |
655 | 0 | return yr_lex_parse_rules_bytes(rules_data, rules_size, compiler); |
656 | 0 | } |
657 | | |
658 | | YR_API int yr_compiler_add_string( |
659 | | YR_COMPILER* compiler, |
660 | | const char* rules_string, |
661 | | const char* namespace_) |
662 | 1.35k | { |
663 | | // Don't allow calls to yr_compiler_add_string() after |
664 | | // yr_compiler_get_rules() has been called. |
665 | 1.35k | assert(compiler->rules == NULL); |
666 | | |
667 | | // Don't allow calls to yr_compiler_add_string() if a previous call to |
668 | | // yr_compiler_add_XXXX failed. |
669 | 1.35k | assert(compiler->errors == 0); |
670 | | |
671 | 1.35k | if (namespace_ != NULL) |
672 | 0 | compiler->last_error = _yr_compiler_set_namespace(compiler, namespace_); |
673 | 1.35k | else |
674 | 1.35k | compiler->last_error = _yr_compiler_set_namespace(compiler, "default"); |
675 | | |
676 | 1.35k | if (compiler->last_error != ERROR_SUCCESS) |
677 | 0 | return ++compiler->errors; |
678 | | |
679 | 1.35k | return yr_lex_parse_rules_string(rules_string, compiler); |
680 | 1.35k | } |
681 | | |
682 | | static int _yr_compiler_compile_rules(YR_COMPILER* compiler) |
683 | 97 | { |
684 | 97 | YR_RULE null_rule; |
685 | 97 | YR_EXTERNAL_VARIABLE null_external; |
686 | | |
687 | 97 | uint8_t halt = OP_HALT; |
688 | | |
689 | | // Write halt instruction at the end of code. |
690 | 97 | FAIL_ON_ERROR(yr_arena_write_data( |
691 | 97 | compiler->arena, YR_CODE_SECTION, &halt, sizeof(uint8_t), NULL)); |
692 | | |
693 | | // Write a null rule indicating the end. |
694 | 97 | memset(&null_rule, 0xFA, sizeof(YR_RULE)); |
695 | 97 | null_rule.flags = RULE_FLAGS_NULL; |
696 | | |
697 | 97 | FAIL_ON_ERROR(yr_arena_write_data( |
698 | 97 | compiler->arena, YR_RULES_TABLE, &null_rule, sizeof(YR_RULE), NULL)); |
699 | | |
700 | | // Write a null external indicating the end. |
701 | 97 | memset(&null_external, 0xFA, sizeof(YR_EXTERNAL_VARIABLE)); |
702 | 97 | null_external.type = EXTERNAL_VARIABLE_TYPE_NULL; |
703 | | |
704 | 97 | FAIL_ON_ERROR(yr_arena_write_data( |
705 | 97 | compiler->arena, |
706 | 97 | YR_EXTERNAL_VARIABLES_TABLE, |
707 | 97 | &null_external, |
708 | 97 | sizeof(YR_EXTERNAL_VARIABLE), |
709 | 97 | NULL)); |
710 | | |
711 | | // Write Aho-Corasick automaton to arena. |
712 | 97 | FAIL_ON_ERROR(yr_ac_compile(compiler->automaton, compiler->arena)); |
713 | | |
714 | 97 | YR_ARENA_REF ref; |
715 | | |
716 | 97 | FAIL_ON_ERROR(yr_arena_allocate_struct( |
717 | 97 | compiler->arena, YR_SUMMARY_SECTION, sizeof(YR_SUMMARY), &ref, EOL)); |
718 | | |
719 | 97 | YR_SUMMARY* summary = (YR_SUMMARY*) yr_arena_ref_to_ptr( |
720 | 97 | compiler->arena, &ref); |
721 | | |
722 | 97 | summary->num_namespaces = compiler->num_namespaces; |
723 | 97 | summary->num_rules = compiler->next_rule_idx; |
724 | 97 | summary->num_strings = compiler->current_string_idx; |
725 | | |
726 | 97 | return yr_rules_from_arena(compiler->arena, &compiler->rules); |
727 | 97 | } |
728 | | |
729 | | YR_API int yr_compiler_get_rules(YR_COMPILER* compiler, YR_RULES** rules) |
730 | 97 | { |
731 | | // Don't allow calls to yr_compiler_get_rules() if a previous call to |
732 | | // yr_compiler_add_XXXX failed. |
733 | 97 | assert(compiler->errors == 0); |
734 | | |
735 | 97 | *rules = NULL; |
736 | | |
737 | 97 | if (compiler->rules == NULL) |
738 | 97 | FAIL_ON_ERROR(_yr_compiler_compile_rules(compiler)); |
739 | | |
740 | 97 | *rules = compiler->rules; |
741 | | |
742 | 97 | return ERROR_SUCCESS; |
743 | 97 | } |
744 | | |
745 | | static int _yr_compiler_define_variable( |
746 | | YR_COMPILER* compiler, |
747 | | YR_EXTERNAL_VARIABLE* external) |
748 | 0 | { |
749 | 0 | YR_EXTERNAL_VARIABLE* ext; |
750 | 0 | YR_OBJECT* object; |
751 | |
|
752 | 0 | if (external->identifier == NULL) |
753 | 0 | return ERROR_INVALID_ARGUMENT; |
754 | | |
755 | 0 | object = (YR_OBJECT*) yr_hash_table_lookup( |
756 | 0 | compiler->objects_table, external->identifier, NULL); |
757 | |
|
758 | 0 | if (object != NULL) |
759 | 0 | return ERROR_DUPLICATED_EXTERNAL_VARIABLE; |
760 | | |
761 | 0 | YR_ARENA_REF ext_ref; |
762 | 0 | YR_ARENA_REF ref; |
763 | |
|
764 | 0 | FAIL_ON_ERROR(yr_arena_allocate_struct( |
765 | 0 | compiler->arena, |
766 | 0 | YR_EXTERNAL_VARIABLES_TABLE, |
767 | 0 | sizeof(YR_EXTERNAL_VARIABLE), |
768 | 0 | &ext_ref, |
769 | 0 | offsetof(YR_EXTERNAL_VARIABLE, identifier), |
770 | 0 | EOL)); |
771 | |
|
772 | 0 | ext = (YR_EXTERNAL_VARIABLE*) yr_arena_ref_to_ptr(compiler->arena, &ext_ref); |
773 | |
|
774 | 0 | FAIL_ON_ERROR( |
775 | 0 | _yr_compiler_store_string(compiler, external->identifier, &ref)); |
776 | |
|
777 | 0 | ext->identifier = (const char*) yr_arena_ref_to_ptr(compiler->arena, &ref); |
778 | |
|
779 | 0 | ext->type = external->type; |
780 | 0 | ext->value = external->value; |
781 | |
|
782 | 0 | if (external->type == EXTERNAL_VARIABLE_TYPE_STRING) |
783 | 0 | { |
784 | 0 | if (external->value.s == NULL) |
785 | 0 | return ERROR_INVALID_ARGUMENT; |
786 | | |
787 | 0 | FAIL_ON_ERROR(_yr_compiler_store_string(compiler, external->value.s, &ref)); |
788 | |
|
789 | 0 | FAIL_ON_ERROR(yr_arena_make_ptr_relocatable( |
790 | 0 | compiler->arena, |
791 | 0 | YR_EXTERNAL_VARIABLES_TABLE, |
792 | 0 | ext_ref.offset + offsetof(YR_EXTERNAL_VARIABLE, value.s), |
793 | 0 | EOL)); |
794 | |
|
795 | 0 | ext->value.s = (char*) yr_arena_ref_to_ptr(compiler->arena, &ref); |
796 | 0 | } |
797 | | |
798 | 0 | FAIL_ON_ERROR(yr_object_from_external_variable(external, &object)); |
799 | |
|
800 | 0 | FAIL_ON_ERROR_WITH_CLEANUP( |
801 | 0 | yr_hash_table_add( |
802 | 0 | compiler->objects_table, external->identifier, NULL, (void*) object), |
803 | 0 | yr_object_destroy(object)); |
804 | |
|
805 | 0 | return ERROR_SUCCESS; |
806 | 0 | } |
807 | | |
808 | | YR_API int yr_compiler_define_integer_variable( |
809 | | YR_COMPILER* compiler, |
810 | | const char* identifier, |
811 | | int64_t value) |
812 | 0 | { |
813 | 0 | YR_EXTERNAL_VARIABLE external; |
814 | |
|
815 | 0 | external.type = EXTERNAL_VARIABLE_TYPE_INTEGER; |
816 | 0 | external.identifier = identifier; |
817 | 0 | external.value.i = value; |
818 | |
|
819 | 0 | FAIL_ON_ERROR(_yr_compiler_define_variable(compiler, &external)); |
820 | |
|
821 | 0 | return ERROR_SUCCESS; |
822 | 0 | } |
823 | | |
824 | | YR_API int yr_compiler_define_boolean_variable( |
825 | | YR_COMPILER* compiler, |
826 | | const char* identifier, |
827 | | int value) |
828 | 0 | { |
829 | 0 | YR_EXTERNAL_VARIABLE external; |
830 | |
|
831 | 0 | external.type = EXTERNAL_VARIABLE_TYPE_BOOLEAN; |
832 | 0 | external.identifier = identifier; |
833 | 0 | external.value.i = value; |
834 | |
|
835 | 0 | FAIL_ON_ERROR(_yr_compiler_define_variable(compiler, &external)); |
836 | |
|
837 | 0 | return ERROR_SUCCESS; |
838 | 0 | } |
839 | | |
840 | | YR_API int yr_compiler_define_float_variable( |
841 | | YR_COMPILER* compiler, |
842 | | const char* identifier, |
843 | | double value) |
844 | 0 | { |
845 | 0 | YR_EXTERNAL_VARIABLE external; |
846 | |
|
847 | 0 | external.type = EXTERNAL_VARIABLE_TYPE_FLOAT; |
848 | 0 | external.identifier = identifier; |
849 | 0 | external.value.f = value; |
850 | |
|
851 | 0 | FAIL_ON_ERROR(_yr_compiler_define_variable(compiler, &external)); |
852 | |
|
853 | 0 | return ERROR_SUCCESS; |
854 | 0 | } |
855 | | |
856 | | YR_API int yr_compiler_define_string_variable( |
857 | | YR_COMPILER* compiler, |
858 | | const char* identifier, |
859 | | const char* value) |
860 | 0 | { |
861 | 0 | YR_EXTERNAL_VARIABLE external; |
862 | |
|
863 | 0 | external.type = EXTERNAL_VARIABLE_TYPE_STRING; |
864 | 0 | external.identifier = identifier; |
865 | 0 | external.value.s = (char*) value; |
866 | |
|
867 | 0 | FAIL_ON_ERROR(_yr_compiler_define_variable(compiler, &external)); |
868 | |
|
869 | 0 | return ERROR_SUCCESS; |
870 | 0 | } |
871 | | |
872 | | YR_API char* yr_compiler_get_error_message( |
873 | | YR_COMPILER* compiler, |
874 | | char* buffer, |
875 | | int buffer_size) |
876 | 0 | { |
877 | 0 | uint32_t max_strings_per_rule; |
878 | |
|
879 | 0 | switch (compiler->last_error) |
880 | 0 | { |
881 | 0 | case ERROR_INSUFFICIENT_MEMORY: |
882 | 0 | snprintf(buffer, buffer_size, "not enough memory"); |
883 | 0 | break; |
884 | 0 | case ERROR_DUPLICATED_IDENTIFIER: |
885 | 0 | snprintf( |
886 | 0 | buffer, |
887 | 0 | buffer_size, |
888 | 0 | "duplicated identifier \"%s\"", |
889 | 0 | compiler->last_error_extra_info); |
890 | 0 | break; |
891 | 0 | case ERROR_DUPLICATED_STRING_IDENTIFIER: |
892 | 0 | snprintf( |
893 | 0 | buffer, |
894 | 0 | buffer_size, |
895 | 0 | "duplicated string identifier \"%s\"", |
896 | 0 | compiler->last_error_extra_info); |
897 | 0 | break; |
898 | 0 | case ERROR_DUPLICATED_TAG_IDENTIFIER: |
899 | 0 | snprintf( |
900 | 0 | buffer, |
901 | 0 | buffer_size, |
902 | 0 | "duplicated tag identifier \"%s\"", |
903 | 0 | compiler->last_error_extra_info); |
904 | 0 | break; |
905 | 0 | case ERROR_DUPLICATED_META_IDENTIFIER: |
906 | 0 | snprintf( |
907 | 0 | buffer, |
908 | 0 | buffer_size, |
909 | 0 | "duplicated metadata identifier \"%s\"", |
910 | 0 | compiler->last_error_extra_info); |
911 | 0 | break; |
912 | 0 | case ERROR_DUPLICATED_LOOP_IDENTIFIER: |
913 | 0 | snprintf( |
914 | 0 | buffer, |
915 | 0 | buffer_size, |
916 | 0 | "duplicated loop identifier \"%s\"", |
917 | 0 | compiler->last_error_extra_info); |
918 | 0 | break; |
919 | 0 | case ERROR_UNDEFINED_STRING: |
920 | 0 | snprintf( |
921 | 0 | buffer, |
922 | 0 | buffer_size, |
923 | 0 | "undefined string \"%s\"", |
924 | 0 | compiler->last_error_extra_info); |
925 | 0 | break; |
926 | 0 | case ERROR_UNDEFINED_IDENTIFIER: |
927 | 0 | snprintf( |
928 | 0 | buffer, |
929 | 0 | buffer_size, |
930 | 0 | "undefined identifier \"%s\"", |
931 | 0 | compiler->last_error_extra_info); |
932 | 0 | break; |
933 | 0 | case ERROR_UNREFERENCED_STRING: |
934 | 0 | snprintf( |
935 | 0 | buffer, |
936 | 0 | buffer_size, |
937 | 0 | "unreferenced string \"%s\"", |
938 | 0 | compiler->last_error_extra_info); |
939 | 0 | break; |
940 | 0 | case ERROR_EMPTY_STRING: |
941 | 0 | snprintf( |
942 | 0 | buffer, |
943 | 0 | buffer_size, |
944 | 0 | "empty string \"%s\"", |
945 | 0 | compiler->last_error_extra_info); |
946 | 0 | break; |
947 | 0 | case ERROR_NOT_A_STRUCTURE: |
948 | 0 | snprintf( |
949 | 0 | buffer, |
950 | 0 | buffer_size, |
951 | 0 | "\"%s\" is not a structure", |
952 | 0 | compiler->last_error_extra_info); |
953 | 0 | break; |
954 | 0 | case ERROR_NOT_INDEXABLE: |
955 | 0 | snprintf( |
956 | 0 | buffer, |
957 | 0 | buffer_size, |
958 | 0 | "\"%s\" is not an array or dictionary", |
959 | 0 | compiler->last_error_extra_info); |
960 | 0 | break; |
961 | 0 | case ERROR_NOT_A_FUNCTION: |
962 | 0 | snprintf( |
963 | 0 | buffer, |
964 | 0 | buffer_size, |
965 | 0 | "\"%s\" is not a function", |
966 | 0 | compiler->last_error_extra_info); |
967 | 0 | break; |
968 | 0 | case ERROR_INVALID_FIELD_NAME: |
969 | 0 | snprintf( |
970 | 0 | buffer, |
971 | 0 | buffer_size, |
972 | 0 | "invalid field name \"%s\"", |
973 | 0 | compiler->last_error_extra_info); |
974 | 0 | break; |
975 | 0 | case ERROR_MISPLACED_ANONYMOUS_STRING: |
976 | 0 | snprintf(buffer, buffer_size, "wrong use of anonymous string"); |
977 | 0 | break; |
978 | 0 | case ERROR_INCLUDES_CIRCULAR_REFERENCE: |
979 | 0 | snprintf(buffer, buffer_size, "include circular reference"); |
980 | 0 | break; |
981 | 0 | case ERROR_INCLUDE_DEPTH_EXCEEDED: |
982 | 0 | snprintf(buffer, buffer_size, "too many levels of included rules"); |
983 | 0 | break; |
984 | 0 | case ERROR_LOOP_NESTING_LIMIT_EXCEEDED: |
985 | 0 | snprintf(buffer, buffer_size, "loop nesting limit exceeded"); |
986 | 0 | break; |
987 | 0 | case ERROR_NESTED_FOR_OF_LOOP: |
988 | 0 | snprintf( |
989 | 0 | buffer, |
990 | 0 | buffer_size, |
991 | 0 | "'for <quantifier> of <string set>' loops can't be nested"); |
992 | 0 | break; |
993 | 0 | case ERROR_UNKNOWN_MODULE: |
994 | 0 | snprintf( |
995 | 0 | buffer, |
996 | 0 | buffer_size, |
997 | 0 | "unknown module \"%s\"", |
998 | 0 | compiler->last_error_extra_info); |
999 | 0 | break; |
1000 | 0 | case ERROR_INVALID_MODULE_NAME: |
1001 | 0 | snprintf( |
1002 | 0 | buffer, |
1003 | 0 | buffer_size, |
1004 | 0 | "invalid module name \"%s\"", |
1005 | 0 | compiler->last_error_extra_info); |
1006 | 0 | break; |
1007 | 0 | case ERROR_DUPLICATED_STRUCTURE_MEMBER: |
1008 | 0 | snprintf(buffer, buffer_size, "duplicated structure member"); |
1009 | 0 | break; |
1010 | 0 | case ERROR_WRONG_ARGUMENTS: |
1011 | 0 | snprintf( |
1012 | 0 | buffer, |
1013 | 0 | buffer_size, |
1014 | 0 | "wrong arguments for function \"%s\"", |
1015 | 0 | compiler->last_error_extra_info); |
1016 | 0 | break; |
1017 | 0 | case ERROR_WRONG_RETURN_TYPE: |
1018 | 0 | snprintf(buffer, buffer_size, "wrong return type for overloaded function"); |
1019 | 0 | break; |
1020 | 0 | case ERROR_INVALID_HEX_STRING: |
1021 | 0 | case ERROR_INVALID_REGULAR_EXPRESSION: |
1022 | 0 | case ERROR_SYNTAX_ERROR: |
1023 | 0 | case ERROR_WRONG_TYPE: |
1024 | 0 | case ERROR_INVALID_MODIFIER: |
1025 | 0 | case ERROR_INVALID_PERCENTAGE: |
1026 | 0 | snprintf(buffer, buffer_size, "%s", compiler->last_error_extra_info); |
1027 | 0 | break; |
1028 | 0 | case ERROR_INTERNAL_FATAL_ERROR: |
1029 | 0 | snprintf(buffer, buffer_size, "internal fatal error"); |
1030 | 0 | break; |
1031 | 0 | case ERROR_DIVISION_BY_ZERO: |
1032 | 0 | snprintf(buffer, buffer_size, "division by zero"); |
1033 | 0 | break; |
1034 | 0 | case ERROR_REGULAR_EXPRESSION_TOO_LARGE: |
1035 | 0 | snprintf(buffer, buffer_size, "regular expression is too large"); |
1036 | 0 | break; |
1037 | 0 | case ERROR_REGULAR_EXPRESSION_TOO_COMPLEX: |
1038 | 0 | snprintf(buffer, buffer_size, "regular expression is too complex"); |
1039 | 0 | break; |
1040 | 0 | case ERROR_TOO_MANY_STRINGS: |
1041 | 0 | yr_get_configuration_uint32( |
1042 | 0 | YR_CONFIG_MAX_STRINGS_PER_RULE, &max_strings_per_rule); |
1043 | 0 | snprintf( |
1044 | 0 | buffer, |
1045 | 0 | buffer_size, |
1046 | 0 | "too many strings in rule \"%s\" (limit: %d)", |
1047 | 0 | compiler->last_error_extra_info, |
1048 | 0 | max_strings_per_rule); |
1049 | 0 | break; |
1050 | 0 | case ERROR_INTEGER_OVERFLOW: |
1051 | 0 | snprintf( |
1052 | 0 | buffer, |
1053 | 0 | buffer_size, |
1054 | 0 | "integer overflow in \"%s\"", |
1055 | 0 | compiler->last_error_extra_info); |
1056 | 0 | break; |
1057 | 0 | case ERROR_COULD_NOT_READ_FILE: |
1058 | 0 | snprintf(buffer, buffer_size, "could not read file"); |
1059 | 0 | break; |
1060 | 0 | case ERROR_DUPLICATED_MODIFIER: |
1061 | 0 | snprintf(buffer, buffer_size, "duplicated modifier"); |
1062 | 0 | break; |
1063 | 0 | case ERROR_IDENTIFIER_MATCHES_WILDCARD: |
1064 | 0 | snprintf( |
1065 | 0 | buffer, |
1066 | 0 | buffer_size, |
1067 | 0 | "rule identifier \"%s\" matches previously used wildcard rule set", |
1068 | 0 | compiler->last_error_extra_info); |
1069 | 0 | break; |
1070 | 0 | case ERROR_INVALID_VALUE: |
1071 | 0 | snprintf( |
1072 | 0 | buffer, |
1073 | 0 | buffer_size, |
1074 | 0 | "invalid value in condition: \"%s\"", |
1075 | 0 | compiler->last_error_extra_info); |
1076 | 0 | break; |
1077 | 0 | } |
1078 | | |
1079 | 0 | return buffer; |
1080 | 0 | } |