mirror of
https://github.com/Cisco-Talos/clamav.git
synced 2025-10-19 18:33:16 +00:00
Add the YARA compiler files.
This commit is contained in:
parent
a10670874c
commit
c329e3c72e
2 changed files with 999 additions and 0 deletions
806
libclamav/yara_compiler.c
Normal file
806
libclamav/yara_compiler.c
Normal file
|
@ -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 <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef REAL_YARA
|
||||||
|
#include <yara/utils.h>
|
||||||
|
#include <yara/compiler.h>
|
||||||
|
#include <yara/exec.h>
|
||||||
|
#include <yara/error.h>
|
||||||
|
#include <yara/mem.h>
|
||||||
|
#include <yara/object.h>
|
||||||
|
#include <yara/lexer.h>
|
||||||
|
#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 <quantifier> of <string set>' 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;
|
||||||
|
}
|
193
libclamav/yara_compiler.h
Normal file
193
libclamav/yara_compiler.h
Normal file
|
@ -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 <stdio.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
|
#ifdef REAL_YARA
|
||||||
|
#include <yara/ahocorasick.h>
|
||||||
|
#include <yara/arena.h>
|
||||||
|
#include <yara/hash.h>
|
||||||
|
#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
|
Loading…
Add table
Add a link
Reference in a new issue