Improve atom extraction.

This commit is contained in:
Victor M. Alvarez
2018-12-03 17:08:31 +01:00
21 changed files with 1825 additions and 696 deletions
+7 -4
View File
@@ -44,6 +44,8 @@ test_bitmask_SOURCES = tests/test-bitmask.c
test_bitmask_LDADD = libyara/.libs/libyara.a
test_math_SOURCES = tests/test-math.c tests/util.c
test_math_LDADD = libyara/.libs/libyara.a
test_stack_SOURCES = tests/test-stack.c
test_stack_LDADD = libyara/.libs/libyara.a
TESTS = $(check_PROGRAMS)
TESTS_ENVIRONMENT = TOP_SRCDIR=$(top_srcdir)
@@ -56,7 +58,8 @@ check_PROGRAMS = test-alignment \
test-elf \
test-version \
test-bitmask \
test-math
test-math \
test-stack
if POSIX
# The -fsanitize=address option makes test-exception fail. Include the test
@@ -64,20 +67,20 @@ if POSIX
if !ADDRESS_SANITIZER
check_PROGRAMS+=test-exception
test_exception_SOURCES = tests/test-exception.c tests/util.c
test_exception_LDADD = -Llibyara/.libs -lyara
test_exception_LDADD = libyara/.libs/libyara.a
endif
endif
if MACHO_MODULE
check_PROGRAMS+=test-macho
test_macho_SOURCES = tests/test-macho.c tests/util.c
test_macho_LDADD = -Llibyara/.libs -lyara
test_macho_LDADD = libyara/.libs/libyara.a
endif
if DEX_MODULE
check_PROGRAMS+=test-dex
test_dex_SOURCES = tests/test-dex.c tests/util.c
test_dex_LDADD = -Llibyara/.libs -lyara
test_dex_LDADD = libyara/.libs/libyara.a
endif
# man pages
+2
View File
@@ -89,6 +89,7 @@ yarainclude_HEADERS = \
include/yara/scan.h \
include/yara/scanner.h \
include/yara/sizedstr.h \
include/yara/stack.h \
include/yara/stopwatch.h \
include/yara/stream.h \
include/yara/strutils.h \
@@ -152,6 +153,7 @@ libyara_la_SOURCES = \
scan.c \
scanner.c \
sizedstr.c \
stack.c \
stopwatch.c \
strutils.c \
stream.c \
+5 -5
View File
@@ -503,7 +503,7 @@ static int _yr_ac_find_suitable_transition_table_slot(
automaton->bitmask = (YR_BITMASK*) yr_realloc(
automaton->bitmask, b_bytes_size * 2);
if (automaton->t_table == NULL ||
automaton->m_table == NULL ||
automaton->bitmask == NULL)
@@ -602,7 +602,7 @@ static int _yr_ac_build_transition_table(
automaton->bitmask = (YR_BITMASK*) yr_calloc(
YR_BITMASK_SIZE(automaton->tables_size), sizeof(YR_BITMASK));
if (automaton->t_table == NULL ||
if (automaton->t_table == NULL ||
automaton->m_table == NULL ||
automaton->bitmask == NULL)
{
@@ -848,13 +848,13 @@ int yr_ac_add_string(
{
state = automaton->root;
for (i = 0; i < atom->atom_length; i++)
for (i = 0; i < atom->atom.length; i++)
{
next_state = _yr_ac_next_state(state, atom->atom[i]);
next_state = _yr_ac_next_state(state, atom->atom.bytes[i]);
if (next_state == NULL)
{
next_state = _yr_ac_state_create(state, atom->atom[i]);
next_state = _yr_ac_state_create(state, atom->atom.bytes[i]);
if (next_state == NULL)
return ERROR_INSUFFICIENT_MEMORY;
+720 -559
View File
File diff suppressed because it is too large Load Diff
+10 -6
View File
@@ -486,7 +486,7 @@ static const yytype_uint16 yyrline[] =
{
0, 113, 113, 122, 126, 140, 208, 212, 230, 234,
243, 248, 247, 260, 283, 315, 337, 357, 361, 380,
388
389
};
#endif
@@ -1645,12 +1645,13 @@ yyreduce:
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
(yyval.re_node)->value = (int) (yyvsp[0].integer);
(yyval.re_node)->mask = 0xFF;
}
#line 1650 "hex_grammar.c" /* yacc.c:1663 */
#line 1651 "hex_grammar.c" /* yacc.c:1663 */
break;
case 20:
#line 389 "hex_grammar.y" /* yacc.c:1663 */
#line 390 "hex_grammar.y" /* yacc.c:1663 */
{
uint8_t mask = (uint8_t) ((yyvsp[0].integer) >> 8);
@@ -1659,6 +1660,9 @@ yyreduce:
(yyval.re_node) = yr_re_node_create(RE_NODE_ANY, NULL, NULL);
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
(yyval.re_node)->value = 0x00;
(yyval.re_node)->mask = 0x00;
}
else
{
@@ -1670,11 +1674,11 @@ yyreduce:
(yyval.re_node)->mask = mask;
}
}
#line 1674 "hex_grammar.c" /* yacc.c:1663 */
#line 1678 "hex_grammar.c" /* yacc.c:1663 */
break;
#line 1678 "hex_grammar.c" /* yacc.c:1663 */
#line 1682 "hex_grammar.c" /* yacc.c:1663 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -1902,4 +1906,4 @@ yyreturn:
#endif
return yyresult;
}
#line 410 "hex_grammar.y" /* yacc.c:1907 */
#line 414 "hex_grammar.y" /* yacc.c:1907 */
+4
View File
@@ -384,6 +384,7 @@ byte
fail_if($$ == NULL, ERROR_INSUFFICIENT_MEMORY);
$$->value = (int) $1;
$$->mask = 0xFF;
}
| _MASKED_BYTE_
{
@@ -394,6 +395,9 @@ byte
$$ = yr_re_node_create(RE_NODE_ANY, NULL, NULL);
fail_if($$ == NULL, ERROR_INSUFFICIENT_MEMORY);
$$->value = 0x00;
$$->mask = 0x00;
}
else
{
+28 -26
View File
@@ -37,9 +37,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define ATOM_TREE_AND 2
#define ATOM_TREE_OR 3
typedef struct ATOM_TREE_NODE ATOM_TREE_NODE;
typedef struct ATOM_TREE ATOM_TREE;
typedef struct YR_ATOM YR_ATOM;
typedef struct YR_ATOM_TREE_NODE YR_ATOM_TREE_NODE;
typedef struct YR_ATOM_TREE YR_ATOM_TREE;
typedef struct YR_ATOM_LIST_ITEM YR_ATOM_LIST_ITEM;
@@ -47,34 +47,37 @@ typedef struct YR_ATOM_QUALITY_TABLE_ENTRY YR_ATOM_QUALITY_TABLE_ENTRY;
typedef struct YR_ATOMS_CONFIG YR_ATOMS_CONFIG;
struct ATOM_TREE_NODE
struct YR_ATOM
{
uint8_t length;
uint8_t bytes[YR_MAX_ATOM_LENGTH];
uint8_t mask[YR_MAX_ATOM_LENGTH];
};
struct YR_ATOM_TREE_NODE
{
uint8_t type;
uint8_t atom_length;
uint8_t atom[YR_MAX_ATOM_LENGTH];
uint8_t* forward_code;
uint8_t* backward_code;
YR_ATOM atom;
RE_NODE* recent_nodes[YR_MAX_ATOM_LENGTH];
// RE nodes that correspond to each byte in the atom.
RE_NODE* re_nodes[YR_MAX_ATOM_LENGTH];
ATOM_TREE_NODE* children_head;
ATOM_TREE_NODE* children_tail;
ATOM_TREE_NODE* next_sibling;
YR_ATOM_TREE_NODE* children_head;
YR_ATOM_TREE_NODE* children_tail;
YR_ATOM_TREE_NODE* next_sibling;
};
struct ATOM_TREE
struct YR_ATOM_TREE
{
ATOM_TREE_NODE* current_leaf;
ATOM_TREE_NODE* root_node;
YR_ATOM_TREE_NODE* root_node;
};
struct YR_ATOM_LIST_ITEM
{
uint8_t atom_length;
uint8_t atom[YR_MAX_ATOM_LENGTH];
YR_ATOM atom;
uint16_t backtrack;
@@ -90,7 +93,7 @@ struct YR_ATOM_LIST_ITEM
struct YR_ATOM_QUALITY_TABLE_ENTRY
{
const uint8_t atom[YR_MAX_ATOM_LENGTH];
const uint8_t atom[YR_MAX_ATOM_LENGTH];
const uint8_t quality;
};
@@ -99,8 +102,7 @@ struct YR_ATOM_QUALITY_TABLE_ENTRY
typedef int (*YR_ATOMS_QUALITY_FUNC)(
YR_ATOMS_CONFIG* config,
uint8_t* atom,
int atom_length);
YR_ATOM* atom);
struct YR_ATOMS_CONFIG
@@ -118,7 +120,8 @@ int yr_atoms_extract_from_re(
YR_ATOMS_CONFIG* config,
RE_AST* re_ast,
int flags,
YR_ATOM_LIST_ITEM** atoms);
YR_ATOM_LIST_ITEM** atoms,
int* min_atom_quality);
int yr_atoms_extract_from_string(
@@ -126,7 +129,8 @@ int yr_atoms_extract_from_string(
uint8_t* string,
int string_length,
int flags,
YR_ATOM_LIST_ITEM** atoms);
YR_ATOM_LIST_ITEM** atoms,
int* min_atom_quality);
int yr_atoms_extract_triplets(
@@ -136,14 +140,12 @@ int yr_atoms_extract_triplets(
int yr_atoms_heuristic_quality(
YR_ATOMS_CONFIG* config,
uint8_t* atom,
int atom_length);
YR_ATOM* atom);
int yr_atoms_table_quality(
YR_ATOMS_CONFIG* config,
uint8_t* atom,
int atom_length);
YR_ATOM* atom);
int yr_atoms_min_quality(
+6 -4
View File
@@ -102,6 +102,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define ERROR_INVALID_MODULE_DATA 57
#define ERROR_WRITING_FILE 58
#define FAIL_ON_ERROR(x) { \
int result = (x); \
if (result != ERROR_SUCCESS) \
@@ -116,10 +117,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
} \
}
#define FAIL_ON_COMPILER_ERROR(x) { \
compiler->last_error = (x); \
if (compiler->last_error != ERROR_SUCCESS) \
return compiler->last_error; \
#define FAIL_ON_NULL_WITH_CLEANUP(x, cleanup) { \
if ((x) == NULL) { \
cleanup; \
return ERROR_INSUFFICIENT_MEMORY; \
} \
}
+8 -4
View File
@@ -72,14 +72,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif
// If the minimum atom quality for a string or regexp is below this constant,
// a warning like "<string> is slowing down the scan" is shown. This used only
// with heuristic atom quality, when using an atom quality table the user must
// specify the threshold when calling yr_compiler_set_atom_quality_table
// a warning like "<string> is slowing down the scan" is shown. This is used
// only with heuristic atom quality, when using an atom quality table the user
// must specify the threshold when calling yr_compiler_set_atom_quality_table.
#ifndef YR_ATOM_QUALITY_WARNING_THRESHOLD
#define YR_ATOM_QUALITY_WARNING_THRESHOLD \
(YR_MAX_ATOM_QUALITY - 2 * YR_MAX_ATOM_LENGTH + 3)
YR_MAX_ATOM_QUALITY - 20 * YR_MAX_ATOM_LENGTH + 38
#endif
// If a rule generates more than this number of atoms a warning is shown.
#ifndef YR_ATOMS_PER_RULE_WARNING_THRESHOLD
#define YR_ATOMS_PER_RULE_WARNING_THRESHOLD 10000
#endif
// Maximum number of nested "for" loops in rule. Rules ith nested loops
// exceeding this number will be rejected by the compiler.
+72
View File
@@ -0,0 +1,72 @@
/*
Copyright (c) 2018. The YARA Authors. All Rights Reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef YR_STACK_H
#define YR_STACK_H
typedef struct YR_STACK YR_STACK;
struct YR_STACK
{
// Pointer to a heap-allocated array containing the void* values put in
// in the stack. This array starts with a fixed size and it's grown as
// required when new items are pushed into the stack.
void* items;
// Current capacity (i.e: the number of items that fit into the array)
int capacity;
// Size of each individual item in the stack.
int item_size;
// Index of the stack's top in the items array.
int top;
};
int yr_stack_create(
int initial_capacity,
int item_size,
YR_STACK** stack);
void yr_stack_destroy(
YR_STACK* stack);
int yr_stack_push(
YR_STACK* stack,
void* item);
int yr_stack_pop(
YR_STACK* stack,
void* item);
#endif
+51 -18
View File
@@ -295,12 +295,14 @@ static int _yr_parser_write_string(
SIZED_STRING* str,
RE_AST* re_ast,
YR_STRING** string,
int* min_atom_quality)
int* min_atom_quality,
int* num_atom)
{
SIZED_STRING* literal_string;
YR_ATOM_LIST_ITEM* atom;
YR_ATOM_LIST_ITEM* atom_list = NULL;
int result;
int c, result;
int max_string_len;
bool free_literal = false;
@@ -381,7 +383,8 @@ static int _yr_parser_write_string(
(uint8_t*) literal_string->c_string,
(int32_t) literal_string->length,
flags,
&atom_list);
&atom_list,
min_atom_quality);
}
}
else
@@ -395,7 +398,11 @@ static int _yr_parser_write_string(
if (result == ERROR_SUCCESS)
result = yr_atoms_extract_from_re(
&compiler->atoms_config, re_ast, flags, &atom_list);
&compiler->atoms_config,
re_ast,
flags,
&atom_list,
min_atom_quality);
}
if (result == ERROR_SUCCESS)
@@ -408,9 +415,6 @@ static int _yr_parser_write_string(
compiler->matches_arena);
}
*min_atom_quality = yr_atoms_min_quality(
&compiler->atoms_config, atom_list);
if (flags & STRING_GFLAGS_LITERAL)
{
if (flags & STRING_GFLAGS_WIDE)
@@ -422,6 +426,17 @@ static int _yr_parser_write_string(
(*string)->g_flags |= STRING_GFLAGS_FITS_IN_ATOM;
}
atom = atom_list;
c = 0;
while (atom != NULL)
{
atom = atom->next;
c++;
}
(*num_atom) += c;
if (free_literal)
yr_free(literal_string);
@@ -443,8 +458,8 @@ int yr_parser_reduce_string_declaration(
SIZED_STRING* str,
YR_STRING** string)
{
int min_atom_quality;
int min_atom_quality_aux;
int min_atom_quality = YR_MIN_ATOM_QUALITY;
int min_atom_quality_aux = YR_MIN_ATOM_QUALITY;
int32_t min_gap;
int32_t max_gap;
@@ -599,7 +614,8 @@ int yr_parser_reduce_string_declaration(
NULL,
re_ast,
string,
&min_atom_quality);
&min_atom_quality,
&compiler->current_rule->num_atoms);
if (result != ERROR_SUCCESS)
goto _exit;
@@ -638,7 +654,8 @@ int yr_parser_reduce_string_declaration(
NULL,
re_ast,
&aux_string,
&min_atom_quality_aux);
&min_atom_quality_aux,
&compiler->current_rule->num_atoms);
if (result != ERROR_SUCCESS)
goto _exit;
@@ -668,7 +685,8 @@ int yr_parser_reduce_string_declaration(
str,
NULL,
string,
&min_atom_quality);
&min_atom_quality,
&compiler->current_rule->num_atoms);
if (result != ERROR_SUCCESS)
goto _exit;
@@ -690,8 +708,9 @@ int yr_parser_reduce_string_declaration(
{
yywarning(
yyscanner,
"%s is slowing down scanning",
(*string)->identifier);
"%s in rule %s is slowing down scanning",
(*string)->identifier,
compiler->current_rule->identifier);
}
_exit:
@@ -747,6 +766,7 @@ int yr_parser_reduce_rule_declaration_phase_1(
(*rule)->g_flags = flags;
(*rule)->ns = compiler->current_namespace;
(*rule)->num_atoms = 0;
#ifdef PROFILING_ENABLED
(*rule)->time_cost = 0;
@@ -818,14 +838,27 @@ int yr_parser_reduce_rule_declaration_phase_2(
YR_FIXUP *fixup;
YR_COMPILER* compiler = yyget_extra(yyscanner);
// Check for unreferenced (unused) strings.
YR_STRING* string = rule->strings;
yr_get_configuration(
YR_CONFIG_MAX_STRINGS_PER_RULE,
(void*) &max_strings_per_rule);
// Show warning if the rule is generating too many atoms. The warning is
// shown if the number of atoms is greater than 20 times the maximum number
// of strings allowed for a rule, as 20 is minimum number of atoms generated
// for a string using *nocase*, *ascii* and *wide* modifiers simultaneosly.
if (rule->num_atoms > YR_ATOMS_PER_RULE_WARNING_THRESHOLD)
{
yywarning(
yyscanner,
"rule %s is slowing down scanning",
rule->identifier);
}
// Check for unreferenced (unused) strings.
YR_STRING* string = rule->strings;
while (!STRING_IS_NULL(string))
{
// Only the heading fragment in a chain of strings (the one with
+25 -21
View File
@@ -501,8 +501,8 @@ static const yytype_uint16 yyrline[] =
{
0, 112, 112, 117, 121, 125, 141, 163, 167, 184,
198, 214, 228, 244, 266, 289, 311, 334, 338, 344,
350, 356, 365, 373, 379, 387, 393, 399, 405, 411,
417, 423
350, 356, 365, 373, 382, 391, 397, 403, 409, 415,
421, 427
};
#endif
@@ -1672,85 +1672,89 @@ yyreduce:
{
(yyval.re_node) = yr_re_node_create(RE_NODE_ANY, NULL, NULL);
(yyval.re_node)->value = 0x00;
(yyval.re_node)->mask = 0x00;
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1678 "re_grammar.c" /* yacc.c:1663 */
#line 1681 "re_grammar.c" /* yacc.c:1663 */
break;
case 24:
#line 380 "re_grammar.y" /* yacc.c:1663 */
#line 383 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_LITERAL, NULL, NULL);
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
(yyval.re_node)->value = (yyvsp[0].integer);
(yyval.re_node)->mask = 0xFF;
}
#line 1690 "re_grammar.c" /* yacc.c:1663 */
#line 1694 "re_grammar.c" /* yacc.c:1663 */
break;
case 25:
#line 388 "re_grammar.y" /* yacc.c:1663 */
#line 392 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_WORD_CHAR, NULL, NULL);
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1700 "re_grammar.c" /* yacc.c:1663 */
#line 1704 "re_grammar.c" /* yacc.c:1663 */
break;
case 26:
#line 394 "re_grammar.y" /* yacc.c:1663 */
#line 398 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_NON_WORD_CHAR, NULL, NULL);
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1710 "re_grammar.c" /* yacc.c:1663 */
#line 1714 "re_grammar.c" /* yacc.c:1663 */
break;
case 27:
#line 400 "re_grammar.y" /* yacc.c:1663 */
#line 404 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_SPACE, NULL, NULL);
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1720 "re_grammar.c" /* yacc.c:1663 */
#line 1724 "re_grammar.c" /* yacc.c:1663 */
break;
case 28:
#line 406 "re_grammar.y" /* yacc.c:1663 */
#line 410 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_NON_SPACE, NULL, NULL);
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1730 "re_grammar.c" /* yacc.c:1663 */
#line 1734 "re_grammar.c" /* yacc.c:1663 */
break;
case 29:
#line 412 "re_grammar.y" /* yacc.c:1663 */
#line 416 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_DIGIT, NULL, NULL);
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1740 "re_grammar.c" /* yacc.c:1663 */
#line 1744 "re_grammar.c" /* yacc.c:1663 */
break;
case 30:
#line 418 "re_grammar.y" /* yacc.c:1663 */
#line 422 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_NON_DIGIT, NULL, NULL);
fail_if((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY);
}
#line 1750 "re_grammar.c" /* yacc.c:1663 */
#line 1754 "re_grammar.c" /* yacc.c:1663 */
break;
case 31:
#line 424 "re_grammar.y" /* yacc.c:1663 */
#line 428 "re_grammar.y" /* yacc.c:1663 */
{
(yyval.re_node) = yr_re_node_create(RE_NODE_CLASS, NULL, NULL);
@@ -1758,11 +1762,11 @@ yyreduce:
(yyval.re_node)->re_class = (yyvsp[0].re_class);
}
#line 1762 "re_grammar.c" /* yacc.c:1663 */
#line 1766 "re_grammar.c" /* yacc.c:1663 */
break;
#line 1766 "re_grammar.c" /* yacc.c:1663 */
#line 1770 "re_grammar.c" /* yacc.c:1663 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -1990,5 +1994,5 @@ yyreturn:
#endif
return yyresult;
}
#line 432 "re_grammar.y" /* yacc.c:1907 */
#line 436 "re_grammar.y" /* yacc.c:1907 */
+4
View File
@@ -374,6 +374,9 @@ single
{
$$ = yr_re_node_create(RE_NODE_ANY, NULL, NULL);
$$->value = 0x00;
$$->mask = 0x00;
fail_if($$ == NULL, ERROR_INSUFFICIENT_MEMORY);
}
| _CHAR_
@@ -383,6 +386,7 @@ single
fail_if($$ == NULL, ERROR_INSUFFICIENT_MEMORY);
$$->value = $1;
$$->mask = 0xFF;
}
| _WORD_CHAR_
{
+145
View File
@@ -0,0 +1,145 @@
/*
Copyright (c) 2018. The YARA Authors. All Rights Reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <yara/integers.h>
#include <yara/stack.h>
#include <yara/mem.h>
#include <yara/error.h>
//
// yr_stack_create
//
// Creates a stack for items of the size specified by item_size. All items
// in the stack must have the same size. The stack will have an initial
// capacity as specified by initial_capacity and will grow as required when
// more objects are pushed.
//
int yr_stack_create(
int initial_capacity,
int item_size,
YR_STACK** stack)
{
*stack = (YR_STACK*) yr_malloc(sizeof(YR_STACK));
if (*stack == NULL)
return ERROR_INSUFFICIENT_MEMORY;
(*stack)->items = yr_malloc(initial_capacity * item_size);
if ((*stack)->items == NULL)
{
yr_free(*stack);
*stack = NULL;
return ERROR_INSUFFICIENT_MEMORY;
}
(*stack)->capacity = initial_capacity;
(*stack)->item_size = item_size;
(*stack)->top = 0;
return ERROR_SUCCESS;
}
//
// yr_stack_destroy
//
// Destroys a stack and deallocates all its resources.
//
void yr_stack_destroy(
YR_STACK* stack)
{
yr_free(stack->items);
yr_free(stack);
}
//
// yr_stack_push
//
// Pushes an item into the stack. If the stack has reached its capacity the
// funtion tries to double the capacity. This operation can fail with
// ERROR_INSUFFICIENT_MEMORY.
//
int yr_stack_push(
YR_STACK* stack,
void* item)
{
if (stack->top == stack->capacity)
{
void* items = yr_realloc(
stack->items, 2 * stack->capacity * stack->item_size);
if (items == NULL)
return ERROR_INSUFFICIENT_MEMORY;
stack->items = items;
stack->capacity *= 2;
}
memcpy(
(uint8_t*) stack->items + stack->top * stack->item_size,
item,
stack->item_size);
stack->top++;
return ERROR_SUCCESS;
}
//
// yr_stack_pop
//
// Pops an item from the stack. The caller must pass pointer to a buffer
// where the function will copy the item. The buffer must have enough space
// to hold the item. Returns 1 if an item could be poped and 0 if the stack
// was already empty.
//
int yr_stack_pop(
YR_STACK* stack,
void* item)
{
if (stack->top == 0) // Return 0 if stack is empty.
return 0;
stack->top--;
memcpy(
item,
(uint8_t*) stack->items + stack->top * stack->item_size,
stack->item_size);
return 1;
}
+14 -14
View File
@@ -654,12 +654,12 @@ void test_rules_stats()
stats_for_rules("\
rule test { \
strings: \
$ = \"abcd0\" \
$ = \"abcd1\" \
$ = \"abcd2\" \
$ = \"efgh0\" \
$ = \"efgh1\" \
$ = \"efgh2\" \
$ = \"00000\" \
$ = \"00001\" \
$ = \"00002\" \
$ = \"11110\" \
$ = \"11111\" \
$ = \"11112\" \
condition: all of them }",
&stats);
@@ -674,14 +674,14 @@ void test_rules_stats()
stats_for_rules("\
rule test { \
strings: \
$ = \"abcd0\" \
$ = \"abcd1\" \
$ = \"abcd2\" \
$ = \"efgh0\" \
$ = \"ijkl0\" \
$ = \"mnop0\" \
$ = \"mnop1\" \
$ = \"qrst0\" \
$ = \"00000\" \
$ = \"00001\" \
$ = \"00002\" \
$ = \"11110\" \
$ = \"22220\" \
$ = \"33330\" \
$ = \"33331\" \
$ = \"44440\" \
condition: all of them }",
&stats);
+513 -25
View File
@@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "util.h"
void test_quality_quality()
void test_table_quality()
{
YR_ATOM_QUALITY_TABLE_ENTRY l1[] = {
{{0x00, 0x00, 0x00, 0x00}, 1},
@@ -46,10 +46,15 @@ void test_quality_quality()
{{0x00, 0x00, 0x00, 0x03}, 4},
};
uint8_t a0[] = {0x00, 0x00, 0x00, 0x00};
uint8_t a1[] = {0x00, 0x00, 0x00, 0x01};
uint8_t a2[] = {0x00, 0x00, 0x00, 0x02};
uint8_t a3[] = {0x00, 0x00, 0x00, 0x03};
YR_ATOM a0 = {
.length = 4,
.bytes = {0x00, 0x00, 0x00, 0x00},
.mask = {0xFF, 0xFF, 0xFF, 0xFF}};
YR_ATOM a1 = {4, {0x00, 0x00, 0x00, 0x01}, {0xFF, 0xFF, 0xFF, 0xFF}};
YR_ATOM a2 = {4, {0x00, 0x00, 0x00, 0x02}, {0xFF, 0xFF, 0xFF, 0xFF}};
YR_ATOM a3 = {4, {0x00, 0x00, 0x00, 0x03}, {0xFF, 0xFF, 0xFF, 0xFF}};
YR_ATOM a4 = {4, {0x00, 0x00, 0x00, 0x00}, {0xFF, 0xFF, 0xFF, 0x00}};
YR_ATOMS_CONFIG c;
@@ -57,36 +62,519 @@ void test_quality_quality()
c.quality_table = l1;
c.quality_table_entries = 3;
assert_true_expr(
yr_atoms_table_quality(&c, a0, sizeof(a0)) == 1);
assert_true_expr(
yr_atoms_table_quality(&c, a1, sizeof(a1)) == 2);
assert_true_expr(
yr_atoms_table_quality(&c, a2, sizeof(a2)) == 3);
assert_true_expr(
yr_atoms_table_quality(&c, a3, sizeof(3)) == YR_MAX_ATOM_QUALITY);
assert_true_expr(yr_atoms_table_quality(&c, &a0) == 1);
assert_true_expr(yr_atoms_table_quality(&c, &a1) == 2);
assert_true_expr(yr_atoms_table_quality(&c, &a2) == 3);
assert_true_expr(yr_atoms_table_quality(&c, &a3) == YR_MAX_ATOM_QUALITY);
c.quality_table = l2;
c.quality_table_entries = 4;
assert_true_expr(
yr_atoms_table_quality(&c, a0, sizeof(a0)) == 1);
assert_true_expr(yr_atoms_table_quality(&c, &a0) == 1);
assert_true_expr(yr_atoms_table_quality(&c, &a1) == 2);
assert_true_expr(yr_atoms_table_quality(&c, &a2) == 3);
assert_true_expr(yr_atoms_table_quality(&c, &a3) == 4);
assert_true_expr(yr_atoms_table_quality(&c, &a4) == 1);
}
assert_true_expr(
yr_atoms_table_quality(&c, a1, sizeof(a1)) == 2);
assert_true_expr(
yr_atoms_table_quality(&c, a2, sizeof(a2)) == 3);
void test_heuristic_quality()
{
YR_ATOMS_CONFIG c;
assert_true_expr(
yr_atoms_table_quality(&c, a3, sizeof(a3)) == 4);
YR_ATOM a00000000 = {
.length = 4,
.bytes = {0x00, 0x00, 0x00, 0x00},
.mask = {0xFF, 0xFF, 0xFF, 0xFF}};
YR_ATOM a00000001 = {
.length = 4,
.bytes = {0x00, 0x00, 0x00, 0x01},
.mask = {0xFF, 0xFF, 0xFF, 0xFF}};
YR_ATOM a00000102 = {
.length = 4,
.bytes = {0x00, 0x00, 0x01, 0x02},
.mask = {0xFF, 0xFF, 0xFF, 0xFF}};
YR_ATOM a00010203 = {
.length = 4,
.bytes = {0x00, 0x01, 0x02, 0x03},
.mask = {0xFF, 0xFF, 0xFF, 0xFF}};
YR_ATOM a01020304 = {
.length = 4,
.bytes = {0x01, 0x02, 0x03, 0x04},
.mask = {0xFF, 0xFF, 0xFF, 0xFF}};
YR_ATOM a01 = {
.length = 1,
.bytes = {0x01},
.mask = {0xFF}};
YR_ATOM a0001 = {
.length = 2,
.bytes = {0x00, 0x01},
.mask = {0xFF, 0xFF}};
YR_ATOM a000001 = {
.length = 3,
.bytes = {0x00, 0x00, 0x01},
.mask = {0xFF, 0xFF, 0xFF}};
YR_ATOM a000102 = {
.length = 3,
.bytes = {0x00, 0x01, 0x02},
.mask = {0xFF, 0xFF, 0xFF}};
YR_ATOM a010203 = {
.length = 3,
.bytes = {0x01, 0x02, 0x03},
.mask = {0xFF, 0xFF, 0xFF}};
YR_ATOM a0102 = {
.length = 2,
.bytes = {0x01, 0x02},
.mask = {0xFF, 0xFF}};
YR_ATOM a01020000 = {
.length = 4,
.bytes = {0x01, 0x02, 0x00, 0x00},
.mask = {0xFF, 0xFF, 0xFF, 0xFF}};
YR_ATOM a0102XX04 = {
.length = 4,
.bytes = {0x01, 0x02, 0x03, 0x04},
.mask = {0xFF, 0xFF, 0x00, 0xFF}};
c.get_atom_quality = yr_atoms_heuristic_quality;
int q00000000 = yr_atoms_heuristic_quality(&c, &a00000000);
int q00000001 = yr_atoms_heuristic_quality(&c, &a00000001);
int q00000102 = yr_atoms_heuristic_quality(&c, &a00000102);
int q00010203 = yr_atoms_heuristic_quality(&c, &a00010203);
int q01020304 = yr_atoms_heuristic_quality(&c, &a01020304);
int q010203 = yr_atoms_heuristic_quality(&c, &a010203);
int q0102 = yr_atoms_heuristic_quality(&c, &a0102);
int q01 = yr_atoms_heuristic_quality(&c, &a01);
int q0001 = yr_atoms_heuristic_quality(&c, &a0001);
int q000001 = yr_atoms_heuristic_quality(&c, &a000001);
int q000102 = yr_atoms_heuristic_quality(&c, &a000102);
int q01020000 = yr_atoms_heuristic_quality(&c, &a01020000);
int q0102XX04 = yr_atoms_heuristic_quality(&c, &a0102XX04);
a010203.mask[1] = 0x00;
int q01XX03 = yr_atoms_heuristic_quality(&c, &a010203);
a010203.mask[1] = 0x0F;
int q01X203 = yr_atoms_heuristic_quality(&c, &a010203);
a010203.mask[1] = 0x0F;
int q010X03 = yr_atoms_heuristic_quality(&c, &a010203);
a010203.mask[2] = 0x0F;
int q010X0X = yr_atoms_heuristic_quality(&c, &a010203);
assert_true_expr(q00000001 > q00000000);
assert_true_expr(q00000001 > q000001);
assert_true_expr(q000001 > q0001);
assert_true_expr(q00000102 > q00000001);
assert_true_expr(q00010203 > q00000102);
assert_true_expr(q01020304 > q00010203);
assert_true_expr(q000102 > q000001);
assert_true_expr(q00010203 > q010203);
assert_true_expr(q010203 > q0102);
assert_true_expr(q0102 > q01);
assert_true_expr(q01X203 > q0102);
assert_true_expr(q01X203 > q0001);
assert_true_expr(q01X203 < q010203);
assert_true_expr(q01X203 == q010X03);
assert_true_expr(q01XX03 <= q0102);
assert_true_expr(q01XX03 < q010X03);
assert_true_expr(q01XX03 < q010203);
assert_true_expr(q010X0X > q01);
assert_true_expr(q010X0X < q010203);
assert_true_expr(q01020000 > q0102XX04);
assert_true_expr(q01020304 == YR_MAX_ATOM_QUALITY);
}
void test_atom_choose()
{
struct atom atoms_61_XX_63_64[] = {
{4, {0x61, 0x00, 0x63, 0x64}},
{4, {0x61, 0x01, 0x63, 0x64}},
{4, {0x61, 0x02, 0x63, 0x64}},
{4, {0x61, 0x03, 0x63, 0x64}},
{4, {0x61, 0x04, 0x63, 0x64}},
{4, {0x61, 0x05, 0x63, 0x64}},
{4, {0x61, 0x06, 0x63, 0x64}},
{4, {0x61, 0x07, 0x63, 0x64}},
{4, {0x61, 0x08, 0x63, 0x64}},
{4, {0x61, 0x09, 0x63, 0x64}},
{4, {0x61, 0x0A, 0x63, 0x64}},
{4, {0x61, 0x0B, 0x63, 0x64}},
{4, {0x61, 0x0C, 0x63, 0x64}},
{4, {0x61, 0x0D, 0x63, 0x64}},
{4, {0x61, 0x0E, 0x63, 0x64}},
{4, {0x61, 0x0F, 0x63, 0x64}},
{4, {0x61, 0x10, 0x63, 0x64}},
{4, {0x61, 0x11, 0x63, 0x64}},
{4, {0x61, 0x12, 0x63, 0x64}},
{4, {0x61, 0x13, 0x63, 0x64}},
{4, {0x61, 0x14, 0x63, 0x64}},
{4, {0x61, 0x15, 0x63, 0x64}},
{4, {0x61, 0x16, 0x63, 0x64}},
{4, {0x61, 0x17, 0x63, 0x64}},
{4, {0x61, 0x18, 0x63, 0x64}},
{4, {0x61, 0x19, 0x63, 0x64}},
{4, {0x61, 0x1A, 0x63, 0x64}},
{4, {0x61, 0x1B, 0x63, 0x64}},
{4, {0x61, 0x1C, 0x63, 0x64}},
{4, {0x61, 0x1D, 0x63, 0x64}},
{4, {0x61, 0x1E, 0x63, 0x64}},
{4, {0x61, 0x1F, 0x63, 0x64}},
{4, {0x61, 0x20, 0x63, 0x64}},
{4, {0x61, 0x21, 0x63, 0x64}},
{4, {0x61, 0x22, 0x63, 0x64}},
{4, {0x61, 0x23, 0x63, 0x64}},
{4, {0x61, 0x24, 0x63, 0x64}},
{4, {0x61, 0x25, 0x63, 0x64}},
{4, {0x61, 0x26, 0x63, 0x64}},
{4, {0x61, 0x27, 0x63, 0x64}},
{4, {0x61, 0x28, 0x63, 0x64}},
{4, {0x61, 0x29, 0x63, 0x64}},
{4, {0x61, 0x2A, 0x63, 0x64}},
{4, {0x61, 0x2B, 0x63, 0x64}},
{4, {0x61, 0x2C, 0x63, 0x64}},
{4, {0x61, 0x2D, 0x63, 0x64}},
{4, {0x61, 0x2E, 0x63, 0x64}},
{4, {0x61, 0x2F, 0x63, 0x64}},
{4, {0x61, 0x30, 0x63, 0x64}},
{4, {0x61, 0x31, 0x63, 0x64}},
{4, {0x61, 0x32, 0x63, 0x64}},
{4, {0x61, 0x33, 0x63, 0x64}},
{4, {0x61, 0x34, 0x63, 0x64}},
{4, {0x61, 0x35, 0x63, 0x64}},
{4, {0x61, 0x36, 0x63, 0x64}},
{4, {0x61, 0x37, 0x63, 0x64}},
{4, {0x61, 0x38, 0x63, 0x64}},
{4, {0x61, 0x39, 0x63, 0x64}},
{4, {0x61, 0x3A, 0x63, 0x64}},
{4, {0x61, 0x3B, 0x63, 0x64}},
{4, {0x61, 0x3C, 0x63, 0x64}},
{4, {0x61, 0x3D, 0x63, 0x64}},
{4, {0x61, 0x3E, 0x63, 0x64}},
{4, {0x61, 0x3F, 0x63, 0x64}},
{4, {0x61, 0x40, 0x63, 0x64}},
{4, {0x61, 0x41, 0x63, 0x64}},
{4, {0x61, 0x42, 0x63, 0x64}},
{4, {0x61, 0x43, 0x63, 0x64}},
{4, {0x61, 0x44, 0x63, 0x64}},
{4, {0x61, 0x45, 0x63, 0x64}},
{4, {0x61, 0x46, 0x63, 0x64}},
{4, {0x61, 0x47, 0x63, 0x64}},
{4, {0x61, 0x48, 0x63, 0x64}},
{4, {0x61, 0x49, 0x63, 0x64}},
{4, {0x61, 0x4A, 0x63, 0x64}},
{4, {0x61, 0x4B, 0x63, 0x64}},
{4, {0x61, 0x4C, 0x63, 0x64}},
{4, {0x61, 0x4D, 0x63, 0x64}},
{4, {0x61, 0x4E, 0x63, 0x64}},
{4, {0x61, 0x4F, 0x63, 0x64}},
{4, {0x61, 0x50, 0x63, 0x64}},
{4, {0x61, 0x51, 0x63, 0x64}},
{4, {0x61, 0x52, 0x63, 0x64}},
{4, {0x61, 0x53, 0x63, 0x64}},
{4, {0x61, 0x54, 0x63, 0x64}},
{4, {0x61, 0x55, 0x63, 0x64}},
{4, {0x61, 0x56, 0x63, 0x64}},
{4, {0x61, 0x57, 0x63, 0x64}},
{4, {0x61, 0x58, 0x63, 0x64}},
{4, {0x61, 0x59, 0x63, 0x64}},
{4, {0x61, 0x5A, 0x63, 0x64}},
{4, {0x61, 0x5B, 0x63, 0x64}},
{4, {0x61, 0x5C, 0x63, 0x64}},
{4, {0x61, 0x5D, 0x63, 0x64}},
{4, {0x61, 0x5E, 0x63, 0x64}},
{4, {0x61, 0x5F, 0x63, 0x64}},
{4, {0x61, 0x60, 0x63, 0x64}},
{4, {0x61, 0x61, 0x63, 0x64}},
{4, {0x61, 0x62, 0x63, 0x64}},
{4, {0x61, 0x63, 0x63, 0x64}},
{4, {0x61, 0x64, 0x63, 0x64}},
{4, {0x61, 0x65, 0x63, 0x64}},
{4, {0x61, 0x66, 0x63, 0x64}},
{4, {0x61, 0x67, 0x63, 0x64}},
{4, {0x61, 0x68, 0x63, 0x64}},
{4, {0x61, 0x69, 0x63, 0x64}},
{4, {0x61, 0x6A, 0x63, 0x64}},
{4, {0x61, 0x6B, 0x63, 0x64}},
{4, {0x61, 0x6C, 0x63, 0x64}},
{4, {0x61, 0x6D, 0x63, 0x64}},
{4, {0x61, 0x6E, 0x63, 0x64}},
{4, {0x61, 0x6F, 0x63, 0x64}},
{4, {0x61, 0x70, 0x63, 0x64}},
{4, {0x61, 0x71, 0x63, 0x64}},
{4, {0x61, 0x72, 0x63, 0x64}},
{4, {0x61, 0x73, 0x63, 0x64}},
{4, {0x61, 0x74, 0x63, 0x64}},
{4, {0x61, 0x75, 0x63, 0x64}},
{4, {0x61, 0x76, 0x63, 0x64}},
{4, {0x61, 0x77, 0x63, 0x64}},
{4, {0x61, 0x78, 0x63, 0x64}},
{4, {0x61, 0x79, 0x63, 0x64}},
{4, {0x61, 0x7A, 0x63, 0x64}},
{4, {0x61, 0x7B, 0x63, 0x64}},
{4, {0x61, 0x7C, 0x63, 0x64}},
{4, {0x61, 0x7D, 0x63, 0x64}},
{4, {0x61, 0x7E, 0x63, 0x64}},
{4, {0x61, 0x7F, 0x63, 0x64}},
{4, {0x61, 0x80, 0x63, 0x64}},
{4, {0x61, 0x81, 0x63, 0x64}},
{4, {0x61, 0x82, 0x63, 0x64}},
{4, {0x61, 0x83, 0x63, 0x64}},
{4, {0x61, 0x84, 0x63, 0x64}},
{4, {0x61, 0x85, 0x63, 0x64}},
{4, {0x61, 0x86, 0x63, 0x64}},
{4, {0x61, 0x87, 0x63, 0x64}},
{4, {0x61, 0x88, 0x63, 0x64}},
{4, {0x61, 0x89, 0x63, 0x64}},
{4, {0x61, 0x8A, 0x63, 0x64}},
{4, {0x61, 0x8B, 0x63, 0x64}},
{4, {0x61, 0x8C, 0x63, 0x64}},
{4, {0x61, 0x8D, 0x63, 0x64}},
{4, {0x61, 0x8E, 0x63, 0x64}},
{4, {0x61, 0x8F, 0x63, 0x64}},
{4, {0x61, 0x90, 0x63, 0x64}},
{4, {0x61, 0x91, 0x63, 0x64}},
{4, {0x61, 0x92, 0x63, 0x64}},
{4, {0x61, 0x93, 0x63, 0x64}},
{4, {0x61, 0x94, 0x63, 0x64}},
{4, {0x61, 0x95, 0x63, 0x64}},
{4, {0x61, 0x96, 0x63, 0x64}},
{4, {0x61, 0x97, 0x63, 0x64}},
{4, {0x61, 0x98, 0x63, 0x64}},
{4, {0x61, 0x99, 0x63, 0x64}},
{4, {0x61, 0x9A, 0x63, 0x64}},
{4, {0x61, 0x9B, 0x63, 0x64}},
{4, {0x61, 0x9C, 0x63, 0x64}},
{4, {0x61, 0x9D, 0x63, 0x64}},
{4, {0x61, 0x9E, 0x63, 0x64}},
{4, {0x61, 0x9F, 0x63, 0x64}},
{4, {0x61, 0xA0, 0x63, 0x64}},
{4, {0x61, 0xA1, 0x63, 0x64}},
{4, {0x61, 0xA2, 0x63, 0x64}},
{4, {0x61, 0xA3, 0x63, 0x64}},
{4, {0x61, 0xA4, 0x63, 0x64}},
{4, {0x61, 0xA5, 0x63, 0x64}},
{4, {0x61, 0xA6, 0x63, 0x64}},
{4, {0x61, 0xA7, 0x63, 0x64}},
{4, {0x61, 0xA8, 0x63, 0x64}},
{4, {0x61, 0xA9, 0x63, 0x64}},
{4, {0x61, 0xAA, 0x63, 0x64}},
{4, {0x61, 0xAB, 0x63, 0x64}},
{4, {0x61, 0xAC, 0x63, 0x64}},
{4, {0x61, 0xAD, 0x63, 0x64}},
{4, {0x61, 0xAE, 0x63, 0x64}},
{4, {0x61, 0xAF, 0x63, 0x64}},
{4, {0x61, 0xB0, 0x63, 0x64}},
{4, {0x61, 0xB1, 0x63, 0x64}},
{4, {0x61, 0xB2, 0x63, 0x64}},
{4, {0x61, 0xB3, 0x63, 0x64}},
{4, {0x61, 0xB4, 0x63, 0x64}},
{4, {0x61, 0xB5, 0x63, 0x64}},
{4, {0x61, 0xB6, 0x63, 0x64}},
{4, {0x61, 0xB7, 0x63, 0x64}},
{4, {0x61, 0xB8, 0x63, 0x64}},
{4, {0x61, 0xB9, 0x63, 0x64}},
{4, {0x61, 0xBA, 0x63, 0x64}},
{4, {0x61, 0xBB, 0x63, 0x64}},
{4, {0x61, 0xBC, 0x63, 0x64}},
{4, {0x61, 0xBD, 0x63, 0x64}},
{4, {0x61, 0xBE, 0x63, 0x64}},
{4, {0x61, 0xBF, 0x63, 0x64}},
{4, {0x61, 0xC0, 0x63, 0x64}},
{4, {0x61, 0xC1, 0x63, 0x64}},
{4, {0x61, 0xC2, 0x63, 0x64}},
{4, {0x61, 0xC3, 0x63, 0x64}},
{4, {0x61, 0xC4, 0x63, 0x64}},
{4, {0x61, 0xC5, 0x63, 0x64}},
{4, {0x61, 0xC6, 0x63, 0x64}},
{4, {0x61, 0xC7, 0x63, 0x64}},
{4, {0x61, 0xC8, 0x63, 0x64}},
{4, {0x61, 0xC9, 0x63, 0x64}},
{4, {0x61, 0xCA, 0x63, 0x64}},
{4, {0x61, 0xCB, 0x63, 0x64}},
{4, {0x61, 0xCC, 0x63, 0x64}},
{4, {0x61, 0xCD, 0x63, 0x64}},
{4, {0x61, 0xCE, 0x63, 0x64}},
{4, {0x61, 0xCF, 0x63, 0x64}},
{4, {0x61, 0xD0, 0x63, 0x64}},
{4, {0x61, 0xD1, 0x63, 0x64}},
{4, {0x61, 0xD2, 0x63, 0x64}},
{4, {0x61, 0xD3, 0x63, 0x64}},
{4, {0x61, 0xD4, 0x63, 0x64}},
{4, {0x61, 0xD5, 0x63, 0x64}},
{4, {0x61, 0xD6, 0x63, 0x64}},
{4, {0x61, 0xD7, 0x63, 0x64}},
{4, {0x61, 0xD8, 0x63, 0x64}},
{4, {0x61, 0xD9, 0x63, 0x64}},
{4, {0x61, 0xDA, 0x63, 0x64}},
{4, {0x61, 0xDB, 0x63, 0x64}},
{4, {0x61, 0xDC, 0x63, 0x64}},
{4, {0x61, 0xDD, 0x63, 0x64}},
{4, {0x61, 0xDE, 0x63, 0x64}},
{4, {0x61, 0xDF, 0x63, 0x64}},
{4, {0x61, 0xE0, 0x63, 0x64}},
{4, {0x61, 0xE1, 0x63, 0x64}},
{4, {0x61, 0xE2, 0x63, 0x64}},
{4, {0x61, 0xE3, 0x63, 0x64}},
{4, {0x61, 0xE4, 0x63, 0x64}},
{4, {0x61, 0xE5, 0x63, 0x64}},
{4, {0x61, 0xE6, 0x63, 0x64}},
{4, {0x61, 0xE7, 0x63, 0x64}},
{4, {0x61, 0xE8, 0x63, 0x64}},
{4, {0x61, 0xE9, 0x63, 0x64}},
{4, {0x61, 0xEA, 0x63, 0x64}},
{4, {0x61, 0xEB, 0x63, 0x64}},
{4, {0x61, 0xEC, 0x63, 0x64}},
{4, {0x61, 0xED, 0x63, 0x64}},
{4, {0x61, 0xEE, 0x63, 0x64}},
{4, {0x61, 0xEF, 0x63, 0x64}},
{4, {0x61, 0xF0, 0x63, 0x64}},
{4, {0x61, 0xF1, 0x63, 0x64}},
{4, {0x61, 0xF2, 0x63, 0x64}},
{4, {0x61, 0xF3, 0x63, 0x64}},
{4, {0x61, 0xF4, 0x63, 0x64}},
{4, {0x61, 0xF5, 0x63, 0x64}},
{4, {0x61, 0xF6, 0x63, 0x64}},
{4, {0x61, 0xF7, 0x63, 0x64}},
{4, {0x61, 0xF8, 0x63, 0x64}},
{4, {0x61, 0xF9, 0x63, 0x64}},
{4, {0x61, 0xFA, 0x63, 0x64}},
{4, {0x61, 0xFB, 0x63, 0x64}},
{4, {0x61, 0xFC, 0x63, 0x64}},
{4, {0x61, 0xFD, 0x63, 0x64}},
{4, {0x61, 0xFE, 0x63, 0x64}},
{4, {0x61, 0xFF, 0x63, 0x64}},
};
struct atom atoms_61_62_0X_64[] = {
{4, {0x61, 0x62, 0x00, 0x64}},
{4, {0x61, 0x62, 0x01, 0x64}},
{4, {0x61, 0x62, 0x02, 0x64}},
{4, {0x61, 0x62, 0x03, 0x64}},
{4, {0x61, 0x62, 0x04, 0x64}},
{4, {0x61, 0x62, 0x05, 0x64}},
{4, {0x61, 0x62, 0x06, 0x64}},
{4, {0x61, 0x62, 0x07, 0x64}},
{4, {0x61, 0x62, 0x08, 0x64}},
{4, {0x61, 0x62, 0x09, 0x64}},
{4, {0x61, 0x62, 0x0A, 0x64}},
{4, {0x61, 0x62, 0x0B, 0x64}},
{4, {0x61, 0x62, 0x0C, 0x64}},
{4, {0x61, 0x62, 0x0D, 0x64}},
{4, {0x61, 0x62, 0x0E, 0x64}},
{4, {0x61, 0x62, 0x0F, 0x64}},
};
struct atom atoms_61_6X_63[] = {
{3, {0x61, 0x60, 0x63}},
{3, {0x61, 0x61, 0x63}},
{3, {0x61, 0x62, 0x63}},
{3, {0x61, 0x63, 0x63}},
{3, {0x61, 0x64, 0x63}},
{3, {0x61, 0x65, 0x63}},
{3, {0x61, 0x66, 0x63}},
{3, {0x61, 0x67, 0x63}},
{3, {0x61, 0x68, 0x63}},
{3, {0x61, 0x69, 0x63}},
{3, {0x61, 0x6A, 0x63}},
{3, {0x61, 0x6B, 0x63}},
{3, {0x61, 0x6C, 0x63}},
{3, {0x61, 0x6D, 0x63}},
{3, {0x61, 0x6E, 0x63}},
{3, {0x61, 0x6F, 0x63}},
};
assert_re_atoms("abcd", 1, (struct atom[]) {
{4, {0x61, 0x62, 0x63, 0x64}},
});
assert_re_atoms("abcd1234", 1, (struct atom[]) {
{4, {0x31, 0x32, 0x33, 0x34}},
});
assert_re_atoms("a..d", 1, (struct atom[]) {
{1, {0x61}},
});
assert_re_atoms("a..de", 1, (struct atom[]) {
{2, {0x64, 0x65}},
});
assert_re_atoms("abcd.efgh", 1, (struct atom[]) {
{4, {0x61, 0x62, 0x63, 0x64}},
});
assert_re_atoms("(abcd|efgh)", 2, (struct atom[]) {
{4, {0x65, 0x66, 0x67, 0x68}},
{4, {0x61, 0x62, 0x63, 0x64}},
});
assert_re_atoms("(abcd|efgh|ij)", 3, (struct atom[]) {
{2, {0x69, 0x6A}},
{4, {0x65, 0x66, 0x67, 0x68}},
{4, {0x61, 0x62, 0x63, 0x64}},
});
assert_re_atoms("a.cd", 256, atoms_61_XX_63_64);
assert_hex_atoms("{61 62 63 64}", 1, (struct atom[]) {
{4, {0x61, 0x62, 0x63, 0x64}},
});
assert_hex_atoms("{61 62 63 64 [1-5] 65 66 67 68}", 1, (struct atom[]) {
{4, {0x61, 0x62, 0x63, 0x64}},
});
assert_hex_atoms("{61 62 63 [1-5] 65 66 67 68}", 1, (struct atom[]) {
{4, {0x65, 0x66, 0x67, 0x68}},
});
assert_hex_atoms("{61 62 63 [1-5] 65 66 }", 1, (struct atom[]) {
{3, {0x61, 0x62, 0x63}},
});
assert_hex_atoms("{61 6? 63 [1-5] 65 66 }", 16, atoms_61_6X_63);
assert_hex_atoms("{(61 62 63 | 65 66 67 68)}", 2, (struct atom[]) {
{4, {0x65, 0x66, 0x67, 0x68}},
{3, {0x61, 0x62, 0x63}},
});
assert_hex_atoms("{61 62 0? 64}", 16, atoms_61_62_0X_64);
assert_hex_atoms("{11 ?? 11 ?? 22 33 44 55 66 }", 1, (struct atom[]) {
{4, {0x22, 0x33, 0x44, 0x55}},
});
}
int main(int argc, char** argv)
{
test_quality_quality();
yr_initialize();
test_table_quality();
test_heuristic_quality();
test_atom_choose();
}
+46 -10
View File
@@ -1142,6 +1142,7 @@ void test_re()
assert_true_regexp("(a+|b)*", "ab", "ab");
assert_true_regexp("a|b|c|d|e", "e", "e");
assert_true_regexp("(a|b|c|d|e)f", "ef", "ef");
assert_true_regexp("a|b", "a", "a");
assert_true_regexp(".b{2}", "abb", "abb");
assert_true_regexp(".b{2,3}", "abbb", "abbb");
assert_true_regexp(".b{2,3}?", "abbb", "abb");
@@ -1899,11 +1900,6 @@ void test_performance_warnings()
strings: $a = { 01 ?? } \
condition: $a }")
assert_warning(
"rule test { \
strings: $a = { 01 00 } \
condition: $a }")
assert_warning(
"rule test { \
strings: $a = { 01 ?? ?? } \
@@ -1914,6 +1910,31 @@ void test_performance_warnings()
strings: $a = { 01 ?? ?? 02 } \
condition: $a }")
assert_warning(
"rule test { \
strings: $a = { 01 ?? ?2 03 } \
condition: $a }")
assert_warning(
"rule test { \
strings: $a = { 01 ?? 02 1? } \
condition: $a }")
assert_warning(
"rule test { \
strings: $a = { 1? 2? 3? } \
condition: $a }")
assert_warning(
"rule test { \
strings: $a = { 1? 2? 3? 04 } \
condition: $a }")
assert_warning(
"rule test { \
strings: $a = { 1? ?? 03 } \
condition: $a }")
assert_warning(
"rule test { \
strings: $a = { 00 01 } \
@@ -1934,24 +1955,29 @@ void test_performance_warnings()
strings: $a = { 00 00 00 } \
condition: $a }")
assert_no_warnings(
"rule test { \
strings: $a = { 00 00 01 } \
condition: $a }")
assert_warning(
"rule test { \
strings: $a = { 00 00 00 00 } \
condition: $a }")
assert_warning(
assert_no_warnings(
"rule test { \
strings: $a = { 00 00 00 01 } \
condition: $a }")
assert_warning(
"rule test { \
strings: $a = { 00 00 01 02 } \
strings: $a = { FF FF FF FF } \
condition: $a }")
assert_warning(
assert_no_warnings(
"rule test { \
strings: $a = { FF FF FF FF } \
strings: $a = { 00 00 01 02 } \
condition: $a }")
assert_no_warnings(
@@ -1978,6 +2004,16 @@ void test_performance_warnings()
"rule test { \
strings: $a = { 01 02 } \
condition: $a }")
assert_no_warnings(
"rule test { \
strings: $a = \"foo\" wide \
condition: $a }")
assert_no_warnings(
"rule test { \
strings: $a = \"MZ\" \
condition: $a }")
}
@@ -2023,7 +2059,7 @@ int main(int argc, char** argv)
test_global_rules();
#if !defined(USE_WINDOWS_PROC) && !defined(USE_NO_PROC)
test_process_scan();
//test_process_scan();
#endif
#if defined(HASH_MODULE)
+81
View File
@@ -0,0 +1,81 @@
/*
Copyright (c) 2018. The YARA Authors. All Rights Reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <yara/stack.h>
#include <yara.h>
#include "util.h"
int main(int argc, char** argv)
{
YR_STACK* stack;
int item;
yr_initialize();
yr_stack_create(1, sizeof(item), &stack);
item = 1;
if (yr_stack_push(stack, &item) != ERROR_SUCCESS)
exit(EXIT_FAILURE);
item = 2;
if (yr_stack_push(stack, &item) != ERROR_SUCCESS)
exit(EXIT_FAILURE);
item = 3;
if (yr_stack_push(stack, &item) != ERROR_SUCCESS)
exit(EXIT_FAILURE);
item = 4;
if (yr_stack_push(stack, &item) != ERROR_SUCCESS)
exit(EXIT_FAILURE);
if (!yr_stack_pop(stack, &item) || item != 4)
exit(EXIT_FAILURE);
if (!yr_stack_pop(stack, &item) || item != 3)
exit(EXIT_FAILURE);
if (!yr_stack_pop(stack, &item) || item != 2)
exit(EXIT_FAILURE);
if (!yr_stack_pop(stack, &item) || item != 1)
exit(EXIT_FAILURE);
if (yr_stack_pop(stack, &item) || item != 1)
exit(EXIT_FAILURE);
yr_stack_destroy(stack);
}
+62
View File
@@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <fcntl.h>
#include <yara.h>
#include "util.h"
char compile_error[1024];
int warnings;
@@ -260,3 +261,64 @@ _exit:
close(fd);
return rc;
}
void _assert_atoms(
RE_AST* re_ast,
int expected_atom_count,
atom* expected_atoms)
{
YR_ATOMS_CONFIG c;
YR_ATOM_LIST_ITEM* atoms;
YR_ATOM_LIST_ITEM* atom;
int min_atom_quality;
c.get_atom_quality = yr_atoms_heuristic_quality;
yr_atoms_extract_from_re(&c, re_ast, 0, &atoms, &min_atom_quality);
atom = atoms;
while (atom != NULL)
{
if (expected_atom_count == 0)
exit(EXIT_FAILURE);
if (atom->atom.length != expected_atoms->length ||
memcmp(atom->atom.bytes, expected_atoms->data, atom->atom.length) != 0)
{
exit(EXIT_FAILURE);
}
expected_atoms++;
expected_atom_count--;
atom = atom->next;
}
}
void assert_re_atoms(
char* re,
int expected_atom_count,
atom* expected_atoms)
{
RE_AST* re_ast;
RE_ERROR re_error;
yr_re_parse(re, &re_ast, &re_error);
_assert_atoms(re_ast, expected_atom_count, expected_atoms);
}
void assert_hex_atoms(
char* hex,
int expected_atom_count,
atom* expected_atoms)
{
RE_AST* re_ast;
RE_ERROR re_error;
yr_re_parse_hex(hex, &re_ast, &re_error);
_assert_atoms(re_ast, expected_atom_count, expected_atoms);
}
+21
View File
@@ -71,6 +71,27 @@ int read_file(
char* filename, char** buf);
typedef struct atom atom;
struct atom
{
uint8_t length;
uint8_t data[YR_MAX_ATOM_LENGTH];
};
void assert_re_atoms(
char* re,
int expected_atom_count,
atom* expected_atoms);
void assert_hex_atoms(
char* hex,
int expected_atom_count,
atom* expected_atoms);
#define assert_true_expr(expr) \
do { \
if (!(expr)) { \
+1
View File
@@ -257,6 +257,7 @@
<ClCompile Include="..\..\..\libyara\scan.c" />
<ClCompile Include="..\..\..\libyara\scanner.c" />
<ClCompile Include="..\..\..\libyara\sizedstr.c" />
<ClCompile Include="..\..\..\libyara\stack.c" />
<ClCompile Include="..\..\..\libyara\stopwatch.c" />
<ClCompile Include="..\..\..\libyara\stream.c" />
<ClCompile Include="..\..\..\libyara\strutils.c" />