From c329e3c72e5c9bfa6b54936bbf4516f6812c4565 Mon Sep 17 00:00:00 2001 From: Steven Morgan Date: Thu, 28 May 2015 18:00:16 -0400 Subject: [PATCH] Add the YARA compiler files. --- libclamav/yara_compiler.c | 806 ++++++++++++++++++++++++++++++++++++++ libclamav/yara_compiler.h | 193 +++++++++ 2 files changed, 999 insertions(+) create mode 100644 libclamav/yara_compiler.c create mode 100644 libclamav/yara_compiler.h diff --git a/libclamav/yara_compiler.c b/libclamav/yara_compiler.c new file mode 100644 index 000000000..9f8f9f837 --- /dev/null +++ b/libclamav/yara_compiler.c @@ -0,0 +1,806 @@ +/* +Copyright (c) 2013. The YARA Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include +#include +#include + +#ifdef REAL_YARA +#include +#include +#include +#include +#include +#include +#include +#else +#include "yara_clam.h" +#include "yara_compiler.h" +#include "yara_exec.h" +#include "yara_grammar.h" +#include "yara_lexer.h" +#endif + +#ifdef REAL_YARA +int yr_compiler_create( + YR_COMPILER** compiler) +{ + int result; + YR_COMPILER* new_compiler; + + new_compiler = (YR_COMPILER*) yr_malloc(sizeof(YR_COMPILER)); + + if (new_compiler == NULL) + return ERROR_INSUFICIENT_MEMORY; + + new_compiler->errors = 0; + new_compiler->callback = NULL; + new_compiler->last_error = ERROR_SUCCESS; + new_compiler->last_error_line = 0; + new_compiler->error_line = 0; + new_compiler->last_result = ERROR_SUCCESS; + new_compiler->file_stack_ptr = 0; + new_compiler->file_name_stack_ptr = 0; + new_compiler->current_rule_flags = 0; + new_compiler->allow_includes = 1; + new_compiler->loop_depth = 0; + new_compiler->loop_for_of_mem_offset = -1; + new_compiler->compiled_rules_arena = NULL; + new_compiler->namespaces_count = 0; + new_compiler->current_rule_strings = NULL; + + result = yr_hash_table_create(10007, &new_compiler->rules_table); + + if (result == ERROR_SUCCESS) + result = yr_hash_table_create(10007, &new_compiler->objects_table); + + if (result == ERROR_SUCCESS) + result = yr_arena_create(65536, 0, &new_compiler->sz_arena); + + if (result == ERROR_SUCCESS) + result = yr_arena_create(65536, 0, &new_compiler->rules_arena); + + if (result == ERROR_SUCCESS) + result = yr_arena_create(65536, 0, &new_compiler->strings_arena); + + if (result == ERROR_SUCCESS) + result = yr_arena_create(65536, 0, &new_compiler->code_arena); + + if (result == ERROR_SUCCESS) + result = yr_arena_create(65536, 0, &new_compiler->re_code_arena); + + if (result == ERROR_SUCCESS) + result = yr_arena_create(65536, 0, &new_compiler->automaton_arena); + + if (result == ERROR_SUCCESS) + result = yr_arena_create(65536, 0, &new_compiler->externals_arena); + + if (result == ERROR_SUCCESS) + result = yr_arena_create(65536, 0, &new_compiler->namespaces_arena); + + if (result == ERROR_SUCCESS) + result = yr_arena_create(65536, 0, &new_compiler->metas_arena); + + if (result == ERROR_SUCCESS) + result = yr_ac_create_automaton( + new_compiler->automaton_arena, + &new_compiler->automaton); + + if (result == ERROR_SUCCESS) + { + *compiler = new_compiler; + } + else // if error, do cleanup + { + yr_compiler_destroy(new_compiler); + } + + return result; +} + + +void yr_compiler_destroy( + YR_COMPILER* compiler) +{ + int i; + + if (compiler->compiled_rules_arena != NULL) + yr_arena_destroy(compiler->compiled_rules_arena); + + if (compiler->sz_arena != NULL) + yr_arena_destroy(compiler->sz_arena); + + if (compiler->rules_arena != NULL) + yr_arena_destroy(compiler->rules_arena); + + if (compiler->strings_arena != NULL) + yr_arena_destroy(compiler->strings_arena); + + if (compiler->code_arena != NULL) + yr_arena_destroy(compiler->code_arena); + + if (compiler->re_code_arena != NULL) + yr_arena_destroy(compiler->re_code_arena); + + if (compiler->automaton_arena != NULL) + yr_arena_destroy(compiler->automaton_arena); + + if (compiler->externals_arena != NULL) + yr_arena_destroy(compiler->externals_arena); + + if (compiler->namespaces_arena != NULL) + yr_arena_destroy(compiler->namespaces_arena); + + if (compiler->metas_arena != NULL) + yr_arena_destroy(compiler->metas_arena); + + yr_hash_table_destroy( + compiler->rules_table, + NULL); + + yr_hash_table_destroy( + compiler->objects_table, + (YR_HASH_TABLE_FREE_VALUE_FUNC) yr_object_destroy); + + for (i = 0; i < compiler->file_name_stack_ptr; i++) + yr_free(compiler->file_name_stack[i]); + + yr_free(compiler); +} + + +void yr_compiler_set_callback( + YR_COMPILER* compiler, + YR_COMPILER_CALLBACK_FUNC callback) +{ + compiler->callback = callback; +} +#endif + +int _yr_compiler_push_file( + YR_COMPILER* compiler, + FILE* fh) +{ + if (compiler->file_stack_ptr < MAX_INCLUDE_DEPTH) + { + compiler->file_stack[compiler->file_stack_ptr] = fh; + compiler->file_stack_ptr++; + return ERROR_SUCCESS; + } + else + { + compiler->last_result = ERROR_INCLUDE_DEPTH_EXCEEDED; + return ERROR_INCLUDE_DEPTH_EXCEEDED; + } +} + + +FILE* _yr_compiler_pop_file( + YR_COMPILER* compiler) +{ + FILE* result = NULL; + + if (compiler->file_stack_ptr > 0) + { + compiler->file_stack_ptr--; + result = compiler->file_stack[compiler->file_stack_ptr]; + } + + return result; +} + +int _yr_compiler_push_file_name( + YR_COMPILER* compiler, + const char* file_name) +{ + char* str; + int i; + + for (i = 0; i < compiler->file_name_stack_ptr; i++) + { + if (strcmp(file_name, compiler->file_name_stack[i]) == 0) + { + compiler->last_result = ERROR_INCLUDES_CIRCULAR_REFERENCE; + return ERROR_INCLUDES_CIRCULAR_REFERENCE; + } + } + + if (compiler->file_name_stack_ptr < MAX_INCLUDE_DEPTH) + { + str = yr_strdup(file_name); + + if (str == NULL) + return ERROR_INSUFICIENT_MEMORY; + + compiler->file_name_stack[compiler->file_name_stack_ptr] = str; + compiler->file_name_stack_ptr++; + + return ERROR_SUCCESS; + } + else + { + compiler->last_result = ERROR_INCLUDE_DEPTH_EXCEEDED; + return ERROR_INCLUDE_DEPTH_EXCEEDED; + } +} + + +void _yr_compiler_pop_file_name( + YR_COMPILER* compiler) +{ + if (compiler->file_name_stack_ptr > 0) + { + compiler->file_name_stack_ptr--; + yr_free(compiler->file_name_stack[compiler->file_name_stack_ptr]); + compiler->file_name_stack[compiler->file_name_stack_ptr] = NULL; + } +} + + +char* yr_compiler_get_current_file_name( + YR_COMPILER* context) +{ + if (context->file_name_stack_ptr > 0) + { + return context->file_name_stack[context->file_name_stack_ptr - 1]; + } + else + { + return NULL; + } +} + +#ifdef REAL_YARA +int _yr_compiler_set_namespace( + YR_COMPILER* compiler, + const char* namespace_) +{ + YR_NAMESPACE* ns; + + char* ns_name; + int result; + int i; + int found; + + ns = yr_arena_base_address(compiler->namespaces_arena); + found = FALSE; + + for (i = 0; i < compiler->namespaces_count; i++) + { + if (strcmp(ns->name, namespace_) == 0) + { + found = TRUE; + break; + } + + ns = yr_arena_next_address( + compiler->namespaces_arena, + ns, + sizeof(YR_NAMESPACE)); + } + + if (!found) + { + result = yr_arena_write_string( + compiler->sz_arena, + namespace_, + &ns_name); + + if (result == ERROR_SUCCESS) + result = yr_arena_allocate_struct( + compiler->namespaces_arena, + sizeof(YR_NAMESPACE), + (void*) &ns, + offsetof(YR_NAMESPACE, name), + EOL); + + if (result != ERROR_SUCCESS) + return result; + + ns->name = ns_name; + + for (i = 0; i < MAX_THREADS; i++) + ns->t_flags[i] = 0; + + compiler->namespaces_count++; + } + + compiler->current_namespace = ns; + return ERROR_SUCCESS; +} + +int yr_compiler_add_file( + YR_COMPILER* compiler, + FILE* rules_file, + const char* namespace_, + const char* file_name) +{ + // Don't allow yr_compiler_add_file() after + // yr_compiler_get_rules() has been called. + + assert(compiler->compiled_rules_arena == NULL); + + if (file_name != NULL) + _yr_compiler_push_file_name(compiler, file_name); + + if (namespace_ != NULL) + _yr_compiler_set_namespace(compiler, namespace_); + else + _yr_compiler_set_namespace(compiler, "default"); + + return yr_lex_parse_rules_file(rules_file, compiler); +} + + +int yr_compiler_add_string( + YR_COMPILER* compiler, + const char* rules_string, + const char* namespace_) +{ + // Don't allow yr_compiler_add_string() after + // yr_compiler_get_rules() has been called. + + assert(compiler->compiled_rules_arena == NULL); + + if (namespace_ != NULL) + _yr_compiler_set_namespace(compiler, namespace_); + else + _yr_compiler_set_namespace(compiler, "default"); + + return yr_lex_parse_rules_string(rules_string, compiler); +} + +int _yr_compiler_compile_rules( + YR_COMPILER* compiler) +{ + YARA_RULES_FILE_HEADER* rules_file_header = NULL; + YR_ARENA* arena; + YR_RULE null_rule; + YR_EXTERNAL_VARIABLE null_external; + + int8_t halt = OP_HALT; + int result; + + // Write halt instruction at the end of code. + yr_arena_write_data( + compiler->code_arena, + &halt, + sizeof(int8_t), + NULL); + + // Write a null rule indicating the end. + memset(&null_rule, 0xFA, sizeof(YR_RULE)); + null_rule.g_flags = RULE_GFLAGS_NULL; + + yr_arena_write_data( + compiler->rules_arena, + &null_rule, + sizeof(YR_RULE), + NULL); + + // Write a null external the end. + memset(&null_external, 0xFA, sizeof(YR_EXTERNAL_VARIABLE)); + null_external.type = EXTERNAL_VARIABLE_TYPE_NULL; + + yr_arena_write_data( + compiler->externals_arena, + &null_external, + sizeof(YR_EXTERNAL_VARIABLE), + NULL); + + // Create Aho-Corasick automaton's failure links. + yr_ac_create_failure_links( + compiler->automaton_arena, + compiler->automaton); + + result = yr_arena_create(1024, 0, &arena); + + if (result == ERROR_SUCCESS) + result = yr_arena_allocate_struct( + arena, + sizeof(YARA_RULES_FILE_HEADER), + (void**) &rules_file_header, + offsetof(YARA_RULES_FILE_HEADER, rules_list_head), + offsetof(YARA_RULES_FILE_HEADER, externals_list_head), + offsetof(YARA_RULES_FILE_HEADER, code_start), + offsetof(YARA_RULES_FILE_HEADER, automaton), + EOL); + + if (result == ERROR_SUCCESS) + { + rules_file_header->rules_list_head = yr_arena_base_address( + compiler->rules_arena); + + rules_file_header->externals_list_head = yr_arena_base_address( + compiler->externals_arena); + + rules_file_header->code_start = yr_arena_base_address( + compiler->code_arena); + + rules_file_header->automaton = yr_arena_base_address( + compiler->automaton_arena); + } + + if (result == ERROR_SUCCESS) + result = yr_arena_append( + arena, + compiler->automaton_arena); + + if (result == ERROR_SUCCESS) + { + compiler->automaton_arena = NULL; + result = yr_arena_append( + arena, + compiler->code_arena); + } + + if (result == ERROR_SUCCESS) + { + compiler->code_arena = NULL; + result = yr_arena_append( + arena, + compiler->re_code_arena); + } + + if (result == ERROR_SUCCESS) + { + compiler->re_code_arena = NULL; + result = yr_arena_append( + arena, + compiler->rules_arena); + } + + if (result == ERROR_SUCCESS) + { + compiler->rules_arena = NULL; + result = yr_arena_append( + arena, + compiler->strings_arena); + } + + if (result == ERROR_SUCCESS) + { + compiler->strings_arena = NULL; + result = yr_arena_append( + arena, + compiler->externals_arena); + } + + if (result == ERROR_SUCCESS) + { + compiler->externals_arena = NULL; + result = yr_arena_append( + arena, + compiler->namespaces_arena); + } + + if (result == ERROR_SUCCESS) + { + compiler->namespaces_arena = NULL; + result = yr_arena_append( + arena, + compiler->metas_arena); + } + + if (result == ERROR_SUCCESS) + { + compiler->metas_arena = NULL; + result = yr_arena_append( + arena, + compiler->sz_arena); + } + + if (result == ERROR_SUCCESS) + { + compiler->sz_arena = NULL; + compiler->compiled_rules_arena = arena; + result = yr_arena_coalesce(arena); + } + + return result; +} + + +int yr_compiler_get_rules( + YR_COMPILER* compiler, + YR_RULES** rules) +{ + YR_RULES* yara_rules; + YARA_RULES_FILE_HEADER* rules_file_header; + + *rules = NULL; + + if (compiler->compiled_rules_arena == NULL) + FAIL_ON_ERROR(_yr_compiler_compile_rules(compiler)); + + yara_rules = yr_malloc(sizeof(YR_RULES)); + + if (yara_rules == NULL) + return ERROR_INSUFICIENT_MEMORY; + + FAIL_ON_ERROR_WITH_CLEANUP( + yr_arena_duplicate(compiler->compiled_rules_arena, &yara_rules->arena), + yr_free(yara_rules)); + + rules_file_header = (YARA_RULES_FILE_HEADER*) yr_arena_base_address( + yara_rules->arena); + + yara_rules->externals_list_head = rules_file_header->externals_list_head; + yara_rules->rules_list_head = rules_file_header->rules_list_head; + yara_rules->automaton = rules_file_header->automaton; + yara_rules->code_start = rules_file_header->code_start; + yara_rules->tidx_mask = 0; + + #if _WIN32 + yara_rules->mutex = CreateMutex(NULL, FALSE, NULL); + #else + pthread_mutex_init(&yara_rules->mutex, NULL); + #endif + + *rules = yara_rules; + + return ERROR_SUCCESS; +} + + +int yr_compiler_define_integer_variable( + YR_COMPILER* compiler, + const char* identifier, + int64_t value) +{ + YR_EXTERNAL_VARIABLE* external; + YR_OBJECT* object; + + char* id; + + compiler->last_result = ERROR_SUCCESS; + + FAIL_ON_COMPILER_ERROR(yr_arena_write_string( + compiler->sz_arena, + identifier, + &id)); + + FAIL_ON_COMPILER_ERROR(yr_arena_allocate_struct( + compiler->externals_arena, + sizeof(YR_EXTERNAL_VARIABLE), + (void**) &external, + offsetof(YR_EXTERNAL_VARIABLE, identifier), + offsetof(YR_EXTERNAL_VARIABLE, string), + EOL)); + + external->type = EXTERNAL_VARIABLE_TYPE_INTEGER; + external->identifier = id; + external->integer = value; + external->string = NULL; + + FAIL_ON_COMPILER_ERROR(yr_object_from_external_variable( + external, + &object)); + + FAIL_ON_COMPILER_ERROR(yr_hash_table_add( + compiler->objects_table, + external->identifier, + NULL, + (void*) object)); + + return ERROR_SUCCESS; +} + + +int yr_compiler_define_boolean_variable( + YR_COMPILER* compiler, + const char* identifier, + int value) +{ + return yr_compiler_define_integer_variable( + compiler, + identifier, + value); +} + + +int yr_compiler_define_string_variable( + YR_COMPILER* compiler, + const char* identifier, + const char* value) +{ + YR_OBJECT* object; + YR_EXTERNAL_VARIABLE* external; + + char* id = NULL; + char* val = NULL; + + compiler->last_result = ERROR_SUCCESS; + + FAIL_ON_COMPILER_ERROR(yr_arena_write_string( + compiler->sz_arena, + identifier, + &id)); + + FAIL_ON_COMPILER_ERROR(yr_arena_write_string( + compiler->sz_arena, + value, + &val)); + + FAIL_ON_COMPILER_ERROR(yr_arena_allocate_struct( + compiler->externals_arena, + sizeof(YR_EXTERNAL_VARIABLE), + (void**) &external, + offsetof(YR_EXTERNAL_VARIABLE, identifier), + offsetof(YR_EXTERNAL_VARIABLE, string), + EOL)); + + external->type = EXTERNAL_VARIABLE_TYPE_STRING; + external->identifier = id; + external->integer = 0; + external->string = val; + + FAIL_ON_COMPILER_ERROR(yr_object_from_external_variable( + external, + &object)); + + FAIL_ON_COMPILER_ERROR(yr_hash_table_add( + compiler->objects_table, + external->identifier, + NULL, + (void*) object)); + + return compiler->last_result; +} +#endif + +char* yr_compiler_get_error_message( + YR_COMPILER* compiler, + char* buffer, + int buffer_size) +{ + switch(compiler->last_error) + { + case ERROR_INSUFICIENT_MEMORY: + snprintf(buffer, buffer_size, "not enough memory"); + break; + case ERROR_DUPLICATE_IDENTIFIER: + snprintf( + buffer, + buffer_size, + "duplicate identifier \"%s\"", + compiler->last_error_extra_info); + break; + case ERROR_DUPLICATE_STRING_IDENTIFIER: + snprintf( + buffer, + buffer_size, + "duplicate string identifier \"%s\"", + compiler->last_error_extra_info); + break; + case ERROR_DUPLICATE_TAG_IDENTIFIER: + snprintf( + buffer, + buffer_size, + "duplicate tag identifier \"%s\"", + compiler->last_error_extra_info); + break; + case ERROR_DUPLICATE_META_IDENTIFIER: + snprintf( + buffer, + buffer_size, + "duplicate metadata identifier \"%s\"", + compiler->last_error_extra_info); + break; + case ERROR_DUPLICATE_LOOP_IDENTIFIER: + snprintf( + buffer, + buffer_size, + "duplicate loop identifier \"%s\"", + compiler->last_error_extra_info); + break; + case ERROR_UNDEFINED_STRING: + snprintf( + buffer, + buffer_size, + "undefined string \"%s\"", + compiler->last_error_extra_info); + break; + case ERROR_UNDEFINED_IDENTIFIER: + snprintf( + buffer, + buffer_size, + "undefined identifier \"%s\"", + compiler->last_error_extra_info); + break; + case ERROR_UNREFERENCED_STRING: + snprintf( + buffer, + buffer_size, + "unreferenced string \"%s\"", + compiler->last_error_extra_info); + break; + case ERROR_NOT_A_STRUCTURE: + snprintf( + buffer, + buffer_size, + "\"%s\" is not a structure", + compiler->last_error_extra_info); + break; + case ERROR_NOT_AN_ARRAY: + snprintf( + buffer, + buffer_size, + "\"%s\" is not a array", + compiler->last_error_extra_info); + break; + case ERROR_INVALID_FIELD_NAME: + snprintf( + buffer, + buffer_size, + "invalid field name \"%s\"", + compiler->last_error_extra_info); + break; + case ERROR_MISPLACED_ANONYMOUS_STRING: + snprintf( + buffer, + buffer_size, + "wrong use of anonymous string"); + break; + case ERROR_INCLUDES_CIRCULAR_REFERENCE: + snprintf( + buffer, + buffer_size, + "include circular reference"); + break; + case ERROR_INCLUDE_DEPTH_EXCEEDED: + snprintf(buffer, + buffer_size, + "too many levels of included rules"); + break; + case ERROR_LOOP_NESTING_LIMIT_EXCEEDED: + snprintf(buffer, + buffer_size, + "loop nesting limit exceeded"); + break; + case ERROR_NESTED_FOR_OF_LOOP: + snprintf(buffer, + buffer_size, + "'for of ' loops can't be nested"); + break; + case ERROR_UNKNOWN_MODULE: + snprintf( + buffer, + buffer_size, + "unknown module \"%s\"", + compiler->last_error_extra_info); + break; + case ERROR_INVALID_HEX_STRING: + case ERROR_INVALID_REGULAR_EXPRESSION: + case ERROR_SYNTAX_ERROR: + case ERROR_WRONG_TYPE: + case ERROR_WRONG_NUMBER_OF_ARGUMENTS: + snprintf( + buffer, + buffer_size, + "%s", + compiler->last_error_extra_info); + break; + case ERROR_INTERNAL_FATAL_ERROR: + snprintf( + buffer, + buffer_size, + "internal fatal error"); + break; + } + + return buffer; +} diff --git a/libclamav/yara_compiler.h b/libclamav/yara_compiler.h new file mode 100644 index 000000000..f65d83014 --- /dev/null +++ b/libclamav/yara_compiler.h @@ -0,0 +1,193 @@ +/* +Copyright (c) 2013. The YARA Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#ifndef YR_COMPILER_H +#define YR_COMPILER_H + +#include +#include + +#ifdef REAL_YARA +#include +#include +#include +#else +#include "yara_arena.h" +#include "yara_hash.h" +#endif + +#define YARA_ERROR_LEVEL_ERROR 0 +#define YARA_ERROR_LEVEL_WARNING 1 + + +typedef void (*YR_COMPILER_CALLBACK_FUNC)( + int error_level, + const char* file_name, + int line_number, + const char* message); + + +typedef struct _YR_COMPILER +{ + int errors; + int error_line; + int last_error; + int last_error_line; + int last_result; + + jmp_buf error_recovery; + + YR_ARENA* sz_arena; + YR_ARENA* rules_arena; + YR_ARENA* strings_arena; + YR_ARENA* code_arena; + YR_ARENA* re_code_arena; + YR_ARENA* automaton_arena; + YR_ARENA* compiled_rules_arena; + YR_ARENA* externals_arena; + YR_ARENA* namespaces_arena; + YR_ARENA* metas_arena; + +#ifdef REAL_YARA + YR_AC_AUTOMATON* automaton; +#endif + YR_HASH_TABLE* rules_table; + YR_HASH_TABLE* objects_table; + YR_NAMESPACE* current_namespace; + YR_STRING* current_rule_strings; + + int current_rule_flags; + int namespaces_count; + + int8_t* loop_address[MAX_LOOP_NESTING]; + char* loop_identifier[MAX_LOOP_NESTING]; + int loop_depth; + int loop_for_of_mem_offset; + + int allow_includes; + + char* file_name_stack[MAX_INCLUDE_DEPTH]; + int file_name_stack_ptr; + + FILE* file_stack[MAX_INCLUDE_DEPTH]; + int file_stack_ptr; + + char last_error_extra_info[MAX_COMPILER_ERROR_EXTRA_INFO]; + + char lex_buf[LEX_BUF_SIZE]; + char* lex_buf_ptr; + unsigned short lex_buf_len; + + char include_base_dir[MAX_PATH]; + + + YR_COMPILER_CALLBACK_FUNC callback; + + /* Compiler fields for ClamAV */ + STAILQ_HEAD(rq, _yc_rule) rule_q; + STAILQ_HEAD(cs, _yc_string) current_rule_string_q; + YR_ARENA* the_arena; + uint32_t current_rule_clflags; + +} YR_COMPILER; + + +#define yr_compiler_set_error_extra_info(compiler, info) \ + strlcpy( \ + compiler->last_error_extra_info, \ + info, \ + sizeof(compiler->last_error_extra_info)); \ + + +int _yr_compiler_push_file( + YR_COMPILER* compiler, + FILE* fh); + + +FILE* _yr_compiler_pop_file( + YR_COMPILER* compiler); + + +int _yr_compiler_push_file_name( + YR_COMPILER* compiler, + const char* file_name); + + +void _yr_compiler_pop_file_name( + YR_COMPILER* compiler); + + +int yr_compiler_create( + YR_COMPILER** compiler); + + +void yr_compiler_destroy( + YR_COMPILER* compiler); + + +void yr_compiler_set_callback( + YR_COMPILER* compiler, + YR_COMPILER_CALLBACK_FUNC callback); + + +int yr_compiler_add_file( + YR_COMPILER* compiler, + FILE* rules_file, + const char* namespace_, + const char* file_name); + + +int yr_compiler_add_string( + YR_COMPILER* compiler, + const char* rules_string, + const char* namespace_); + + +char* yr_compiler_get_error_message( + YR_COMPILER* compiler, + char* buffer, + int buffer_size); + + +char* yr_compiler_get_current_file_name( + YR_COMPILER* context); + + +#ifdef REAL_YARA +int yr_compiler_define_integer_variable( + YR_COMPILER* compiler, + const char* identifier, + int64_t value); + + +int yr_compiler_define_boolean_variable( + YR_COMPILER* compiler, + const char* identifier, + int value); + + +int yr_compiler_define_string_variable( + YR_COMPILER* compiler, + const char* identifier, + const char* value); + + +int yr_compiler_get_rules( + YR_COMPILER* compiler, + YR_RULES** rules); +#endif + +#endif