clamav/libclamav/yara_compiler.c

781 lines
21 KiB
C
Raw Normal View History

2015-05-28 18:00:16 -04:00
/*
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>
2015-06-01 14:32:04 -04:00
#ifdef _WIN32
#include <stdint.h>
#endif
2015-05-28 18:00:16 -04:00
#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);
2015-05-28 18:00:16 -04:00
if (result == ERROR_SUCCESS)
result = yr_hash_table_create(10007, &new_compiler->objects_table);
2015-05-28 18:00:16 -04:00
if (result == ERROR_SUCCESS)
result = yr_arena_create(65536, 0, &new_compiler->sz_arena);
2015-05-28 18:00:16 -04:00
if (result == ERROR_SUCCESS)
result = yr_arena_create(65536, 0, &new_compiler->rules_arena);
2015-05-28 18:00:16 -04:00
if (result == ERROR_SUCCESS)
result = yr_arena_create(65536, 0, &new_compiler->strings_arena);
2015-05-28 18:00:16 -04:00
if (result == ERROR_SUCCESS)
result = yr_arena_create(65536, 0, &new_compiler->code_arena);
2015-05-28 18:00:16 -04:00
if (result == ERROR_SUCCESS)
result = yr_arena_create(65536, 0, &new_compiler->re_code_arena);
2015-05-28 18:00:16 -04:00
if (result == ERROR_SUCCESS)
result = yr_arena_create(65536, 0, &new_compiler->automaton_arena);
2015-05-28 18:00:16 -04:00
if (result == ERROR_SUCCESS)
result = yr_arena_create(65536, 0, &new_compiler->externals_arena);
2015-05-28 18:00:16 -04:00
if (result == ERROR_SUCCESS)
result = yr_arena_create(65536, 0, &new_compiler->namespaces_arena);
2015-05-28 18:00:16 -04:00
if (result == ERROR_SUCCESS)
result = yr_arena_create(65536, 0, &new_compiler->metas_arena);
2015-05-28 18:00:16 -04:00
if (result == ERROR_SUCCESS)
result = yr_ac_create_automaton(
new_compiler->automaton_arena,
&new_compiler->automaton);
2015-05-28 18:00:16 -04:00
if (result == ERROR_SUCCESS) {
*compiler = new_compiler;
} else // if error, do cleanup
{
yr_compiler_destroy(new_compiler);
}
2015-05-28 18:00:16 -04:00
return result;
2015-05-28 18:00:16 -04:00
}
void yr_compiler_destroy(
YR_COMPILER* compiler)
{
int i;
2015-05-28 18:00:16 -04:00
if (compiler->compiled_rules_arena != NULL)
yr_arena_destroy(compiler->compiled_rules_arena);
2015-05-28 18:00:16 -04:00
if (compiler->sz_arena != NULL)
yr_arena_destroy(compiler->sz_arena);
2015-05-28 18:00:16 -04:00
if (compiler->rules_arena != NULL)
yr_arena_destroy(compiler->rules_arena);
2015-05-28 18:00:16 -04:00
if (compiler->strings_arena != NULL)
yr_arena_destroy(compiler->strings_arena);
2015-05-28 18:00:16 -04:00
if (compiler->code_arena != NULL)
yr_arena_destroy(compiler->code_arena);
2015-05-28 18:00:16 -04:00
if (compiler->re_code_arena != NULL)
yr_arena_destroy(compiler->re_code_arena);
2015-05-28 18:00:16 -04:00
if (compiler->automaton_arena != NULL)
yr_arena_destroy(compiler->automaton_arena);
2015-05-28 18:00:16 -04:00
if (compiler->externals_arena != NULL)
yr_arena_destroy(compiler->externals_arena);
2015-05-28 18:00:16 -04:00
if (compiler->namespaces_arena != NULL)
yr_arena_destroy(compiler->namespaces_arena);
2015-05-28 18:00:16 -04:00
if (compiler->metas_arena != NULL)
yr_arena_destroy(compiler->metas_arena);
2015-05-28 18:00:16 -04:00
yr_hash_table_destroy(
compiler->rules_table,
NULL);
2015-05-28 18:00:16 -04:00
yr_hash_table_destroy(
compiler->objects_table,
(YR_HASH_TABLE_FREE_VALUE_FUNC)yr_object_destroy);
2015-05-28 18:00:16 -04:00
for (i = 0; i < compiler->file_name_stack_ptr; i++)
yr_free(compiler->file_name_stack[i]);
2015-05-28 18:00:16 -04:00
yr_free(compiler);
2015-05-28 18:00:16 -04:00
}
void yr_compiler_set_callback(
YR_COMPILER* compiler,
YR_COMPILER_CALLBACK_FUNC callback)
{
compiler->callback = callback;
2015-05-28 18:00:16 -04:00
}
#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;
}
2015-05-28 18:00:16 -04:00
}
FILE* _yr_compiler_pop_file(
YR_COMPILER* compiler)
{
FILE* result = NULL;
2015-05-28 18:00:16 -04:00
if (compiler->file_stack_ptr > 0) {
compiler->file_stack_ptr--;
result = compiler->file_stack[compiler->file_stack_ptr];
}
2015-05-28 18:00:16 -04:00
return result;
2015-05-28 18:00:16 -04:00
}
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;
}
2015-05-28 18:00:16 -04:00
}
if (compiler->file_name_stack_ptr < MAX_INCLUDE_DEPTH) {
str = yr_strdup(file_name);
2015-05-28 18:00:16 -04:00
if (str == NULL)
return ERROR_INSUFICIENT_MEMORY;
2015-05-28 18:00:16 -04:00
compiler->file_name_stack[compiler->file_name_stack_ptr] = str;
compiler->file_name_stack_ptr++;
2015-05-28 18:00:16 -04:00
return ERROR_SUCCESS;
} else {
compiler->last_result = ERROR_INCLUDE_DEPTH_EXCEEDED;
return ERROR_INCLUDE_DEPTH_EXCEEDED;
}
2015-05-28 18:00:16 -04:00
}
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;
}
2015-05-28 18:00:16 -04:00
}
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;
}
2015-05-28 18:00:16 -04:00
}
#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));
2015-05-28 18:00:16 -04:00
}
if (!found) {
result = yr_arena_write_string(
compiler->sz_arena,
namespace_,
&ns_name);
2015-05-28 18:00:16 -04:00
if (result == ERROR_SUCCESS)
result = yr_arena_allocate_struct(
compiler->namespaces_arena,
sizeof(YR_NAMESPACE),
(void*)&ns,
offsetof(YR_NAMESPACE, name),
EOL);
2015-05-28 18:00:16 -04:00
if (result != ERROR_SUCCESS)
return result;
2015-05-28 18:00:16 -04:00
ns->name = ns_name;
2015-05-28 18:00:16 -04:00
for (i = 0; i < MAX_THREADS; i++)
ns->t_flags[i] = 0;
2015-05-28 18:00:16 -04:00
compiler->namespaces_count++;
}
2015-05-28 18:00:16 -04:00
compiler->current_namespace = ns;
return ERROR_SUCCESS;
2015-05-28 18:00:16 -04:00
}
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.
2015-05-28 18:00:16 -04:00
assert(compiler->compiled_rules_arena == NULL);
2015-05-28 18:00:16 -04:00
if (file_name != NULL)
_yr_compiler_push_file_name(compiler, file_name);
2015-05-28 18:00:16 -04:00
if (namespace_ != NULL)
_yr_compiler_set_namespace(compiler, namespace_);
else
_yr_compiler_set_namespace(compiler, "default");
2015-05-28 18:00:16 -04:00
return yr_lex_parse_rules_file(rules_file, compiler);
2015-05-28 18:00:16 -04:00
}
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.
2015-05-28 18:00:16 -04:00
assert(compiler->compiled_rules_arena == NULL);
2015-05-28 18:00:16 -04:00
if (namespace_ != NULL)
_yr_compiler_set_namespace(compiler, namespace_);
else
_yr_compiler_set_namespace(compiler, "default");
2015-05-28 18:00:16 -04:00
return yr_lex_parse_rules_string(rules_string, compiler);
2015-05-28 18:00:16 -04:00
}
int _yr_compiler_compile_rules(
YR_COMPILER* compiler)
2015-05-28 18:00:16 -04:00
{
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);
2015-05-28 18:00:16 -04:00
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;
Code cleanup: Refactor to clean up formatting issues Refactored the clamscan code that determines 'what to scan' in order to clean up some very messy logic and also to get around a difference in how vscode and clang-format handle formatting #ifdef blocks in the middle of an else/if. In addition to refactoring, there is a slight behavior improvement. With this change, doing `clamscan blah -` will now scan `blah` and then also scan `stdin`. You can even do `clamscan - blah` to now scan `stdin` and then scan `blah`. Before, The `-` had to be the only "filename" argument in order to scan from stdin. In addition, added a bunch of extra empty lines or changing multi-line function calls to single-line function calls in order to get around a bug in clang-format with these two options do not playing nice together: - AlignConsecutiveAssignments: true - AlignAfterOpenBracket: true AlignAfterOpenBracket is not taking account the spaces inserted by AlignConsecutiveAssignments, so you end up with stuff like this: ```c bleeblah = 1; blah = function(arg1, arg2, arg3); // ^--- these args 4-left from where they should be. ``` VSCode, meanwhile, somehow fixes this whitespace issue so code that is correctly formatted by VSCode doesn't have this bug, meaning that: 1. The clang-format check in GH Actions fails. 2. We'd all have to stop using format-on-save in VSCode and accept the bug if we wanted those GH Actions tests to pass. Adding an empty line before variable assignments from multi-line function calls evades the buggy behavior. This commit should resolve the clang-format github action test failures, for now.
2022-03-10 20:55:13 -08:00
result = yr_arena_append(
arena,
compiler->code_arena);
}
if (result == ERROR_SUCCESS) {
compiler->code_arena = NULL;
Code cleanup: Refactor to clean up formatting issues Refactored the clamscan code that determines 'what to scan' in order to clean up some very messy logic and also to get around a difference in how vscode and clang-format handle formatting #ifdef blocks in the middle of an else/if. In addition to refactoring, there is a slight behavior improvement. With this change, doing `clamscan blah -` will now scan `blah` and then also scan `stdin`. You can even do `clamscan - blah` to now scan `stdin` and then scan `blah`. Before, The `-` had to be the only "filename" argument in order to scan from stdin. In addition, added a bunch of extra empty lines or changing multi-line function calls to single-line function calls in order to get around a bug in clang-format with these two options do not playing nice together: - AlignConsecutiveAssignments: true - AlignAfterOpenBracket: true AlignAfterOpenBracket is not taking account the spaces inserted by AlignConsecutiveAssignments, so you end up with stuff like this: ```c bleeblah = 1; blah = function(arg1, arg2, arg3); // ^--- these args 4-left from where they should be. ``` VSCode, meanwhile, somehow fixes this whitespace issue so code that is correctly formatted by VSCode doesn't have this bug, meaning that: 1. The clang-format check in GH Actions fails. 2. We'd all have to stop using format-on-save in VSCode and accept the bug if we wanted those GH Actions tests to pass. Adding an empty line before variable assignments from multi-line function calls evades the buggy behavior. This commit should resolve the clang-format github action test failures, for now.
2022-03-10 20:55:13 -08:00
result = yr_arena_append(
arena,
compiler->re_code_arena);
}
if (result == ERROR_SUCCESS) {
compiler->re_code_arena = NULL;
Code cleanup: Refactor to clean up formatting issues Refactored the clamscan code that determines 'what to scan' in order to clean up some very messy logic and also to get around a difference in how vscode and clang-format handle formatting #ifdef blocks in the middle of an else/if. In addition to refactoring, there is a slight behavior improvement. With this change, doing `clamscan blah -` will now scan `blah` and then also scan `stdin`. You can even do `clamscan - blah` to now scan `stdin` and then scan `blah`. Before, The `-` had to be the only "filename" argument in order to scan from stdin. In addition, added a bunch of extra empty lines or changing multi-line function calls to single-line function calls in order to get around a bug in clang-format with these two options do not playing nice together: - AlignConsecutiveAssignments: true - AlignAfterOpenBracket: true AlignAfterOpenBracket is not taking account the spaces inserted by AlignConsecutiveAssignments, so you end up with stuff like this: ```c bleeblah = 1; blah = function(arg1, arg2, arg3); // ^--- these args 4-left from where they should be. ``` VSCode, meanwhile, somehow fixes this whitespace issue so code that is correctly formatted by VSCode doesn't have this bug, meaning that: 1. The clang-format check in GH Actions fails. 2. We'd all have to stop using format-on-save in VSCode and accept the bug if we wanted those GH Actions tests to pass. Adding an empty line before variable assignments from multi-line function calls evades the buggy behavior. This commit should resolve the clang-format github action test failures, for now.
2022-03-10 20:55:13 -08:00
result = yr_arena_append(
arena,
compiler->rules_arena);
}
if (result == ERROR_SUCCESS) {
compiler->rules_arena = NULL;
Code cleanup: Refactor to clean up formatting issues Refactored the clamscan code that determines 'what to scan' in order to clean up some very messy logic and also to get around a difference in how vscode and clang-format handle formatting #ifdef blocks in the middle of an else/if. In addition to refactoring, there is a slight behavior improvement. With this change, doing `clamscan blah -` will now scan `blah` and then also scan `stdin`. You can even do `clamscan - blah` to now scan `stdin` and then scan `blah`. Before, The `-` had to be the only "filename" argument in order to scan from stdin. In addition, added a bunch of extra empty lines or changing multi-line function calls to single-line function calls in order to get around a bug in clang-format with these two options do not playing nice together: - AlignConsecutiveAssignments: true - AlignAfterOpenBracket: true AlignAfterOpenBracket is not taking account the spaces inserted by AlignConsecutiveAssignments, so you end up with stuff like this: ```c bleeblah = 1; blah = function(arg1, arg2, arg3); // ^--- these args 4-left from where they should be. ``` VSCode, meanwhile, somehow fixes this whitespace issue so code that is correctly formatted by VSCode doesn't have this bug, meaning that: 1. The clang-format check in GH Actions fails. 2. We'd all have to stop using format-on-save in VSCode and accept the bug if we wanted those GH Actions tests to pass. Adding an empty line before variable assignments from multi-line function calls evades the buggy behavior. This commit should resolve the clang-format github action test failures, for now.
2022-03-10 20:55:13 -08:00
result = yr_arena_append(
arena,
compiler->strings_arena);
}
if (result == ERROR_SUCCESS) {
compiler->strings_arena = NULL;
Code cleanup: Refactor to clean up formatting issues Refactored the clamscan code that determines 'what to scan' in order to clean up some very messy logic and also to get around a difference in how vscode and clang-format handle formatting #ifdef blocks in the middle of an else/if. In addition to refactoring, there is a slight behavior improvement. With this change, doing `clamscan blah -` will now scan `blah` and then also scan `stdin`. You can even do `clamscan - blah` to now scan `stdin` and then scan `blah`. Before, The `-` had to be the only "filename" argument in order to scan from stdin. In addition, added a bunch of extra empty lines or changing multi-line function calls to single-line function calls in order to get around a bug in clang-format with these two options do not playing nice together: - AlignConsecutiveAssignments: true - AlignAfterOpenBracket: true AlignAfterOpenBracket is not taking account the spaces inserted by AlignConsecutiveAssignments, so you end up with stuff like this: ```c bleeblah = 1; blah = function(arg1, arg2, arg3); // ^--- these args 4-left from where they should be. ``` VSCode, meanwhile, somehow fixes this whitespace issue so code that is correctly formatted by VSCode doesn't have this bug, meaning that: 1. The clang-format check in GH Actions fails. 2. We'd all have to stop using format-on-save in VSCode and accept the bug if we wanted those GH Actions tests to pass. Adding an empty line before variable assignments from multi-line function calls evades the buggy behavior. This commit should resolve the clang-format github action test failures, for now.
2022-03-10 20:55:13 -08:00
result = yr_arena_append(
arena,
compiler->externals_arena);
}
if (result == ERROR_SUCCESS) {
compiler->externals_arena = NULL;
Code cleanup: Refactor to clean up formatting issues Refactored the clamscan code that determines 'what to scan' in order to clean up some very messy logic and also to get around a difference in how vscode and clang-format handle formatting #ifdef blocks in the middle of an else/if. In addition to refactoring, there is a slight behavior improvement. With this change, doing `clamscan blah -` will now scan `blah` and then also scan `stdin`. You can even do `clamscan - blah` to now scan `stdin` and then scan `blah`. Before, The `-` had to be the only "filename" argument in order to scan from stdin. In addition, added a bunch of extra empty lines or changing multi-line function calls to single-line function calls in order to get around a bug in clang-format with these two options do not playing nice together: - AlignConsecutiveAssignments: true - AlignAfterOpenBracket: true AlignAfterOpenBracket is not taking account the spaces inserted by AlignConsecutiveAssignments, so you end up with stuff like this: ```c bleeblah = 1; blah = function(arg1, arg2, arg3); // ^--- these args 4-left from where they should be. ``` VSCode, meanwhile, somehow fixes this whitespace issue so code that is correctly formatted by VSCode doesn't have this bug, meaning that: 1. The clang-format check in GH Actions fails. 2. We'd all have to stop using format-on-save in VSCode and accept the bug if we wanted those GH Actions tests to pass. Adding an empty line before variable assignments from multi-line function calls evades the buggy behavior. This commit should resolve the clang-format github action test failures, for now.
2022-03-10 20:55:13 -08:00
result = yr_arena_append(
arena,
compiler->namespaces_arena);
}
if (result == ERROR_SUCCESS) {
compiler->namespaces_arena = NULL;
Code cleanup: Refactor to clean up formatting issues Refactored the clamscan code that determines 'what to scan' in order to clean up some very messy logic and also to get around a difference in how vscode and clang-format handle formatting #ifdef blocks in the middle of an else/if. In addition to refactoring, there is a slight behavior improvement. With this change, doing `clamscan blah -` will now scan `blah` and then also scan `stdin`. You can even do `clamscan - blah` to now scan `stdin` and then scan `blah`. Before, The `-` had to be the only "filename" argument in order to scan from stdin. In addition, added a bunch of extra empty lines or changing multi-line function calls to single-line function calls in order to get around a bug in clang-format with these two options do not playing nice together: - AlignConsecutiveAssignments: true - AlignAfterOpenBracket: true AlignAfterOpenBracket is not taking account the spaces inserted by AlignConsecutiveAssignments, so you end up with stuff like this: ```c bleeblah = 1; blah = function(arg1, arg2, arg3); // ^--- these args 4-left from where they should be. ``` VSCode, meanwhile, somehow fixes this whitespace issue so code that is correctly formatted by VSCode doesn't have this bug, meaning that: 1. The clang-format check in GH Actions fails. 2. We'd all have to stop using format-on-save in VSCode and accept the bug if we wanted those GH Actions tests to pass. Adding an empty line before variable assignments from multi-line function calls evades the buggy behavior. This commit should resolve the clang-format github action test failures, for now.
2022-03-10 20:55:13 -08:00
result = yr_arena_append(
arena,
compiler->metas_arena);
}
if (result == ERROR_SUCCESS) {
compiler->metas_arena = NULL;
Code cleanup: Refactor to clean up formatting issues Refactored the clamscan code that determines 'what to scan' in order to clean up some very messy logic and also to get around a difference in how vscode and clang-format handle formatting #ifdef blocks in the middle of an else/if. In addition to refactoring, there is a slight behavior improvement. With this change, doing `clamscan blah -` will now scan `blah` and then also scan `stdin`. You can even do `clamscan - blah` to now scan `stdin` and then scan `blah`. Before, The `-` had to be the only "filename" argument in order to scan from stdin. In addition, added a bunch of extra empty lines or changing multi-line function calls to single-line function calls in order to get around a bug in clang-format with these two options do not playing nice together: - AlignConsecutiveAssignments: true - AlignAfterOpenBracket: true AlignAfterOpenBracket is not taking account the spaces inserted by AlignConsecutiveAssignments, so you end up with stuff like this: ```c bleeblah = 1; blah = function(arg1, arg2, arg3); // ^--- these args 4-left from where they should be. ``` VSCode, meanwhile, somehow fixes this whitespace issue so code that is correctly formatted by VSCode doesn't have this bug, meaning that: 1. The clang-format check in GH Actions fails. 2. We'd all have to stop using format-on-save in VSCode and accept the bug if we wanted those GH Actions tests to pass. Adding an empty line before variable assignments from multi-line function calls evades the buggy behavior. This commit should resolve the clang-format github action test failures, for now.
2022-03-10 20:55:13 -08:00
result = yr_arena_append(
arena,
compiler->sz_arena);
}
if (result == ERROR_SUCCESS) {
compiler->sz_arena = NULL;
compiler->compiled_rules_arena = arena;
Code cleanup: Refactor to clean up formatting issues Refactored the clamscan code that determines 'what to scan' in order to clean up some very messy logic and also to get around a difference in how vscode and clang-format handle formatting #ifdef blocks in the middle of an else/if. In addition to refactoring, there is a slight behavior improvement. With this change, doing `clamscan blah -` will now scan `blah` and then also scan `stdin`. You can even do `clamscan - blah` to now scan `stdin` and then scan `blah`. Before, The `-` had to be the only "filename" argument in order to scan from stdin. In addition, added a bunch of extra empty lines or changing multi-line function calls to single-line function calls in order to get around a bug in clang-format with these two options do not playing nice together: - AlignConsecutiveAssignments: true - AlignAfterOpenBracket: true AlignAfterOpenBracket is not taking account the spaces inserted by AlignConsecutiveAssignments, so you end up with stuff like this: ```c bleeblah = 1; blah = function(arg1, arg2, arg3); // ^--- these args 4-left from where they should be. ``` VSCode, meanwhile, somehow fixes this whitespace issue so code that is correctly formatted by VSCode doesn't have this bug, meaning that: 1. The clang-format check in GH Actions fails. 2. We'd all have to stop using format-on-save in VSCode and accept the bug if we wanted those GH Actions tests to pass. Adding an empty line before variable assignments from multi-line function calls evades the buggy behavior. This commit should resolve the clang-format github action test failures, for now.
2022-03-10 20:55:13 -08:00
result = yr_arena_coalesce(arena);
}
return result;
}
2015-05-28 18:00:16 -04:00
int yr_compiler_get_rules(
YR_COMPILER* compiler,
YR_RULES** rules)
{
YR_RULES* yara_rules;
YARA_RULES_FILE_HEADER* rules_file_header;
2015-05-28 18:00:16 -04:00
*rules = NULL;
2015-05-28 18:00:16 -04:00
if (compiler->compiled_rules_arena == NULL)
FAIL_ON_ERROR(_yr_compiler_compile_rules(compiler));
2015-05-28 18:00:16 -04:00
yara_rules = yr_malloc(sizeof(YR_RULES));
2015-05-28 18:00:16 -04:00
if (yara_rules == NULL)
return ERROR_INSUFICIENT_MEMORY;
2015-05-28 18:00:16 -04:00
FAIL_ON_ERROR_WITH_CLEANUP(
yr_arena_duplicate(compiler->compiled_rules_arena, &yara_rules->arena),
yr_free(yara_rules));
2015-05-28 18:00:16 -04:00
rules_file_header = (YARA_RULES_FILE_HEADER*)yr_arena_base_address(
yara_rules->arena);
2015-05-28 18:00:16 -04:00
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;
2015-05-28 18:00:16 -04:00
#if _WIN32
yara_rules->mutex = CreateMutex(NULL, FALSE, NULL);
#else
pthread_mutex_init(&yara_rules->mutex, NULL);
#endif
2015-05-28 18:00:16 -04:00
*rules = yara_rules;
2015-05-28 18:00:16 -04:00
return ERROR_SUCCESS;
2015-05-28 18:00:16 -04:00
}
int yr_compiler_define_integer_variable(
YR_COMPILER* compiler,
const char* identifier,
int64_t value)
{
YR_EXTERNAL_VARIABLE* external;
YR_OBJECT* object;
2015-05-28 18:00:16 -04:00
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;
}
2015-05-28 18:00:16 -04:00
int yr_compiler_define_boolean_variable(
YR_COMPILER* compiler,
const char* identifier,
int value)
{
return yr_compiler_define_integer_variable(
compiler,
identifier,
value);
2015-05-28 18:00:16 -04:00
}
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;
2015-05-28 18:00:16 -04:00
}
#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,
2023-11-26 15:01:19 -08:00
"\"%s\" is not an 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;
2015-05-28 18:00:16 -04:00
}