[Forensics-changes] [yara] 196/415: Implement nested loops
Hilko Bengen
bengen at moszumanska.debian.org
Thu Apr 3 05:43:04 UTC 2014
This is an automated email from the git hooks/post-receive script.
bengen pushed a commit to branch debian
in repository yara.
commit 9cd1f9343756eaf044d271a8369c2963e7e3df0f
Author: Victor M. Alvarez <plusvic at gmail.com>
Date: Fri Jul 19 14:31:59 2013 +0000
Implement nested loops
---
libyara/compiler.c | 16 +-
libyara/exec.c | 87 +++++-----
libyara/exec.h | 69 ++++----
libyara/grammar.c | 467 +++++++++++++++++++++++++++++++--------------------
libyara/grammar.h | 2 +-
libyara/grammar.y | 217 +++++++++++++++++-------
libyara/parser.c | 26 ++-
libyara/parser.h | 4 +
libyara/yara.h | 12 +-
yara-python/tests.py | 17 +-
10 files changed, 580 insertions(+), 337 deletions(-)
diff --git a/libyara/compiler.c b/libyara/compiler.c
index 41e90b8..2ebf986 100644
--- a/libyara/compiler.c
+++ b/libyara/compiler.c
@@ -46,9 +46,8 @@ int yr_compiler_create(
new_compiler->file_stack_ptr = 0;
new_compiler->file_name_stack_ptr = 0;
new_compiler->current_rule_flags = 0;
- new_compiler->inside_for = 0;
new_compiler->allow_includes = 1;
- new_compiler->loop_identifier = NULL;
+ new_compiler->loop_depth = 0;
new_compiler->compiled_rules_arena = NULL;
new_compiler->externals_count = 0;
new_compiler->namespaces_count = 0;
@@ -684,6 +683,13 @@ char* yr_compiler_get_error_message(
"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_INVALID_CHAR_IN_HEX_STRING:
snprintf(
buffer,
@@ -808,11 +814,17 @@ char* yr_compiler_get_error_message(
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;
}
return buffer;
diff --git a/libyara/exec.c b/libyara/exec.c
index 3124fa8..0a47462 100644
--- a/libyara/exec.c
+++ b/libyara/exec.c
@@ -20,6 +20,7 @@ limitations under the License.
#include "exec.h"
#define STACK_SIZE 4096
+#define MEM_SIZE MAX_LOOP_NESTING * LOOP_LOCAL_VARS
#define push(x) \
@@ -72,6 +73,7 @@ int yr_execute_code(
int64_t r1;
int64_t r2;
int64_t r3;
+ int64_t mem[MEM_SIZE];
int64_t stack[STACK_SIZE];
int32_t sp = 0;
uint8_t* ip = rules->code_start;
@@ -103,55 +105,56 @@ int yr_execute_code(
push(r1);
break;
- case PUSH_A:
- push(rA);
- break;
-
- case POP_A:
- pop(rA);
- break;
-
- case PUSH_B:
- push(rB);
- break;
-
- case POP_B:
- pop(rB);
+ case POP:
+ pop(r1);
break;
- case PUSH_C:
- push(rC);
+ case CLEAR_M:
+ r1 = *(uint64_t*)(ip + 1);
+ ip += sizeof(uint64_t);
+ mem[r1] = 0;
break;
- case POP_C:
- pop(rC);
+ case ADD_M:
+ r1 = *(uint64_t*)(ip + 1);
+ ip += sizeof(uint64_t);
+ pop(r2);
+ mem[r1] += r2;
break;
- case CLEAR_B:
- rB = 0;
+ case INCR_M:
+ r1 = *(uint64_t*)(ip + 1);
+ ip += sizeof(uint64_t);
+ mem[r1]++;
break;
- case CLEAR_C:
- rC = 0;
+ case PUSH_M:
+ r1 = *(uint64_t*)(ip + 1);
+ ip += sizeof(uint64_t);
+ push(mem[r1]);
break;
- case INCR_A:
- pop(r1);
- rA += r1;
- break;
+ case POP_M:
+ r1 = *(uint64_t*)(ip + 1);
+ ip += sizeof(uint64_t);
+ pop(mem[r1]);
+ break;
- case INCR_B:
- pop(r1);
- rB += r1;
+ case SWAPUNDEF:
+ r1 = *(uint64_t*)(ip + 1);
+ ip += sizeof(uint64_t);
+ pop(r2);
+ if (r2 != UNDEFINED)
+ push(r2);
+ else
+ push(mem[r1]);
break;
- case INCR_C:
+ case JNUNDEF:
pop(r1);
- rC += r1;
- break;
+ push(r1);
- case JLE_A_B:
- if (rA <= rB)
+ if (r1 != UNDEFINED)
{
ip = *(uint8_t**)(ip + 1);
// ip will be incremented at the end of the loop,
@@ -164,8 +167,13 @@ int yr_execute_code(
}
break;
- case JNUNDEF_A:
- if (rA != UNDEFINED)
+ case JLE:
+ pop(r2);
+ pop(r1);
+ push(r1);
+ push(r2);
+
+ if (r1 <= r2)
{
ip = *(uint8_t**)(ip + 1);
// ip will be incremented at the end of the loop,
@@ -178,13 +186,6 @@ int yr_execute_code(
}
break;
- case PNUNDEF_A_B:
- if (rA != UNDEFINED)
- push(rA);
- else
- push(rB);
- break;
-
case AND:
pop(r2);
pop(r1);
diff --git a/libyara/exec.h b/libyara/exec.h
index 5fa545e..8739790 100644
--- a/libyara/exec.h
+++ b/libyara/exec.h
@@ -43,44 +43,37 @@ limitations under the License.
#define NEG 19
#define SHL 20
#define SHR 21
-#define RULE_PUSH 22
-#define RULE_POP 23
-#define SCOUNT 24
-#define SFOUND 25
-#define SFOUND_AT 26
-#define SFOUND_IN 27
-#define SOFFSET 28
-#define OF 30
-#define EXT_BOOL 31
-#define EXT_INT 32
-#define EXT_STR 33
-
-#define PUSH 60
-#define PUSH_A 61
-#define PUSH_B 62
-#define PUSH_C 63
-#define POP_A 64
-#define POP_B 65
-#define POP_C 66
-#define CLEAR_B 67
-#define CLEAR_C 68
-#define INCR_A 69
-#define INCR_B 70
-#define INCR_C 71
-#define PNUNDEF_A_B 72
-#define JLE_A_B 74
-#define JNUNDEF_A 75
-
-#define SIZE 76
-#define ENTRYPOINT 77
-#define INT8 78
-#define INT16 79
-#define INT32 80
-#define UINT8 81
-#define UINT16 82
-#define UINT32 83
-#define CONTAINS 84
-#define MATCHES 85
+#define PUSH 22
+#define POP 23
+#define RULE_PUSH 24
+#define RULE_POP 25
+#define SCOUNT 26
+#define SFOUND 27
+#define SFOUND_AT 28
+#define SFOUND_IN 29
+#define SOFFSET 30
+#define OF 31
+#define EXT_BOOL 32
+#define EXT_INT 33
+#define EXT_STR 34
+#define INCR_M 35
+#define CLEAR_M 36
+#define ADD_M 37
+#define POP_M 38
+#define PUSH_M 39
+#define SWAPUNDEF 40
+#define JNUNDEF 41
+#define JLE 42
+#define SIZE 43
+#define ENTRYPOINT 44
+#define INT8 45
+#define INT16 46
+#define INT32 47
+#define UINT8 48
+#define UINT16 49
+#define UINT32 50
+#define CONTAINS 51
+#define MATCHES 52
typedef struct _EVALUATION_CONTEXT
diff --git a/libyara/grammar.c b/libyara/grammar.c
index ec4283a..c205cd9 100644
--- a/libyara/grammar.c
+++ b/libyara/grammar.c
@@ -221,6 +221,8 @@
#define INTEGER_SET_ENUMERATION 1
#define INTEGER_SET_RANGE 2
+
+
#define ERROR_IF(x) \
if (x) \
{ \
@@ -250,7 +252,7 @@
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
-#line 149 "grammar.y"
+#line 151 "grammar.y"
{
void* sized_string;
char* c_string;
@@ -259,7 +261,7 @@ typedef union YYSTYPE
void* meta;
}
/* Line 193 of yacc.c. */
-#line 263 "grammar.c"
+#line 265 "grammar.c"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
@@ -272,7 +274,7 @@ typedef union YYSTYPE
/* Line 216 of yacc.c. */
-#line 276 "grammar.c"
+#line 278 "grammar.c"
#ifdef short
# undef short
@@ -605,17 +607,17 @@ static const yytype_int8 yyrhs[] =
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 160, 160, 161, 162, 163, 167, 184, 185, 213,
- 217, 245, 249, 250, 254, 255, 259, 260, 275, 285,
- 319, 320, 324, 340, 353, 366, 382, 383, 387, 400,
- 413, 429, 430, 434, 435, 436, 437, 441, 442, 446,
- 450, 481, 523, 527, 538, 549, 553, 564, 570, 578,
- 569, 651, 650, 686, 690, 693, 697, 701, 705, 709,
- 713, 717, 721, 725, 729, 736, 755, 769, 770, 774,
- 778, 779, 783, 782, 787, 794, 795, 798, 803, 810,
- 811, 815, 822, 823, 827, 831, 835, 839, 843, 847,
- 851, 855, 859, 870, 881, 895, 917, 921, 925, 929,
- 933, 937, 941, 945, 949, 953, 957, 963, 964, 965
+ 0, 162, 162, 163, 164, 165, 169, 186, 187, 215,
+ 219, 247, 251, 252, 256, 257, 261, 262, 277, 287,
+ 321, 322, 326, 342, 355, 368, 384, 385, 389, 402,
+ 415, 431, 432, 436, 437, 438, 439, 443, 444, 448,
+ 452, 483, 525, 529, 540, 551, 555, 566, 572, 609,
+ 571, 708, 707, 777, 781, 784, 788, 792, 796, 800,
+ 804, 808, 812, 816, 820, 827, 846, 860, 861, 865,
+ 869, 870, 874, 873, 878, 885, 886, 889, 894, 901,
+ 902, 906, 913, 914, 918, 922, 926, 930, 934, 938,
+ 942, 946, 950, 961, 972, 986, 1014, 1018, 1022, 1026,
+ 1030, 1034, 1038, 1042, 1046, 1050, 1054, 1060, 1061, 1062
};
#endif
@@ -1412,49 +1414,49 @@ yydestruct (yymsg, yytype, yyvaluep, yyscanner)
switch (yytype)
{
case 10: /* "_IDENTIFIER_" */
-#line 139 "grammar.y"
+#line 141 "grammar.y"
{ yr_free((yyvaluep->c_string)); };
-#line 1418 "grammar.c"
+#line 1420 "grammar.c"
break;
case 11: /* "_STRING_IDENTIFIER_" */
-#line 140 "grammar.y"
+#line 142 "grammar.y"
{ yr_free((yyvaluep->c_string)); };
-#line 1423 "grammar.c"
+#line 1425 "grammar.c"
break;
case 12: /* "_STRING_COUNT_" */
-#line 141 "grammar.y"
+#line 143 "grammar.y"
{ yr_free((yyvaluep->c_string)); };
-#line 1428 "grammar.c"
+#line 1430 "grammar.c"
break;
case 13: /* "_STRING_OFFSET_" */
-#line 142 "grammar.y"
+#line 144 "grammar.y"
{ yr_free((yyvaluep->c_string)); };
-#line 1433 "grammar.c"
+#line 1435 "grammar.c"
break;
case 14: /* "_STRING_IDENTIFIER_WITH_WILDCARD_" */
-#line 143 "grammar.y"
+#line 145 "grammar.y"
{ yr_free((yyvaluep->c_string)); };
-#line 1438 "grammar.c"
+#line 1440 "grammar.c"
break;
case 15: /* "_ANONYMOUS_STRING_" */
-#line 144 "grammar.y"
+#line 146 "grammar.y"
{ yr_free((yyvaluep->c_string)); };
-#line 1443 "grammar.c"
+#line 1445 "grammar.c"
break;
case 18: /* "_TEXTSTRING_" */
-#line 145 "grammar.y"
+#line 147 "grammar.y"
{ yr_free((yyvaluep->sized_string)); };
-#line 1448 "grammar.c"
+#line 1450 "grammar.c"
break;
case 19: /* "_HEXSTRING_" */
-#line 146 "grammar.y"
+#line 148 "grammar.y"
{ yr_free((yyvaluep->sized_string)); };
-#line 1453 "grammar.c"
+#line 1455 "grammar.c"
break;
case 20: /* "_REGEXP_" */
-#line 147 "grammar.y"
+#line 149 "grammar.y"
{ yr_free((yyvaluep->sized_string)); };
-#line 1458 "grammar.c"
+#line 1460 "grammar.c"
break;
default:
@@ -1763,7 +1765,7 @@ yyreduce:
switch (yyn)
{
case 6:
-#line 168 "grammar.y"
+#line 170 "grammar.y"
{
int result = yr_parser_reduce_rule_declaration(
yyscanner,
@@ -1780,12 +1782,12 @@ yyreduce:
break;
case 7:
-#line 184 "grammar.y"
+#line 186 "grammar.y"
{ (yyval.meta) = NULL; }
break;
case 8:
-#line 186 "grammar.y"
+#line 188 "grammar.y"
{
// Each rule have a list of meta-data info, consisting in a
// sequence of META structures. The last META structure does
@@ -1812,7 +1814,7 @@ yyreduce:
break;
case 9:
-#line 213 "grammar.y"
+#line 215 "grammar.y"
{
(yyval.string) = NULL;
yyget_extra(yyscanner)->current_rule_strings = (yyval.string);
@@ -1820,7 +1822,7 @@ yyreduce:
break;
case 10:
-#line 218 "grammar.y"
+#line 220 "grammar.y"
{
// Each rule have a list of strings, consisting in a sequence
// of STRING structures. The last STRING structure does not
@@ -1848,32 +1850,32 @@ yyreduce:
break;
case 12:
-#line 249 "grammar.y"
+#line 251 "grammar.y"
{ (yyval.integer) = 0; }
break;
case 13:
-#line 250 "grammar.y"
+#line 252 "grammar.y"
{ (yyval.integer) = (yyvsp[(1) - (2)].integer) | (yyvsp[(2) - (2)].integer); }
break;
case 14:
-#line 254 "grammar.y"
+#line 256 "grammar.y"
{ (yyval.integer) = RULE_FLAGS_PRIVATE; }
break;
case 15:
-#line 255 "grammar.y"
+#line 257 "grammar.y"
{ (yyval.integer) = RULE_FLAGS_GLOBAL; }
break;
case 16:
-#line 259 "grammar.y"
+#line 261 "grammar.y"
{ (yyval.c_string) = NULL; }
break;
case 17:
-#line 261 "grammar.y"
+#line 263 "grammar.y"
{
// Tags list is represented in the arena as a sequence
// of null-terminated strings, the sequence ends with an
@@ -1888,7 +1890,7 @@ yyreduce:
break;
case 18:
-#line 276 "grammar.y"
+#line 278 "grammar.y"
{
char* identifier;
@@ -1901,7 +1903,7 @@ yyreduce:
break;
case 19:
-#line 286 "grammar.y"
+#line 288 "grammar.y"
{
YARA_COMPILER* compiler = yyget_extra(yyscanner);
char* tag_name = (yyvsp[(1) - (2)].c_string);
@@ -1936,17 +1938,17 @@ yyreduce:
break;
case 20:
-#line 319 "grammar.y"
+#line 321 "grammar.y"
{ (yyval.meta) = (yyvsp[(1) - (1)].meta); }
break;
case 21:
-#line 320 "grammar.y"
+#line 322 "grammar.y"
{ (yyval.meta) = (yyvsp[(1) - (2)].meta); }
break;
case 22:
-#line 325 "grammar.y"
+#line 327 "grammar.y"
{
SIZED_STRING* sized_string = (yyvsp[(3) - (3)].sized_string);
@@ -1965,7 +1967,7 @@ yyreduce:
break;
case 23:
-#line 341 "grammar.y"
+#line 343 "grammar.y"
{
(yyval.meta) = yr_parser_reduce_meta_declaration(
yyscanner,
@@ -1981,7 +1983,7 @@ yyreduce:
break;
case 24:
-#line 354 "grammar.y"
+#line 356 "grammar.y"
{
(yyval.meta) = yr_parser_reduce_meta_declaration(
yyscanner,
@@ -1997,7 +1999,7 @@ yyreduce:
break;
case 25:
-#line 367 "grammar.y"
+#line 369 "grammar.y"
{
(yyval.meta) = yr_parser_reduce_meta_declaration(
yyscanner,
@@ -2013,17 +2015,17 @@ yyreduce:
break;
case 26:
-#line 382 "grammar.y"
+#line 384 "grammar.y"
{ (yyval.string) = (yyvsp[(1) - (1)].string); }
break;
case 27:
-#line 383 "grammar.y"
+#line 385 "grammar.y"
{ (yyval.string) = (yyvsp[(1) - (2)].string); }
break;
case 28:
-#line 388 "grammar.y"
+#line 390 "grammar.y"
{
(yyval.string) = yr_parser_reduce_string_declaration(
yyscanner,
@@ -2039,7 +2041,7 @@ yyreduce:
break;
case 29:
-#line 401 "grammar.y"
+#line 403 "grammar.y"
{
(yyval.string) = yr_parser_reduce_string_declaration(
yyscanner,
@@ -2055,7 +2057,7 @@ yyreduce:
break;
case 30:
-#line 414 "grammar.y"
+#line 416 "grammar.y"
{
(yyval.string) = yr_parser_reduce_string_declaration(
yyscanner,
@@ -2071,51 +2073,51 @@ yyreduce:
break;
case 31:
-#line 429 "grammar.y"
+#line 431 "grammar.y"
{ (yyval.integer) = 0; }
break;
case 32:
-#line 430 "grammar.y"
+#line 432 "grammar.y"
{ (yyval.integer) = (yyvsp[(1) - (2)].integer) | (yyvsp[(2) - (2)].integer); }
break;
case 33:
-#line 434 "grammar.y"
+#line 436 "grammar.y"
{ (yyval.integer) = STRING_FLAGS_WIDE; }
break;
case 34:
-#line 435 "grammar.y"
+#line 437 "grammar.y"
{ (yyval.integer) = STRING_FLAGS_ASCII; }
break;
case 35:
-#line 436 "grammar.y"
+#line 438 "grammar.y"
{ (yyval.integer) = STRING_FLAGS_NO_CASE; }
break;
case 36:
-#line 437 "grammar.y"
+#line 439 "grammar.y"
{ (yyval.integer) = STRING_FLAGS_FULL_WORD; }
break;
case 38:
-#line 443 "grammar.y"
+#line 445 "grammar.y"
{
yr_parser_emit_with_arg(yyscanner, PUSH, 1, NULL);
}
break;
case 39:
-#line 447 "grammar.y"
+#line 449 "grammar.y"
{
yr_parser_emit_with_arg(yyscanner, PUSH, 0, NULL);
}
break;
case 40:
-#line 451 "grammar.y"
+#line 453 "grammar.y"
{
YARA_COMPILER* compiler = yyget_extra(yyscanner);
RULE* rule;
@@ -2149,7 +2151,7 @@ yyreduce:
break;
case 41:
-#line 482 "grammar.y"
+#line 484 "grammar.y"
{
YARA_COMPILER* compiler = yyget_extra(yyscanner);
SIZED_STRING* sized_string = (yyvsp[(3) - (3)].sized_string);
@@ -2194,14 +2196,14 @@ yyreduce:
break;
case 42:
-#line 524 "grammar.y"
+#line 526 "grammar.y"
{
yr_parser_emit(yyscanner, CONTAINS, NULL);
}
break;
case 43:
-#line 528 "grammar.y"
+#line 530 "grammar.y"
{
int result = yr_parser_reduce_string_identifier(
yyscanner,
@@ -2215,7 +2217,7 @@ yyreduce:
break;
case 44:
-#line 539 "grammar.y"
+#line 541 "grammar.y"
{
int result = yr_parser_reduce_string_identifier(
yyscanner,
@@ -2229,14 +2231,14 @@ yyreduce:
break;
case 45:
-#line 550 "grammar.y"
+#line 552 "grammar.y"
{
yr_free((yyvsp[(1) - (4)].c_string));
}
break;
case 46:
-#line 554 "grammar.y"
+#line 556 "grammar.y"
{
int result = yr_parser_reduce_string_identifier(
yyscanner,
@@ -2250,7 +2252,7 @@ yyreduce:
break;
case 47:
-#line 565 "grammar.y"
+#line 567 "grammar.y"
{
yr_free((yyvsp[(1) - (6)].c_string));
yr_free((yyvsp[(5) - (6)].sized_string));
@@ -2258,222 +2260,311 @@ yyreduce:
break;
case 48:
-#line 570 "grammar.y"
+#line 572 "grammar.y"
{
- yr_parser_emit_with_arg(
+ YARA_COMPILER* compiler = yyget_extra(yyscanner);
+ int result = ERROR_SUCCESS;
+ int var_index;
+
+ if (compiler->loop_depth == MAX_LOOP_NESTING)
+ compiler->last_result = \
+ ERROR_LOOP_NESTING_LIMIT_EXCEEDED;
+
+ ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+
+ var_index = yr_parser_lookup_loop_variable(
+ yyscanner,
+ (yyvsp[(3) - (4)].c_string));
+
+ if (var_index >= 0)
+ {
+ yr_compiler_set_error_extra_info(
+ compiler,
+ (yyvsp[(3) - (4)].c_string));
+
+ compiler->last_result = \
+ ERROR_DUPLICATE_LOOP_IDENTIFIER;
+ }
+
+ ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+
+ // Push end-of-list marker
+ result = yr_parser_emit_with_arg(
yyscanner,
PUSH,
UNDEFINED,
NULL);
+
+ ERROR_IF(result != ERROR_SUCCESS);
}
break;
case 49:
-#line 578 "grammar.y"
+#line 609 "grammar.y"
{
YARA_COMPILER* compiler = yyget_extra(yyscanner);
+ int mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
+ int8_t* addr;
+
+ // Clear counter for number of expressions evaluating
+ // to TRUE.
+ yr_parser_emit_with_arg(
+ yyscanner, CLEAR_M, mem_offset + 1, NULL);
+
+ // Clear iterations counter
+ yr_parser_emit_with_arg(
+ yyscanner, CLEAR_M, mem_offset + 2, NULL);
if ((yyvsp[(6) - (7)].integer) == INTEGER_SET_ENUMERATION)
{
- yr_parser_emit(yyscanner, CLEAR_B, NULL);
- yr_parser_emit(yyscanner, CLEAR_C, NULL);
- yr_parser_emit(
- yyscanner,
- POP_A,
- &compiler->loop_address);
+ // Pop the first integer
+ yr_parser_emit_with_arg(
+ yyscanner, POP_M, mem_offset, &addr);
}
else // INTEGER_SET_RANGE
{
- yr_parser_emit(yyscanner, POP_B, NULL);
- yr_parser_emit(yyscanner, POP_A, NULL);
- yr_parser_emit(yyscanner, POP_C, NULL);
- yr_parser_emit(yyscanner, CLEAR_C, NULL);
- yr_parser_emit_with_arg(yyscanner, PUSH, 1, NULL);
- yr_parser_emit(yyscanner, INCR_B, NULL);
- yr_parser_emit(yyscanner, PUSH_B, NULL);
- yr_parser_emit(yyscanner, PUSH_A, NULL);
- yr_parser_emit(
- yyscanner,
- SUB,
- &compiler->loop_address);
+ yr_parser_emit_with_arg(
+ yyscanner, POP_M, mem_offset + 3, &addr);
+
+ yr_parser_emit_with_arg(
+ yyscanner, POP_M, mem_offset, NULL);
}
- compiler->loop_address++;
- compiler->loop_identifier = (yyvsp[(3) - (7)].c_string);
+ compiler->loop_address[compiler->loop_depth] = addr;
+ compiler->loop_identifier[compiler->loop_depth] = (yyvsp[(3) - (7)].c_string);
+ compiler->loop_depth++;
}
break;
case 50:
-#line 610 "grammar.y"
+#line 643 "grammar.y"
{
YARA_COMPILER* compiler = yyget_extra(yyscanner);
+ int mem_offset;
+
+ compiler->loop_depth--;
+ mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
+
+ yr_parser_emit_with_arg(
+ yyscanner, ADD_M, mem_offset + 1, NULL);
+
+ yr_parser_emit_with_arg(
+ yyscanner, INCR_M, mem_offset + 2, NULL);
if ((yyvsp[(6) - (11)].integer) == INTEGER_SET_ENUMERATION)
{
- yr_parser_emit(yyscanner, INCR_C, NULL);
- yr_parser_emit_with_arg(yyscanner, PUSH, 1, NULL);
- yr_parser_emit(yyscanner, INCR_B, NULL);
- yr_parser_emit(yyscanner, POP_A, NULL);
-
yr_parser_emit_with_arg_reloc(
yyscanner,
- JNUNDEF_A,
- PTR_TO_UINT64(compiler->loop_address),
+ JNUNDEF,
+ PTR_TO_UINT64(
+ compiler->loop_address[compiler->loop_depth]),
NULL);
}
else // INTEGER_SET_RANGE
{
- yr_parser_emit(yyscanner, INCR_C, NULL);
- yr_parser_emit_with_arg(yyscanner, PUSH, 1, NULL);
- yr_parser_emit(yyscanner, INCR_A, NULL);
+ yr_parser_emit_with_arg(
+ yyscanner, INCR_M, mem_offset, NULL);
+
+ yr_parser_emit_with_arg(
+ yyscanner, PUSH_M, mem_offset, NULL);
+
+ yr_parser_emit_with_arg(
+ yyscanner, PUSH_M, mem_offset + 3, NULL);
yr_parser_emit_with_arg_reloc(
yyscanner,
- JLE_A_B,
- PTR_TO_UINT64(compiler->loop_address),
+ JLE,
+ PTR_TO_UINT64(
+ compiler->loop_address[compiler->loop_depth]),
NULL);
- yr_parser_emit(yyscanner, POP_B, NULL);
+ yr_parser_emit(yyscanner, POP, NULL);
+ yr_parser_emit(yyscanner, POP, NULL);
}
- yr_parser_emit(yyscanner, POP_A, NULL);
- yr_parser_emit(yyscanner, PNUNDEF_A_B, NULL);
- yr_parser_emit(yyscanner, PUSH_C, NULL);
- yr_parser_emit(yyscanner, LE, NULL);
+ // Pop end-of-list marker.
+ yr_parser_emit(yyscanner, POP, NULL);
- compiler->loop_identifier = NULL;
+ // At this point the loop quantifier (any, all, 1, 2,..)
+ // is at the top of the stack. Check if the quantifier
+ // is undefined (meaning "all") and replace it with the
+ // iterations counter in that case.
+ yr_parser_emit_with_arg(
+ yyscanner, SWAPUNDEF, mem_offset + 2, NULL);
+
+ // Compare the loop quantifier with the number of
+ // expressions evaluating to TRUE.
+ yr_parser_emit_with_arg(
+ yyscanner, PUSH_M, mem_offset + 1, NULL);
+ yr_parser_emit(yyscanner, LE, NULL);
+
+ compiler->loop_identifier[compiler->loop_depth] = NULL;
yr_free((yyvsp[(3) - (11)].c_string));
}
break;
case 51:
-#line 651 "grammar.y"
+#line 708 "grammar.y"
{
YARA_COMPILER* compiler = yyget_extra(yyscanner);
+ int mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
+ int result = ERROR_SUCCESS;
+ int8_t* addr;
- yr_parser_emit(yyscanner, CLEAR_B, NULL);
- yr_parser_emit(yyscanner, CLEAR_C, NULL);
- yr_parser_emit(
- yyscanner,
- POP_A,
- &compiler->loop_address);
+ if (compiler->loop_depth == MAX_LOOP_NESTING)
+ compiler->last_result = \
+ ERROR_LOOP_NESTING_LIMIT_EXCEEDED;
+
+ ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+
+ yr_parser_emit_with_arg(
+ yyscanner, CLEAR_M, mem_offset + 1, NULL);
- compiler->loop_address++;
- compiler->inside_for++;
+ yr_parser_emit_with_arg(
+ yyscanner, CLEAR_M, mem_offset + 2, NULL);
+
+ // Pop the first string.
+ yr_parser_emit_with_arg(
+ yyscanner, POP_M, mem_offset, &addr);
+
+ compiler->loop_address[compiler->loop_depth] = addr;
+ compiler->loop_depth++;
}
break;
case 52:
-#line 665 "grammar.y"
+#line 734 "grammar.y"
{
YARA_COMPILER* compiler = yyget_extra(yyscanner);
+ int mem_offset;
- yr_parser_emit(yyscanner, INCR_C, NULL);
- yr_parser_emit_with_arg(yyscanner, PUSH, 1, NULL);
- yr_parser_emit(yyscanner, INCR_B, NULL);
- yr_parser_emit(yyscanner, POP_A, NULL);
+ compiler->loop_depth--;
+ mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
+
+ // Increment counter by the value returned by the
+ // boolean expression (0 or 1).
+ yr_parser_emit_with_arg(
+ yyscanner, ADD_M, mem_offset + 1, NULL);
+
+ // Increment iterations counter.
+ yr_parser_emit_with_arg(
+ yyscanner, INCR_M, mem_offset + 2, NULL);
+ // If next string is not undefined, go back to the
+ // begining of the loop.
yr_parser_emit_with_arg_reloc(
yyscanner,
- JNUNDEF_A,
- PTR_TO_UINT64(compiler->loop_address),
+ JNUNDEF,
+ PTR_TO_UINT64(
+ compiler->loop_address[compiler->loop_depth]),
NULL);
- yr_parser_emit(yyscanner, POP_A, NULL);
- yr_parser_emit(yyscanner, PNUNDEF_A_B, NULL);
- yr_parser_emit(yyscanner, PUSH_C, NULL);
+ // Pop end-of-list marker.
+ yr_parser_emit(yyscanner, POP, NULL);
+
+ // At this point the loop quantifier (any, all, 1, 2,..)
+ // is at top of the stack. Check if the quantifier is
+ // undefined (meaning "all") and replace it with the
+ // iterations counter in that case.
+ yr_parser_emit_with_arg(
+ yyscanner, SWAPUNDEF, mem_offset + 2, NULL);
+
+ // Compare the loop quantifier with the number of
+ // expressions evaluating to TRUE.
+ yr_parser_emit_with_arg(
+ yyscanner, PUSH_M, mem_offset + 1, NULL);
+
yr_parser_emit(yyscanner, LE, NULL);
- compiler->inside_for--;
}
break;
case 53:
-#line 687 "grammar.y"
+#line 778 "grammar.y"
{
yr_parser_emit(yyscanner, OF, NULL);
}
break;
case 54:
-#line 691 "grammar.y"
+#line 782 "grammar.y"
{
}
break;
case 55:
-#line 694 "grammar.y"
+#line 785 "grammar.y"
{
yr_parser_emit(yyscanner, NOT, NULL);
}
break;
case 56:
-#line 698 "grammar.y"
+#line 789 "grammar.y"
{
yr_parser_emit(yyscanner, AND, NULL);
}
break;
case 57:
-#line 702 "grammar.y"
+#line 793 "grammar.y"
{
yr_parser_emit(yyscanner, OR, NULL);
}
break;
case 58:
-#line 706 "grammar.y"
+#line 797 "grammar.y"
{
yr_parser_emit(yyscanner, LT, NULL);
}
break;
case 59:
-#line 710 "grammar.y"
+#line 801 "grammar.y"
{
yr_parser_emit(yyscanner, GT, NULL);
}
break;
case 60:
-#line 714 "grammar.y"
+#line 805 "grammar.y"
{
yr_parser_emit(yyscanner, LE, NULL);
}
break;
case 61:
-#line 718 "grammar.y"
+#line 809 "grammar.y"
{
yr_parser_emit(yyscanner, GE, NULL);
}
break;
case 62:
-#line 722 "grammar.y"
+#line 813 "grammar.y"
{
yr_parser_emit(yyscanner, EQ, NULL);
}
break;
case 63:
-#line 726 "grammar.y"
+#line 817 "grammar.y"
{
yr_parser_emit(yyscanner, EQ, NULL);
}
break;
case 64:
-#line 730 "grammar.y"
+#line 821 "grammar.y"
{
yr_parser_emit(yyscanner, NEQ, NULL);
}
break;
case 65:
-#line 737 "grammar.y"
+#line 828 "grammar.y"
{
YARA_COMPILER* compiler = yyget_extra(yyscanner);
SIZED_STRING* sized_string = (yyvsp[(1) - (1)].sized_string);
@@ -2495,7 +2586,7 @@ yyreduce:
break;
case 66:
-#line 756 "grammar.y"
+#line 847 "grammar.y"
{
int result = yr_parser_reduce_external(
yyscanner,
@@ -2509,24 +2600,24 @@ yyreduce:
break;
case 67:
-#line 769 "grammar.y"
+#line 860 "grammar.y"
{ (yyval.integer) = INTEGER_SET_ENUMERATION; }
break;
case 68:
-#line 770 "grammar.y"
+#line 861 "grammar.y"
{ (yyval.integer) = INTEGER_SET_RANGE; }
break;
case 72:
-#line 783 "grammar.y"
+#line 874 "grammar.y"
{
yr_parser_emit_with_arg(yyscanner, PUSH, UNDEFINED, NULL);
}
break;
case 74:
-#line 788 "grammar.y"
+#line 879 "grammar.y"
{
yr_parser_emit_with_arg(yyscanner, PUSH, UNDEFINED, NULL);
yr_parser_emit_pushes_for_strings(yyscanner, "$*");
@@ -2534,7 +2625,7 @@ yyreduce:
break;
case 77:
-#line 799 "grammar.y"
+#line 890 "grammar.y"
{
yr_parser_emit_pushes_for_strings(yyscanner, (yyvsp[(1) - (1)].c_string));
yr_free((yyvsp[(1) - (1)].c_string));
@@ -2542,7 +2633,7 @@ yyreduce:
break;
case 78:
-#line 804 "grammar.y"
+#line 895 "grammar.y"
{
yr_parser_emit_pushes_for_strings(yyscanner, (yyvsp[(1) - (1)].c_string));
yr_free((yyvsp[(1) - (1)].c_string));
@@ -2550,84 +2641,84 @@ yyreduce:
break;
case 80:
-#line 812 "grammar.y"
+#line 903 "grammar.y"
{
yr_parser_emit_with_arg(yyscanner, PUSH, UNDEFINED, NULL);
}
break;
case 81:
-#line 816 "grammar.y"
+#line 907 "grammar.y"
{
yr_parser_emit_with_arg(yyscanner, PUSH, 1, NULL);
}
break;
case 83:
-#line 824 "grammar.y"
+#line 915 "grammar.y"
{
yr_parser_emit(yyscanner, SIZE, NULL);
}
break;
case 84:
-#line 828 "grammar.y"
+#line 919 "grammar.y"
{
yr_parser_emit(yyscanner, ENTRYPOINT, NULL);
}
break;
case 85:
-#line 832 "grammar.y"
+#line 923 "grammar.y"
{
yr_parser_emit(yyscanner, INT8, NULL);
}
break;
case 86:
-#line 836 "grammar.y"
+#line 927 "grammar.y"
{
yr_parser_emit(yyscanner, INT16, NULL);
}
break;
case 87:
-#line 840 "grammar.y"
+#line 931 "grammar.y"
{
yr_parser_emit(yyscanner, INT32, NULL);
}
break;
case 88:
-#line 844 "grammar.y"
+#line 935 "grammar.y"
{
yr_parser_emit(yyscanner, UINT8, NULL);
}
break;
case 89:
-#line 848 "grammar.y"
+#line 939 "grammar.y"
{
yr_parser_emit(yyscanner, UINT16, NULL);
}
break;
case 90:
-#line 852 "grammar.y"
+#line 943 "grammar.y"
{
yr_parser_emit(yyscanner, UINT32, NULL);
}
break;
case 91:
-#line 856 "grammar.y"
+#line 947 "grammar.y"
{
yr_parser_emit_with_arg(yyscanner, PUSH, (yyvsp[(1) - (1)].integer), NULL);
}
break;
case 92:
-#line 860 "grammar.y"
+#line 951 "grammar.y"
{
int result = yr_parser_reduce_string_identifier(
yyscanner,
@@ -2641,7 +2732,7 @@ yyreduce:
break;
case 93:
-#line 871 "grammar.y"
+#line 962 "grammar.y"
{
int result = yr_parser_reduce_string_identifier(
yyscanner,
@@ -2655,7 +2746,7 @@ yyreduce:
break;
case 94:
-#line 882 "grammar.y"
+#line 973 "grammar.y"
{
int result = yr_parser_emit_with_arg(yyscanner, PUSH, 1, NULL);
@@ -2672,15 +2763,21 @@ yyreduce:
break;
case 95:
-#line 896 "grammar.y"
+#line 987 "grammar.y"
{
YARA_COMPILER* compiler = yyget_extra(yyscanner);
EXTERNAL_VARIABLE* external;
+ int var_index;
+
+ var_index = yr_parser_lookup_loop_variable(yyscanner, (yyvsp[(1) - (1)].c_string));
- if (compiler->loop_identifier != NULL &&
- strcmp((yyvsp[(1) - (1)].c_string), compiler->loop_identifier) == 0)
+ if (var_index >= 0)
{
- yr_parser_emit(yyscanner, PUSH_A, NULL);
+ yr_parser_emit_with_arg(
+ yyscanner,
+ PUSH_M,
+ LOOP_LOCAL_VARS * var_index,
+ NULL);
}
else
{
@@ -2697,77 +2794,77 @@ yyreduce:
break;
case 96:
-#line 918 "grammar.y"
+#line 1015 "grammar.y"
{
yr_parser_emit(yyscanner, ADD, NULL);
}
break;
case 97:
-#line 922 "grammar.y"
+#line 1019 "grammar.y"
{
yr_parser_emit(yyscanner, SUB, NULL);
}
break;
case 98:
-#line 926 "grammar.y"
+#line 1023 "grammar.y"
{
yr_parser_emit(yyscanner, MUL, NULL);
}
break;
case 99:
-#line 930 "grammar.y"
+#line 1027 "grammar.y"
{
yr_parser_emit(yyscanner, DIV, NULL);
}
break;
case 100:
-#line 934 "grammar.y"
+#line 1031 "grammar.y"
{
yr_parser_emit(yyscanner, MOD, NULL);
}
break;
case 101:
-#line 938 "grammar.y"
+#line 1035 "grammar.y"
{
yr_parser_emit(yyscanner, XOR, NULL);
}
break;
case 102:
-#line 942 "grammar.y"
+#line 1039 "grammar.y"
{
yr_parser_emit(yyscanner, AND, NULL);
}
break;
case 103:
-#line 946 "grammar.y"
+#line 1043 "grammar.y"
{
yr_parser_emit(yyscanner, OR, NULL);
}
break;
case 104:
-#line 950 "grammar.y"
+#line 1047 "grammar.y"
{
yr_parser_emit(yyscanner, NEG, NULL);
}
break;
case 105:
-#line 954 "grammar.y"
+#line 1051 "grammar.y"
{
yr_parser_emit(yyscanner, SHL, NULL);
}
break;
case 106:
-#line 958 "grammar.y"
+#line 1055 "grammar.y"
{
yr_parser_emit(yyscanner, SHR, NULL);
}
@@ -2775,7 +2872,7 @@ yyreduce:
/* Line 1267 of yacc.c. */
-#line 2779 "grammar.c"
+#line 2876 "grammar.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -2989,7 +3086,7 @@ yyreturn:
}
-#line 968 "grammar.y"
+#line 1065 "grammar.y"
diff --git a/libyara/grammar.h b/libyara/grammar.h
index b16578c..0c3a4af 100644
--- a/libyara/grammar.h
+++ b/libyara/grammar.h
@@ -170,7 +170,7 @@
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
-#line 149 "grammar.y"
+#line 151 "grammar.y"
{
void* sized_string;
char* c_string;
diff --git a/libyara/grammar.y b/libyara/grammar.y
index 6bd21ae..8733895 100644
--- a/libyara/grammar.y
+++ b/libyara/grammar.y
@@ -38,6 +38,8 @@ limitations under the License.
#define INTEGER_SET_ENUMERATION 1
#define INTEGER_SET_RANGE 2
+
+
#define ERROR_IF(x) \
if (x) \
{ \
@@ -568,120 +570,209 @@ boolean_expression : '(' boolean_expression ')'
}
| _FOR_ for_expression _IDENTIFIER_ _IN_
{
- yr_parser_emit_with_arg(
+ YARA_COMPILER* compiler = yyget_extra(yyscanner);
+ int result = ERROR_SUCCESS;
+ int var_index;
+
+ if (compiler->loop_depth == MAX_LOOP_NESTING)
+ compiler->last_result = \
+ ERROR_LOOP_NESTING_LIMIT_EXCEEDED;
+
+ ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+
+ var_index = yr_parser_lookup_loop_variable(
+ yyscanner,
+ $3);
+
+ if (var_index >= 0)
+ {
+ yr_compiler_set_error_extra_info(
+ compiler,
+ $3);
+
+ compiler->last_result = \
+ ERROR_DUPLICATE_LOOP_IDENTIFIER;
+ }
+
+ ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+
+ // Push end-of-list marker
+ result = yr_parser_emit_with_arg(
yyscanner,
PUSH,
UNDEFINED,
NULL);
+
+ ERROR_IF(result != ERROR_SUCCESS);
}
integer_set ':'
{
YARA_COMPILER* compiler = yyget_extra(yyscanner);
+ int mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
+ int8_t* addr;
+
+ // Clear counter for number of expressions evaluating
+ // to TRUE.
+ yr_parser_emit_with_arg(
+ yyscanner, CLEAR_M, mem_offset + 1, NULL);
+
+ // Clear iterations counter
+ yr_parser_emit_with_arg(
+ yyscanner, CLEAR_M, mem_offset + 2, NULL);
if ($6 == INTEGER_SET_ENUMERATION)
{
- yr_parser_emit(yyscanner, CLEAR_B, NULL);
- yr_parser_emit(yyscanner, CLEAR_C, NULL);
- yr_parser_emit(
- yyscanner,
- POP_A,
- &compiler->loop_address);
+ // Pop the first integer
+ yr_parser_emit_with_arg(
+ yyscanner, POP_M, mem_offset, &addr);
}
else // INTEGER_SET_RANGE
{
- yr_parser_emit(yyscanner, POP_B, NULL);
- yr_parser_emit(yyscanner, POP_A, NULL);
- yr_parser_emit(yyscanner, POP_C, NULL);
- yr_parser_emit(yyscanner, CLEAR_C, NULL);
- yr_parser_emit_with_arg(yyscanner, PUSH, 1, NULL);
- yr_parser_emit(yyscanner, INCR_B, NULL);
- yr_parser_emit(yyscanner, PUSH_B, NULL);
- yr_parser_emit(yyscanner, PUSH_A, NULL);
- yr_parser_emit(
- yyscanner,
- SUB,
- &compiler->loop_address);
+ yr_parser_emit_with_arg(
+ yyscanner, POP_M, mem_offset + 3, &addr);
+
+ yr_parser_emit_with_arg(
+ yyscanner, POP_M, mem_offset, NULL);
}
- compiler->loop_address++;
- compiler->loop_identifier = $3;
+ compiler->loop_address[compiler->loop_depth] = addr;
+ compiler->loop_identifier[compiler->loop_depth] = $3;
+ compiler->loop_depth++;
}
'(' boolean_expression ')'
{
YARA_COMPILER* compiler = yyget_extra(yyscanner);
+ int mem_offset;
+
+ compiler->loop_depth--;
+ mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
+
+ yr_parser_emit_with_arg(
+ yyscanner, ADD_M, mem_offset + 1, NULL);
+
+ yr_parser_emit_with_arg(
+ yyscanner, INCR_M, mem_offset + 2, NULL);
if ($6 == INTEGER_SET_ENUMERATION)
{
- yr_parser_emit(yyscanner, INCR_C, NULL);
- yr_parser_emit_with_arg(yyscanner, PUSH, 1, NULL);
- yr_parser_emit(yyscanner, INCR_B, NULL);
- yr_parser_emit(yyscanner, POP_A, NULL);
-
yr_parser_emit_with_arg_reloc(
yyscanner,
- JNUNDEF_A,
- PTR_TO_UINT64(compiler->loop_address),
+ JNUNDEF,
+ PTR_TO_UINT64(
+ compiler->loop_address[compiler->loop_depth]),
NULL);
}
else // INTEGER_SET_RANGE
{
- yr_parser_emit(yyscanner, INCR_C, NULL);
- yr_parser_emit_with_arg(yyscanner, PUSH, 1, NULL);
- yr_parser_emit(yyscanner, INCR_A, NULL);
+ yr_parser_emit_with_arg(
+ yyscanner, INCR_M, mem_offset, NULL);
+
+ yr_parser_emit_with_arg(
+ yyscanner, PUSH_M, mem_offset, NULL);
+
+ yr_parser_emit_with_arg(
+ yyscanner, PUSH_M, mem_offset + 3, NULL);
yr_parser_emit_with_arg_reloc(
yyscanner,
- JLE_A_B,
- PTR_TO_UINT64(compiler->loop_address),
+ JLE,
+ PTR_TO_UINT64(
+ compiler->loop_address[compiler->loop_depth]),
NULL);
- yr_parser_emit(yyscanner, POP_B, NULL);
+ yr_parser_emit(yyscanner, POP, NULL);
+ yr_parser_emit(yyscanner, POP, NULL);
}
- yr_parser_emit(yyscanner, POP_A, NULL);
- yr_parser_emit(yyscanner, PNUNDEF_A_B, NULL);
- yr_parser_emit(yyscanner, PUSH_C, NULL);
- yr_parser_emit(yyscanner, LE, NULL);
+ // Pop end-of-list marker.
+ yr_parser_emit(yyscanner, POP, NULL);
+
+ // At this point the loop quantifier (any, all, 1, 2,..)
+ // is at the top of the stack. Check if the quantifier
+ // is undefined (meaning "all") and replace it with the
+ // iterations counter in that case.
+ yr_parser_emit_with_arg(
+ yyscanner, SWAPUNDEF, mem_offset + 2, NULL);
+
+ // Compare the loop quantifier with the number of
+ // expressions evaluating to TRUE.
+ yr_parser_emit_with_arg(
+ yyscanner, PUSH_M, mem_offset + 1, NULL);
- compiler->loop_identifier = NULL;
+ yr_parser_emit(yyscanner, LE, NULL);
+ compiler->loop_identifier[compiler->loop_depth] = NULL;
yr_free($3);
}
| _FOR_ for_expression _OF_ string_set ':'
{
YARA_COMPILER* compiler = yyget_extra(yyscanner);
+ int mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
+ int result = ERROR_SUCCESS;
+ int8_t* addr;
- yr_parser_emit(yyscanner, CLEAR_B, NULL);
- yr_parser_emit(yyscanner, CLEAR_C, NULL);
- yr_parser_emit(
- yyscanner,
- POP_A,
- &compiler->loop_address);
+ if (compiler->loop_depth == MAX_LOOP_NESTING)
+ compiler->last_result = \
+ ERROR_LOOP_NESTING_LIMIT_EXCEEDED;
+
+ ERROR_IF(compiler->last_result != ERROR_SUCCESS);
+
+ yr_parser_emit_with_arg(
+ yyscanner, CLEAR_M, mem_offset + 1, NULL);
- compiler->loop_address++;
- compiler->inside_for++;
+ yr_parser_emit_with_arg(
+ yyscanner, CLEAR_M, mem_offset + 2, NULL);
+
+ // Pop the first string.
+ yr_parser_emit_with_arg(
+ yyscanner, POP_M, mem_offset, &addr);
+
+ compiler->loop_address[compiler->loop_depth] = addr;
+ compiler->loop_depth++;
}
'(' boolean_expression ')'
{
YARA_COMPILER* compiler = yyget_extra(yyscanner);
+ int mem_offset;
- yr_parser_emit(yyscanner, INCR_C, NULL);
- yr_parser_emit_with_arg(yyscanner, PUSH, 1, NULL);
- yr_parser_emit(yyscanner, INCR_B, NULL);
- yr_parser_emit(yyscanner, POP_A, NULL);
+ compiler->loop_depth--;
+ mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
+
+ // Increment counter by the value returned by the
+ // boolean expression (0 or 1).
+ yr_parser_emit_with_arg(
+ yyscanner, ADD_M, mem_offset + 1, NULL);
+ // Increment iterations counter.
+ yr_parser_emit_with_arg(
+ yyscanner, INCR_M, mem_offset + 2, NULL);
+
+ // If next string is not undefined, go back to the
+ // begining of the loop.
yr_parser_emit_with_arg_reloc(
yyscanner,
- JNUNDEF_A,
- PTR_TO_UINT64(compiler->loop_address),
+ JNUNDEF,
+ PTR_TO_UINT64(
+ compiler->loop_address[compiler->loop_depth]),
NULL);
- yr_parser_emit(yyscanner, POP_A, NULL);
- yr_parser_emit(yyscanner, PNUNDEF_A_B, NULL);
- yr_parser_emit(yyscanner, PUSH_C, NULL);
+ // Pop end-of-list marker.
+ yr_parser_emit(yyscanner, POP, NULL);
+
+ // At this point the loop quantifier (any, all, 1, 2,..)
+ // is at top of the stack. Check if the quantifier is
+ // undefined (meaning "all") and replace it with the
+ // iterations counter in that case.
+ yr_parser_emit_with_arg(
+ yyscanner, SWAPUNDEF, mem_offset + 2, NULL);
+
+ // Compare the loop quantifier with the number of
+ // expressions evaluating to TRUE.
+ yr_parser_emit_with_arg(
+ yyscanner, PUSH_M, mem_offset + 1, NULL);
+
yr_parser_emit(yyscanner, LE, NULL);
- compiler->inside_for--;
}
| for_expression _OF_ string_set
{
@@ -896,11 +987,17 @@ expression : '(' expression ')'
{
YARA_COMPILER* compiler = yyget_extra(yyscanner);
EXTERNAL_VARIABLE* external;
+ int var_index;
+
+ var_index = yr_parser_lookup_loop_variable(yyscanner, $1);
- if (compiler->loop_identifier != NULL &&
- strcmp($1, compiler->loop_identifier) == 0)
+ if (var_index >= 0)
{
- yr_parser_emit(yyscanner, PUSH_A, NULL);
+ yr_parser_emit_with_arg(
+ yyscanner,
+ PUSH_M,
+ LOOP_LOCAL_VARS * var_index,
+ NULL);
}
else
{
diff --git a/libyara/parser.c b/libyara/parser.c
index b836196..b0281b3 100644
--- a/libyara/parser.c
+++ b/libyara/parser.c
@@ -720,9 +720,14 @@ int yr_parser_reduce_string_identifier(
if (strcmp(identifier, "$") == 0)
{
- if (compiler->inside_for > 0)
+ if (compiler->loop_depth > 0)
{
- yr_parser_emit(yyscanner, PUSH_A, NULL);
+ yr_parser_emit_with_arg(
+ yyscanner,
+ PUSH_M,
+ LOOP_LOCAL_VARS * (compiler->loop_depth - 1),
+ NULL);
+
yr_parser_emit(yyscanner, instruction, NULL);
if (instruction != SFOUND)
@@ -865,3 +870,20 @@ META* yr_parser_reduce_meta_declaration(
}
+int yr_parser_lookup_loop_variable(
+ yyscan_t yyscanner,
+ const char* identifier)
+{
+ YARA_COMPILER* compiler = yyget_extra(yyscanner);
+ int i;
+
+ for (i = 0; i < compiler->loop_depth; i++)
+ {
+ if (strcmp(identifier, compiler->loop_identifier[i]) == 0)
+ return i;
+ }
+
+ return -1;
+}
+
+
diff --git a/libyara/parser.h b/libyara/parser.h
index 6e5e141..0e853c4 100644
--- a/libyara/parser.h
+++ b/libyara/parser.h
@@ -93,4 +93,8 @@ int yr_parser_reduce_external(
const char* identifier,
int8_t intruction);
+int yr_parser_lookup_loop_variable(
+ yyscan_t yyscanner,
+ const char* identifier);
+
#endif
\ No newline at end of file
diff --git a/libyara/yara.h b/libyara/yara.h
index bd85d76..57859db 100644
--- a/libyara/yara.h
+++ b/libyara/yara.h
@@ -79,7 +79,11 @@ limitations under the License.
#define ERROR_INVALID_OR_CORRUPT_FILE 33
#define ERROR_EXEC_STACK_OVERFLOW 34
#define ERROR_TIMEOUT 35
+#define ERROR_LOOP_NESTING_LIMIT_EXCEEDED 36
+#define ERROR_DUPLICATE_LOOP_IDENTIFIER 37
+#define LOOP_LOCAL_VARS 4
+#define MAX_LOOP_NESTING 4
#define MAX_INCLUDE_DEPTH 16
#define LEX_BUF_SIZE 1024
@@ -438,10 +442,10 @@ typedef struct _YARA_COMPILER
int externals_count;
int namespaces_count;
- int8_t* loop_address;
- char* loop_identifier;
-
- int inside_for;
+ int8_t* loop_address[MAX_LOOP_NESTING];
+ char* loop_identifier[MAX_LOOP_NESTING];
+ int loop_depth;
+
int allow_includes;
char* file_name_stack[MAX_INCLUDE_DEPTH];
diff --git a/yara-python/tests.py b/yara-python/tests.py
index 0094289..7393ac2 100644
--- a/yara-python/tests.py
+++ b/yara-python/tests.py
@@ -165,6 +165,14 @@ class TestYara(unittest.TestCase):
'rule test { strings: $a = "ssi" condition: $a at 2 and $a at 5 }',
], 'mississippi')
+ def testOffset(self):
+
+ self.assertTrueRules([
+ 'rule test { strings: $a = "ssi" condition: @a == 2 }',
+ 'rule test { strings: $a = "ssi" condition: @a == @a[1] }',
+ 'rule test { strings: $a = "ssi" condition: @a[2] == 5 }'
+ ], 'mississippi')
+
def testOf(self):
self.assertTrueRules([
@@ -177,10 +185,15 @@ class TestYara(unittest.TestCase):
'rule test { strings: $a = "ssi" $b = "mis" $c = "oops" condition: all of them }'
], 'mississipi')
- def testForAll(self):
+ def testFor(self):
self.assertTrueRules([
- 'rule test { strings: $a = "ssi" condition: for all i in (1..#a) : (@a[i] >= 2 and @a[i] <= 5) }'
+ 'rule test { strings: $a = "ssi" condition: for all i in (1..#a) : (@a[i] >= 2 and @a[i] <= 5) }',
+ 'rule test { strings: $a = "ssi" $b = "mi" condition: for all i in (1..#a) : ( for all j in (1..#b) : (@a[i] >= @b[j])) }'
+ ], 'mississipi')
+
+ self.assertFalseRules([
+ 'rule test { strings: $a = "ssi" condition: for all i in (1..#a) : (@a[i] == 5) }',
], 'mississipi')
def testRE(self):
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/forensics/yara.git
More information about the forensics-changes
mailing list