Browse code

add YARA grammer and tokenizer files (gutted).

Steven Morgan authored on 2014/09/26 07:56:32
Showing 6 changed files
... ...
@@ -75,7 +75,8 @@ DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
75 75
 	$(top_srcdir)/docs/man/sigtool.1.in AUTHORS COPYING ChangeLog \
76 76
 	INSTALL NEWS config/compile config/config.guess \
77 77
 	config/config.rpath config/config.sub config/depcomp \
78
-	config/install-sh config/ltmain.sh config/missing
78
+	config/install-sh config/ltmain.sh config/missing \
79
+	config/ylwrap
79 80
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
80 81
 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \
81 82
 	$(top_srcdir)/m4/argz.m4 \
... ...
@@ -17,6 +17,7 @@
17 17
 #  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 18
 #  MA 02110-1301, USA.
19 19
 
20
+AM_YFLAGS = -d
20 21
 AM_CPPFLAGS = -I$(top_srcdir) -I@srcdir@/nsis $(LTDLINCL)
21 22
 AM_CFLAGS=@WERR_CFLAGS@
22 23
 lib_LTLIBRARIES =
... ...
@@ -442,6 +443,9 @@ libclamav_la_SOURCES = \
442 442
 	hostid.h \
443 443
 	openioc.c \
444 444
 	openioc.h \
445
+	yara_grammar.y \
446
+	yara_lexer.l \
447
+	yara_lexer.h \
445 448
 	yara_clam.h
446 449
 
447 450
 libclamav_la_SOURCES += bignum.h\
... ...
@@ -66,7 +66,8 @@ target_triplet = @target@
66 66
 @VERSIONSCRIPT_TRUE@am__append_6 = -Wl,@VERSIONSCRIPTFLAG@,@top_srcdir@/libclamav/libclamav.map
67 67
 subdir = libclamav
68 68
 DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \
69
-	$(srcdir)/Makefile.in
69
+	$(srcdir)/Makefile.in yara_grammar.c yara_grammar.h \
70
+	yara_lexer.c
70 71
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
71 72
 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \
72 73
 	$(top_srcdir)/m4/argz.m4 \
... ...
@@ -238,6 +239,7 @@ am_libclamav_la_OBJECTS = libclamav_la-matcher-ac.lo \
238 238
 	libclamav_la-asn1.lo libclamav_la-fpu.lo libclamav_la-stats.lo \
239 239
 	libclamav_la-www.lo libclamav_la-stats_json.lo \
240 240
 	libclamav_la-hostid.lo libclamav_la-openioc.lo \
241
+	libclamav_la-yara_grammar.lo libclamav_la-yara_lexer.lo \
241 242
 	libclamav_la-fp_add.lo libclamav_la-fp_add_d.lo \
242 243
 	libclamav_la-fp_addmod.lo libclamav_la-fp_cmp.lo \
243 244
 	libclamav_la-fp_cmp_d.lo libclamav_la-fp_cmp_mag.lo \
... ...
@@ -396,6 +398,21 @@ LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
396 396
 AM_V_CCLD = $(am__v_CCLD_@AM_V@)
397 397
 am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
398 398
 am__v_CCLD_0 = @echo "  CCLD  " $@;
399
+@MAINTAINER_MODE_FALSE@am__skiplex = test -f $@ ||
400
+LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS)
401
+LTLEXCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
402
+	$(LIBTOOLFLAGS) --mode=compile $(LEX) $(AM_LFLAGS) $(LFLAGS)
403
+AM_V_LEX = $(am__v_LEX_@AM_V@)
404
+am__v_LEX_ = $(am__v_LEX_@AM_DEFAULT_V@)
405
+am__v_LEX_0 = @echo "  LEX   " $@;
406
+YLWRAP = $(top_srcdir)/config/ylwrap
407
+@MAINTAINER_MODE_FALSE@am__skipyacc = test -f $@ ||
408
+YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS)
409
+LTYACCCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
410
+	$(LIBTOOLFLAGS) --mode=compile $(YACC) $(AM_YFLAGS) $(YFLAGS)
411
+AM_V_YACC = $(am__v_YACC_@AM_V@)
412
+am__v_YACC_ = $(am__v_YACC_@AM_DEFAULT_V@)
413
+am__v_YACC_0 = @echo "  YACC  " $@;
399 414
 AM_V_GEN = $(am__v_GEN_@AM_V@)
400 415
 am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
401 416
 am__v_GEN_0 = @echo "  GEN   " $@;
... ...
@@ -651,6 +668,7 @@ target_vendor = @target_vendor@
651 651
 top_build_prefix = @top_build_prefix@
652 652
 top_builddir = @top_builddir@
653 653
 top_srcdir = @top_srcdir@
654
+AM_YFLAGS = -d
654 655
 AM_CPPFLAGS = -I$(top_srcdir) -I@srcdir@/nsis $(LTDLINCL) \
655 656
 	$(am__append_1)
656 657
 AM_CFLAGS = @WERR_CFLAGS@
... ...
@@ -810,10 +828,10 @@ libclamav_la_SOURCES = matcher-ac.c matcher-ac.h matcher-bm.c \
810 810
 	iso9660.h arc4.c arc4.h rijndael.c rijndael.h crtmgr.c \
811 811
 	crtmgr.h asn1.c asn1.h fpu.c fpu.h stats.c stats.h www.c www.h \
812 812
 	stats_json.c stats_json.h hostid.c hostid.h openioc.c \
813
-	openioc.h yara_clam.h bignum.h bignum_fast.h \
814
-	tomsfastmath/addsub/fp_add.c tomsfastmath/addsub/fp_add_d.c \
815
-	tomsfastmath/addsub/fp_addmod.c tomsfastmath/addsub/fp_cmp.c \
816
-	tomsfastmath/addsub/fp_cmp_d.c \
813
+	openioc.h yara_grammar.y yara_lexer.l yara_lexer.h yara_clam.h \
814
+	bignum.h bignum_fast.h tomsfastmath/addsub/fp_add.c \
815
+	tomsfastmath/addsub/fp_add_d.c tomsfastmath/addsub/fp_addmod.c \
816
+	tomsfastmath/addsub/fp_cmp.c tomsfastmath/addsub/fp_cmp_d.c \
817 817
 	tomsfastmath/addsub/fp_cmp_mag.c tomsfastmath/addsub/fp_sub.c \
818 818
 	tomsfastmath/addsub/fp_sub_d.c tomsfastmath/addsub/fp_submod.c \
819 819
 	tomsfastmath/addsub/s_fp_add.c tomsfastmath/addsub/s_fp_sub.c \
... ...
@@ -884,7 +902,7 @@ all: $(BUILT_SOURCES)
884 884
 	$(MAKE) $(AM_MAKEFLAGS) all-recursive
885 885
 
886 886
 .SUFFIXES:
887
-.SUFFIXES: .c .lo .o .obj
887
+.SUFFIXES: .c .l .lo .o .obj .y
888 888
 $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
889 889
 	@for dep in $?; do \
890 890
 	  case '$(am__configure_deps)' in \
... ...
@@ -955,6 +973,9 @@ clean-noinstLTLIBRARIES:
955 955
 	  echo "rm -f \"$${dir}/so_locations\""; \
956 956
 	  rm -f "$${dir}/so_locations"; \
957 957
 	done
958
+yara_grammar.h: yara_grammar.c
959
+	@if test ! -f $@; then rm -f yara_grammar.c; else :; fi
960
+	@if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) yara_grammar.c; else :; fi
958 961
 libclamav.la: $(libclamav_la_OBJECTS) $(libclamav_la_DEPENDENCIES) $(EXTRA_libclamav_la_DEPENDENCIES) 
959 962
 	$(AM_V_CCLD)$(libclamav_la_LINK) -rpath $(libdir) $(libclamav_la_OBJECTS) $(libclamav_la_LIBADD) $(LIBS)
960 963
 libclamav_internal_utils.la: $(libclamav_internal_utils_la_OBJECTS) $(libclamav_internal_utils_la_DEPENDENCIES) $(EXTRA_libclamav_internal_utils_la_DEPENDENCIES) 
... ...
@@ -1213,6 +1234,8 @@ distclean-compile:
1213 1213
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-xar.Plo@am__quote@
1214 1214
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-xdp.Plo@am__quote@
1215 1215
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-xz_iface.Plo@am__quote@
1216
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-yara_grammar.Plo@am__quote@
1217
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-yara_lexer.Plo@am__quote@
1216 1218
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-yc.Plo@am__quote@
1217 1219
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_nocxx_la-bytecode_nojit.Plo@am__quote@
1218 1220
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unrar.Plo@am__quote@
... ...
@@ -2205,6 +2228,20 @@ libclamav_la-openioc.lo: openioc.c
2205 2205
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2206 2206
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-openioc.lo `test -f 'openioc.c' || echo '$(srcdir)/'`openioc.c
2207 2207
 
2208
+libclamav_la-yara_grammar.lo: yara_grammar.c
2209
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-yara_grammar.lo -MD -MP -MF $(DEPDIR)/libclamav_la-yara_grammar.Tpo -c -o libclamav_la-yara_grammar.lo `test -f 'yara_grammar.c' || echo '$(srcdir)/'`yara_grammar.c
2210
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-yara_grammar.Tpo $(DEPDIR)/libclamav_la-yara_grammar.Plo
2211
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='yara_grammar.c' object='libclamav_la-yara_grammar.lo' libtool=yes @AMDEPBACKSLASH@
2212
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2213
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-yara_grammar.lo `test -f 'yara_grammar.c' || echo '$(srcdir)/'`yara_grammar.c
2214
+
2215
+libclamav_la-yara_lexer.lo: yara_lexer.c
2216
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-yara_lexer.lo -MD -MP -MF $(DEPDIR)/libclamav_la-yara_lexer.Tpo -c -o libclamav_la-yara_lexer.lo `test -f 'yara_lexer.c' || echo '$(srcdir)/'`yara_lexer.c
2217
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-yara_lexer.Tpo $(DEPDIR)/libclamav_la-yara_lexer.Plo
2218
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='yara_lexer.c' object='libclamav_la-yara_lexer.lo' libtool=yes @AMDEPBACKSLASH@
2219
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2220
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-yara_lexer.lo `test -f 'yara_lexer.c' || echo '$(srcdir)/'`yara_lexer.c
2221
+
2208 2222
 libclamav_la-fp_add.lo: tomsfastmath/addsub/fp_add.c
2209 2223
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-fp_add.lo -MD -MP -MF $(DEPDIR)/libclamav_la-fp_add.Tpo -c -o libclamav_la-fp_add.lo `test -f 'tomsfastmath/addsub/fp_add.c' || echo '$(srcdir)/'`tomsfastmath/addsub/fp_add.c
2210 2224
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-fp_add.Tpo $(DEPDIR)/libclamav_la-fp_add.Plo
... ...
@@ -2996,6 +3033,12 @@ unrar_iface.lo: ../libclamunrar_iface/unrar_iface.c
2996 2996
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2997 2997
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unrar_iface.lo `test -f '../libclamunrar_iface/unrar_iface.c' || echo '$(srcdir)/'`../libclamunrar_iface/unrar_iface.c
2998 2998
 
2999
+.l.c:
3000
+	$(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
3001
+
3002
+.y.c:
3003
+	$(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE)
3004
+
2999 3005
 mostlyclean-libtool:
3000 3006
 	-rm -f *.lo
3001 3007
 
... ...
@@ -3254,6 +3297,9 @@ distclean-generic:
3254 3254
 maintainer-clean-generic:
3255 3255
 	@echo "This command is intended for maintainers to use"
3256 3256
 	@echo "it deletes files that may require special tools to rebuild."
3257
+	-rm -f yara_grammar.c
3258
+	-rm -f yara_grammar.h
3259
+	-rm -f yara_lexer.c
3257 3260
 	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
3258 3261
 clean: clean-recursive
3259 3262
 
3260 3263
new file mode 100644
... ...
@@ -0,0 +1,1919 @@
0
+/*
1
+ * YARA rule parser for ClamAV
2
+ * 
3
+ * Copyright (C) 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
4
+ * 
5
+ * Authors: Steven Morgan
6
+ * 
7
+ * This program is free software; you can redistribute it and/or modify it under
8
+ * the terms of the GNU General Public License version 2 as published by the
9
+ * Free Software Foundation.
10
+ * 
11
+ * This program is distributed in the hope that it will be useful, but WITHOUT
12
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14
+ * more details.
15
+ * 
16
+ * You should have received a copy of the GNU General Public License along with
17
+ * this program; if not, write to the Free Software Foundation, Inc., 51
18
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
+ */
20
+/* This file was originally derived from yara 3.1.0 libyara/parser.y and is
21
+   revised for running YARA rules in ClamAV. Following is the YARA copyright. */
22
+/*
23
+Copyright (c) 2007-2013. The YARA Authors. All Rights Reserved.
24
+
25
+Licensed under the Apache License, Version 2.0 (the "License");
26
+you may not use this file except in compliance with the License.
27
+You may obtain a copy of the License at
28
+
29
+   http://www.apache.org/licenses/LICENSE-2.0
30
+
31
+Unless required by applicable law or agreed to in writing, software
32
+distributed under the License is distributed on an "AS IS" BASIS,
33
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34
+See the License for the specific language governing permissions and
35
+limitations under the License.
36
+*/
37
+
38
+%{
39
+
40
+#include <assert.h>
41
+#include <stdio.h>
42
+#include <stdint.h>
43
+#include <string.h>
44
+#include <limits.h>
45
+#include <stddef.h>
46
+
47
+#ifdef REAL_YARA
48
+#include <yara/utils.h>
49
+#include <yara/compiler.h>
50
+#include <yara/object.h>
51
+#include <yara/sizedstr.h>
52
+#include <yara/exec.h>
53
+#include <yara/error.h>
54
+#include <yara/mem.h>
55
+#include <yara/lexer.h>
56
+#include <yara/parser.h>
57
+#else
58
+#define YYDEBUG 1 /* Set for development testing */
59
+#include "libclamav/yara_clam.h"
60
+#include "clamav-config.h"
61
+#endif
62
+
63
+#define YYERROR_VERBOSE
64
+
65
+#define INTEGER_SET_ENUMERATION   1
66
+#define INTEGER_SET_RANGE         2
67
+
68
+#define EXPRESSION_TYPE_BOOLEAN   1
69
+#define EXPRESSION_TYPE_INTEGER   2
70
+#define EXPRESSION_TYPE_STRING    3
71
+#define EXPRESSION_TYPE_REGEXP    4
72
+
73
+
74
+#define ERROR_IF(x) \
75
+    if (x) \
76
+    { \
77
+      yyerror(yyscanner, compiler, NULL); \
78
+      YYERROR; \
79
+    } \
80
+
81
+
82
+#define CHECK_TYPE_WITH_CLEANUP(actual_type, expected_type, op, cleanup) \
83
+    if (actual_type != expected_type) \
84
+    { \
85
+      switch(actual_type) \
86
+      { \
87
+        case EXPRESSION_TYPE_INTEGER: \
88
+          yr_compiler_set_error_extra_info( \
89
+              compiler, "wrong type \"integer\" for " op " operator"); \
90
+          break; \
91
+        case EXPRESSION_TYPE_STRING: \
92
+          yr_compiler_set_error_extra_info( \
93
+              compiler, "wrong type \"string\" for \"" op "\" operator"); \
94
+          break; \
95
+      } \
96
+      compiler->last_result = ERROR_WRONG_TYPE; \
97
+      cleanup; \
98
+      yyerror(yyscanner, compiler, NULL); \
99
+      YYERROR; \
100
+    }
101
+
102
+#define CHECK_TYPE(actual_type, expected_type, op) \
103
+    CHECK_TYPE_WITH_CLEANUP(actual_type, expected_type, op, ) \
104
+
105
+
106
+#define MSG(op)  "wrong type \"string\" for \"" op "\" operator"
107
+
108
+%}
109
+
110
+
111
+%expect 2   // expect 2 shift/reduce conflicts
112
+
113
+%debug
114
+%name-prefix="yara_yy"
115
+%pure-parser
116
+%parse-param {void *yyscanner}
117
+%parse-param {YR_COMPILER* compiler}
118
+%lex-param {yyscan_t yyscanner}
119
+%lex-param {YR_COMPILER* compiler}
120
+
121
+%token _RULE_
122
+%token _PRIVATE_
123
+%token _GLOBAL_
124
+%token _META_
125
+%token <string> _STRINGS_
126
+%token _CONDITION_
127
+%token <c_string> _IDENTIFIER_
128
+%token <c_string> _STRING_IDENTIFIER_
129
+%token <c_string> _STRING_COUNT_
130
+%token <c_string> _STRING_OFFSET_
131
+%token <c_string> _STRING_IDENTIFIER_WITH_WILDCARD_
132
+%token <integer> _NUMBER_
133
+%token <sized_string> _TEXT_STRING_
134
+%token <sized_string> _HEX_STRING_
135
+%token <sized_string> _REGEXP_
136
+%token _ASCII_
137
+%token _WIDE_
138
+%token _NOCASE_
139
+%token _FULLWORD_
140
+%token _AT_
141
+%token _FILESIZE_
142
+%token _ENTRYPOINT_
143
+%token _ALL_
144
+%token _ANY_
145
+%token _IN_
146
+%token _OF_
147
+%token _FOR_
148
+%token _THEM_
149
+%token _INT8_
150
+%token _INT16_
151
+%token _INT32_
152
+%token _UINT8_
153
+%token _UINT16_
154
+%token _UINT32_
155
+%token _MATCHES_
156
+%token _CONTAINS_
157
+%token _IMPORT_
158
+
159
+%token _TRUE_
160
+%token _FALSE_
161
+
162
+%left _OR_
163
+%left _AND_
164
+%left '&' '|' '^'
165
+%left _LT_ _LE_ _GT_ _GE_ _EQ_ _NEQ_ _IS_
166
+%left _SHIFT_LEFT_ _SHIFT_RIGHT_
167
+%left '+' '-'
168
+%left '*' '\\' '%'
169
+%right _NOT_
170
+%right '~'
171
+
172
+%type <string> strings
173
+%type <string> string_declaration
174
+%type <string> string_declarations
175
+
176
+%type <meta> meta
177
+%type <meta> meta_declaration
178
+%type <meta> meta_declarations
179
+
180
+%type <c_string> tags
181
+%type <c_string> tag_list
182
+
183
+%type <integer> string_modifier
184
+%type <integer> string_modifiers
185
+
186
+%type <integer> integer_set
187
+
188
+%type <integer> rule_modifier
189
+%type <integer> rule_modifiers
190
+
191
+%type <object> identifier
192
+
193
+%type <expression_type> primary_expression
194
+%type <expression_type> boolean_expression
195
+%type <expression_type> expression
196
+%type <expression_type> regexp
197
+
198
+%type <c_string> arguments_list
199
+
200
+
201
+%destructor { yr_free($$); } _IDENTIFIER_
202
+%destructor { yr_free($$); } _STRING_IDENTIFIER_
203
+%destructor { yr_free($$); } _STRING_COUNT_
204
+%destructor { yr_free($$); } _STRING_OFFSET_
205
+%destructor { yr_free($$); } _STRING_IDENTIFIER_WITH_WILDCARD_
206
+%destructor { yr_free($$); } _TEXT_STRING_
207
+%destructor { yr_free($$); } _HEX_STRING_
208
+%destructor { yr_free($$); } _REGEXP_
209
+
210
+%union {
211
+  SIZED_STRING*   sized_string;
212
+  char*           c_string;
213
+  int8_t          expression_type;
214
+  int64_t         integer;
215
+  YR_STRING*      string;
216
+  YR_META*        meta;
217
+    //  YR_OBJECT*      object;
218
+}
219
+
220
+
221
+%%
222
+
223
+rules
224
+    : /* empty */
225
+    | rules rule
226
+    | rules import
227
+    | rules error rule      /* on error skip until next rule..*/
228
+    | rules error 'include' /* .. or include statement */
229
+    ;
230
+
231
+
232
+import
233
+    : _IMPORT_ _TEXT_STRING_
234
+      {
235
+#ifdef REAL_YARA
236
+        int result = yr_parser_reduce_import(yyscanner, $2);
237
+
238
+        yr_free($2);
239
+
240
+        ERROR_IF(result != ERROR_SUCCESS);
241
+#endif
242
+      }
243
+    ;
244
+
245
+
246
+rule
247
+    : rule_modifiers _RULE_ _IDENTIFIER_ tags '{' meta strings condition '}'
248
+      {
249
+#ifdef REAL_YARA
250
+        int result = yr_parser_reduce_rule_declaration(
251
+            yyscanner,
252
+            $1,
253
+            $3,
254
+            $4,
255
+            $7,
256
+            $6);
257
+
258
+        yr_free($3);
259
+
260
+        ERROR_IF(result != ERROR_SUCCESS);
261
+#endif
262
+      }
263
+    ;
264
+
265
+
266
+meta
267
+    : /* empty */
268
+      {
269
+#ifdef REAL_YARA
270
+        $$ = NULL;
271
+#endif
272
+      }
273
+    | _META_ ':' meta_declarations
274
+      {
275
+#ifdef REAL_YARA
276
+        // Each rule have a list of meta-data info, consisting in a
277
+        // sequence of YR_META structures. The last YR_META structure does
278
+        // not represent a real meta-data, it's just a end-of-list marker
279
+        // identified by a specific type (META_TYPE_NULL). Here we
280
+        // write the end-of-list marker.
281
+
282
+        YR_META null_meta;
283
+
284
+        memset(&null_meta, 0xFF, sizeof(YR_META));
285
+        null_meta.type = META_TYPE_NULL;
286
+
287
+        compiler->last_result = yr_arena_write_data(
288
+            compiler->metas_arena,
289
+            &null_meta,
290
+            sizeof(YR_META),
291
+            NULL);
292
+
293
+        $$ = $3;
294
+
295
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
296
+#endif
297
+      }
298
+    ;
299
+
300
+
301
+strings
302
+    : /* empty */
303
+      {
304
+#ifdef REAL_YARA
305
+        $$ = NULL;
306
+        compiler->current_rule_strings = $$;
307
+#endif
308
+      }
309
+    | _STRINGS_ ':' string_declarations
310
+      {
311
+#ifdef REAL_YARA
312
+        // Each rule have a list of strings, consisting in a sequence
313
+        // of YR_STRING structures. The last YR_STRING structure does not
314
+        // represent a real string, it's just a end-of-list marker
315
+        // identified by a specific flag (STRING_FLAGS_NULL). Here we
316
+        // write the end-of-list marker.
317
+
318
+        YR_STRING null_string;
319
+
320
+        memset(&null_string, 0xFF, sizeof(YR_STRING));
321
+        null_string.g_flags = STRING_GFLAGS_NULL;
322
+
323
+        compiler->last_result = yr_arena_write_data(
324
+            compiler->strings_arena,
325
+            &null_string,
326
+            sizeof(YR_STRING),
327
+            NULL);
328
+
329
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
330
+
331
+        compiler->current_rule_strings = $3;
332
+        $$ = $3;
333
+#endif
334
+      }
335
+    ;
336
+
337
+
338
+condition
339
+    : _CONDITION_ ':' boolean_expression
340
+    ;
341
+
342
+
343
+rule_modifiers
344
+    : /* empty */                      { $$ = 0;  }
345
+    | rule_modifiers rule_modifier     { $$ = $1 | $2; }
346
+    ;
347
+
348
+
349
+rule_modifier
350
+    : _PRIVATE_      { $$ = RULE_GFLAGS_PRIVATE; }
351
+    | _GLOBAL_       { $$ = RULE_GFLAGS_GLOBAL; }
352
+    ;
353
+
354
+
355
+tags
356
+    : /* empty */
357
+      {
358
+#ifdef REAL_YARA
359
+        $$ = NULL;
360
+#endif
361
+      }
362
+    | ':' tag_list
363
+      {
364
+#ifdef REAL_YARA
365
+        // Tags list is represented in the arena as a sequence
366
+        // of null-terminated strings, the sequence ends with an
367
+        // additional null character. Here we write the ending null
368
+        //character. Example: tag1\0tag2\0tag3\0\0
369
+
370
+        compiler->last_result = yr_arena_write_string(
371
+            yyget_extra(yyscanner)->sz_arena, "", NULL);
372
+
373
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
374
+
375
+        $$ = $2;
376
+#endif
377
+      }
378
+    ;
379
+
380
+
381
+tag_list
382
+    : _IDENTIFIER_
383
+      {
384
+#ifdef REAL_YARA
385
+        char* identifier;
386
+
387
+        compiler->last_result = yr_arena_write_string(
388
+            yyget_extra(yyscanner)->sz_arena, $1, &identifier);
389
+
390
+        yr_free($1);
391
+
392
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
393
+
394
+        $$ = identifier;
395
+#endif
396
+      }
397
+    | tag_list _IDENTIFIER_
398
+      {
399
+#ifdef REAL_YARA
400
+        char* tag_name = $1;
401
+        size_t tag_length = tag_name != NULL ? strlen(tag_name) : 0;
402
+
403
+        while (tag_length > 0)
404
+        {
405
+          if (strcmp(tag_name, $2) == 0)
406
+          {
407
+            yr_compiler_set_error_extra_info(compiler, tag_name);
408
+            compiler->last_result = ERROR_DUPLICATE_TAG_IDENTIFIER;
409
+            break;
410
+          }
411
+
412
+          tag_name = yr_arena_next_address(
413
+              yyget_extra(yyscanner)->sz_arena,
414
+              tag_name,
415
+              tag_length + 1);
416
+
417
+          tag_length = tag_name != NULL ? strlen(tag_name) : 0;
418
+        }
419
+
420
+        if (compiler->last_result == ERROR_SUCCESS)
421
+          compiler->last_result = yr_arena_write_string(
422
+              yyget_extra(yyscanner)->sz_arena, $2, NULL);
423
+
424
+        yr_free($2);
425
+
426
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
427
+
428
+        $$ = $1;
429
+#endif
430
+      }
431
+    ;
432
+
433
+
434
+
435
+meta_declarations
436
+    : meta_declaration                    {  $$ = $1; }
437
+    | meta_declarations meta_declaration  {  $$ = $1; }
438
+    ;
439
+
440
+
441
+meta_declaration
442
+    : _IDENTIFIER_ '=' _TEXT_STRING_
443
+      {
444
+#ifdef REAL_YARA
445
+        SIZED_STRING* sized_string = $3;
446
+
447
+        $$ = yr_parser_reduce_meta_declaration(
448
+            yyscanner,
449
+            META_TYPE_STRING,
450
+            $1,
451
+            sized_string->c_string,
452
+            0);
453
+
454
+        yr_free($1);
455
+        yr_free($3);
456
+
457
+        ERROR_IF($$ == NULL);
458
+#endif
459
+      }
460
+    | _IDENTIFIER_ '=' _NUMBER_
461
+      {
462
+#ifdef REAL_YARA
463
+        $$ = yr_parser_reduce_meta_declaration(
464
+            yyscanner,
465
+            META_TYPE_INTEGER,
466
+            $1,
467
+            NULL,
468
+            $3);
469
+
470
+        yr_free($1);
471
+
472
+        ERROR_IF($$ == NULL);
473
+#endif
474
+      }
475
+    | _IDENTIFIER_ '=' _TRUE_
476
+      {
477
+#ifdef REAL_YARA
478
+        $$ = yr_parser_reduce_meta_declaration(
479
+            yyscanner,
480
+            META_TYPE_BOOLEAN,
481
+            $1,
482
+            NULL,
483
+            TRUE);
484
+
485
+        yr_free($1);
486
+
487
+        ERROR_IF($$ == NULL);
488
+#endif
489
+      }
490
+    | _IDENTIFIER_ '=' _FALSE_
491
+      {
492
+#ifdef REAL_YARA
493
+        $$ = yr_parser_reduce_meta_declaration(
494
+            yyscanner,
495
+            META_TYPE_BOOLEAN,
496
+            $1,
497
+            NULL,
498
+            FALSE);
499
+
500
+        yr_free($1);
501
+
502
+        ERROR_IF($$ == NULL);
503
+#endif
504
+      }
505
+    ;
506
+
507
+
508
+string_declarations
509
+    : string_declaration                      { $$ = $1; }
510
+    | string_declarations string_declaration  { $$ = $1; }
511
+    ;
512
+
513
+
514
+string_declaration
515
+    : _STRING_IDENTIFIER_ '=' _TEXT_STRING_ string_modifiers
516
+      {
517
+#ifdef REAL_YARA
518
+        $$ = yr_parser_reduce_string_declaration(
519
+            yyscanner,
520
+            $4,
521
+            $1,
522
+            $3);
523
+
524
+        yr_free($1);
525
+        yr_free($3);
526
+
527
+        ERROR_IF($$ == NULL);
528
+#endif
529
+      }
530
+    | _STRING_IDENTIFIER_ '='
531
+      {
532
+#ifdef REAL_YARA
533
+        compiler->error_line = yyget_lineno(yyscanner);
534
+#endif
535
+      }
536
+      _REGEXP_ string_modifiers
537
+      {
538
+#ifdef REAL_YARA
539
+        $$ = yr_parser_reduce_string_declaration(
540
+            yyscanner,
541
+            $5 | STRING_GFLAGS_REGEXP,
542
+            $1,
543
+            $4);
544
+
545
+        yr_free($1);
546
+        yr_free($4);
547
+
548
+        ERROR_IF($$ == NULL);
549
+#endif
550
+      }
551
+    | _STRING_IDENTIFIER_ '=' _HEX_STRING_
552
+      {
553
+#ifdef REAL_YARA
554
+        $$ = yr_parser_reduce_string_declaration(
555
+            yyscanner,
556
+            STRING_GFLAGS_HEXADECIMAL,
557
+            $1,
558
+            $3);
559
+
560
+        yr_free($1);
561
+        yr_free($3);
562
+
563
+        ERROR_IF($$ == NULL);
564
+#endif
565
+      }
566
+    ;
567
+
568
+
569
+string_modifiers
570
+    : /* empty */                         { $$ = 0; }
571
+    | string_modifiers string_modifier    { $$ = $1 | $2; }
572
+    ;
573
+
574
+
575
+string_modifier
576
+    : _WIDE_        { $$ = STRING_GFLAGS_WIDE; }
577
+    | _ASCII_       { $$ = STRING_GFLAGS_ASCII; }
578
+    | _NOCASE_      { $$ = STRING_GFLAGS_NO_CASE; }
579
+    | _FULLWORD_    { $$ = STRING_GFLAGS_FULL_WORD; }
580
+    ;
581
+
582
+
583
+identifier
584
+    : _IDENTIFIER_
585
+      {
586
+#ifdef REAL_YARA
587
+        YR_OBJECT* object = NULL;
588
+        YR_RULE* rule;
589
+
590
+        char* id;
591
+        char* ns = NULL;
592
+
593
+        int var_index;
594
+
595
+        var_index = yr_parser_lookup_loop_variable(yyscanner, $1);
596
+
597
+        if (var_index >= 0)
598
+        {
599
+         compiler->last_result = yr_parser_emit_with_arg(
600
+            yyscanner,
601
+            OP_PUSH_M,
602
+            LOOP_LOCAL_VARS * var_index,
603
+            NULL);
604
+
605
+          $$ = (YR_OBJECT*) -1;
606
+        }
607
+        else
608
+        {
609
+          // Search for identifier within the global namespace, where the
610
+          // externals variables reside.
611
+
612
+          object = (YR_OBJECT*) yr_hash_table_lookup(
613
+                compiler->objects_table,
614
+                $1,
615
+                NULL);
616
+
617
+          if (object == NULL)
618
+          {
619
+            // If not found, search within the current namespace.
620
+
621
+            ns = compiler->current_namespace->name;
622
+            object = (YR_OBJECT*) yr_hash_table_lookup(
623
+                compiler->objects_table,
624
+                $1,
625
+                ns);
626
+          }
627
+
628
+          if (object != NULL)
629
+          {
630
+            compiler->last_result = yr_arena_write_string(
631
+                compiler->sz_arena,
632
+                $1,
633
+                &id);
634
+
635
+            if (compiler->last_result == ERROR_SUCCESS)
636
+              compiler->last_result = yr_parser_emit_with_arg_reloc(
637
+                  yyscanner,
638
+                  OP_OBJ_LOAD,
639
+                  PTR_TO_UINT64(id),
640
+                  NULL);
641
+
642
+            $$ = object;
643
+          }
644
+          else
645
+          {
646
+            rule = (YR_RULE*) yr_hash_table_lookup(
647
+                compiler->rules_table,
648
+                $1,
649
+                compiler->current_namespace->name);
650
+
651
+            if (rule != NULL)
652
+            {
653
+              compiler->last_result = yr_parser_emit_with_arg_reloc(
654
+                  yyscanner,
655
+                  OP_PUSH_RULE,
656
+                  PTR_TO_UINT64(rule),
657
+                  NULL);
658
+            }
659
+            else
660
+            {
661
+              yr_compiler_set_error_extra_info(compiler, $1);
662
+              compiler->last_result = ERROR_UNDEFINED_IDENTIFIER;
663
+            }
664
+
665
+            $$ = (YR_OBJECT*) -2;
666
+          }
667
+        }
668
+
669
+        yr_free($1);
670
+
671
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
672
+#endif
673
+      }
674
+    | identifier '.' _IDENTIFIER_
675
+      {
676
+#ifdef REAL_YARA
677
+        YR_OBJECT* object = $1;
678
+        YR_OBJECT* field = NULL;
679
+
680
+        char* ident;
681
+
682
+        if (object != NULL &&
683
+            object != (YR_OBJECT*) -1 &&    // not a loop variable identifier
684
+            object != (YR_OBJECT*) -2 &&    // not a rule identifier
685
+            object->type == OBJECT_TYPE_STRUCTURE)
686
+        {
687
+          field = yr_object_lookup_field(object, $3);
688
+
689
+          if (field != NULL)
690
+          {
691
+            compiler->last_result = yr_arena_write_string(
692
+              compiler->sz_arena,
693
+              $3,
694
+              &ident);
695
+
696
+            if (compiler->last_result == ERROR_SUCCESS)
697
+              compiler->last_result = yr_parser_emit_with_arg_reloc(
698
+                  yyscanner,
699
+                  OP_OBJ_FIELD,
700
+                  PTR_TO_UINT64(ident),
701
+                  NULL);
702
+          }
703
+          else
704
+          {
705
+            yr_compiler_set_error_extra_info(compiler, $3);
706
+            compiler->last_result = ERROR_INVALID_FIELD_NAME;
707
+          }
708
+        }
709
+        else
710
+        {
711
+          yr_compiler_set_error_extra_info(
712
+              compiler,
713
+              object->identifier);
714
+
715
+          compiler->last_result = ERROR_NOT_A_STRUCTURE;
716
+        }
717
+
718
+        $$ = field;
719
+
720
+        yr_free($3);
721
+
722
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
723
+#endif
724
+      }
725
+    | identifier '[' primary_expression ']'
726
+      {
727
+#ifdef REAL_YARA
728
+        if ($1 != NULL && $1->type == OBJECT_TYPE_ARRAY)
729
+        {
730
+          compiler->last_result = yr_parser_emit(
731
+              yyscanner,
732
+              OP_INDEX_ARRAY,
733
+              NULL);
734
+
735
+          $$ = ((YR_OBJECT_ARRAY*) $1)->items->objects[0];
736
+        }
737
+        else
738
+        {
739
+          yr_compiler_set_error_extra_info(
740
+              compiler,
741
+              $1->identifier);
742
+
743
+          compiler->last_result = ERROR_NOT_AN_ARRAY;
744
+        }
745
+
746
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
747
+#endif
748
+      }
749
+
750
+    | identifier '(' arguments_list ')'
751
+      {
752
+#ifdef REAL_YARA
753
+        int args_count;
754
+
755
+        if ($1 != NULL && $1->type == OBJECT_TYPE_FUNCTION)
756
+        {
757
+          compiler->last_result = yr_parser_check_types(
758
+              compiler, (YR_OBJECT_FUNCTION*) $1, $3);
759
+
760
+          if (compiler->last_result == ERROR_SUCCESS)
761
+          {
762
+            args_count = strlen($3);
763
+
764
+            compiler->last_result = yr_parser_emit_with_arg(
765
+                yyscanner,
766
+                OP_CALL,
767
+                args_count,
768
+                NULL);
769
+          }
770
+
771
+          $$ = ((YR_OBJECT_FUNCTION*) $1)->return_obj;
772
+        }
773
+        else
774
+        {
775
+          yr_compiler_set_error_extra_info(
776
+              compiler,
777
+              $1->identifier);
778
+
779
+          compiler->last_result = ERROR_NOT_A_FUNCTION;
780
+        }
781
+
782
+        yr_free($3);
783
+
784
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
785
+#endif
786
+      }
787
+    ;
788
+
789
+
790
+arguments_list
791
+    : /* empty */
792
+      {
793
+#ifdef REAL_YARA
794
+        $$ = yr_strdup("");
795
+#endif
796
+      }
797
+    | expression
798
+      {
799
+#ifdef REAL_YARA
800
+        $$ = yr_malloc(MAX_FUNCTION_ARGS + 1);
801
+
802
+        switch($1)
803
+        {
804
+          case EXPRESSION_TYPE_INTEGER:
805
+            strlcpy($$, "i", MAX_FUNCTION_ARGS);
806
+            break;
807
+          case EXPRESSION_TYPE_BOOLEAN:
808
+            strlcpy($$, "b", MAX_FUNCTION_ARGS);
809
+            break;
810
+          case EXPRESSION_TYPE_STRING:
811
+            strlcpy($$, "s", MAX_FUNCTION_ARGS);
812
+            break;
813
+          case EXPRESSION_TYPE_REGEXP:
814
+            strlcpy($$, "r", MAX_FUNCTION_ARGS);
815
+            break;
816
+        }
817
+
818
+        ERROR_IF($$ == NULL);
819
+#endif
820
+      }
821
+    | arguments_list ',' expression
822
+      {
823
+#ifdef REAL_YARA
824
+        if (strlen($1) == MAX_FUNCTION_ARGS)
825
+        {
826
+          compiler->last_result = ERROR_TOO_MANY_ARGUMENTS;
827
+        }
828
+        else
829
+        {
830
+          switch($3)
831
+          {
832
+            case EXPRESSION_TYPE_INTEGER:
833
+              strlcat($1, "i", MAX_FUNCTION_ARGS);
834
+              break;
835
+            case EXPRESSION_TYPE_BOOLEAN:
836
+              strlcat($1, "b", MAX_FUNCTION_ARGS);
837
+              break;
838
+            case EXPRESSION_TYPE_STRING:
839
+              strlcat($1, "s", MAX_FUNCTION_ARGS);
840
+              break;
841
+            case EXPRESSION_TYPE_REGEXP:
842
+              strlcat($1, "r", MAX_FUNCTION_ARGS);
843
+              break;
844
+          }
845
+        }
846
+
847
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
848
+
849
+        $$ = $1;
850
+#endif
851
+      }
852
+    ;
853
+
854
+
855
+regexp
856
+    : _REGEXP_
857
+      {
858
+#ifdef REAL_YARA
859
+        SIZED_STRING* sized_string = $1;
860
+        RE* re;
861
+        RE_ERROR error;
862
+
863
+        int re_flags = 0;
864
+
865
+        if (sized_string->flags & SIZED_STRING_FLAGS_NO_CASE)
866
+          re_flags |= RE_FLAGS_NO_CASE;
867
+
868
+        if (sized_string->flags & SIZED_STRING_FLAGS_DOT_ALL)
869
+          re_flags |= RE_FLAGS_DOT_ALL;
870
+
871
+        compiler->last_result = yr_re_compile(
872
+            sized_string->c_string,
873
+            re_flags,
874
+            compiler->re_code_arena,
875
+            &re,
876
+            &error);
877
+
878
+        yr_free($1);
879
+
880
+        if (compiler->last_result == ERROR_INVALID_REGULAR_EXPRESSION)
881
+          yr_compiler_set_error_extra_info(compiler, error.message);
882
+
883
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
884
+
885
+        if (compiler->last_result == ERROR_SUCCESS)
886
+          compiler->last_result = yr_parser_emit_with_arg_reloc(
887
+              yyscanner,
888
+              OP_PUSH,
889
+              PTR_TO_UINT64(re->root_node->forward_code),
890
+              NULL);
891
+
892
+        yr_re_destroy(re);
893
+
894
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
895
+
896
+        $$ = EXPRESSION_TYPE_REGEXP;
897
+#endif
898
+      }
899
+    ;
900
+
901
+
902
+boolean_expression
903
+    : expression
904
+      {
905
+#ifdef REAL_YARA
906
+        if ($1 == EXPRESSION_TYPE_STRING)
907
+        {
908
+          compiler->last_result = yr_parser_emit(
909
+              yyscanner,
910
+              OP_SZ_TO_BOOL,
911
+              NULL);
912
+
913
+          ERROR_IF(compiler->last_result != ERROR_SUCCESS);
914
+        }
915
+
916
+
917
+        $$ = EXPRESSION_TYPE_BOOLEAN;
918
+#endif
919
+      }
920
+    ;
921
+
922
+expression
923
+    : _TRUE_
924
+      {
925
+#ifdef REAL_YARA
926
+        compiler->last_result = yr_parser_emit_with_arg(
927
+            yyscanner, OP_PUSH, 1, NULL);
928
+
929
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
930
+
931
+        $$ = EXPRESSION_TYPE_BOOLEAN;
932
+#endif
933
+      }
934
+    | _FALSE_
935
+      {
936
+#ifdef REAL_YARA
937
+        compiler->last_result = yr_parser_emit_with_arg(
938
+            yyscanner, OP_PUSH, 0, NULL);
939
+
940
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
941
+
942
+        $$ = EXPRESSION_TYPE_BOOLEAN;
943
+#endif
944
+      }
945
+    | primary_expression _MATCHES_ regexp
946
+      {
947
+#ifdef REAL_YARA
948
+        CHECK_TYPE($1, EXPRESSION_TYPE_STRING, "matches");
949
+        CHECK_TYPE($3, EXPRESSION_TYPE_REGEXP, "matches");
950
+
951
+        if (compiler->last_result == ERROR_SUCCESS)
952
+          compiler->last_result = yr_parser_emit(
953
+              yyscanner,
954
+              OP_MATCHES,
955
+              NULL);
956
+
957
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
958
+
959
+        $$ = EXPRESSION_TYPE_BOOLEAN;
960
+#endif
961
+      }
962
+    | primary_expression _CONTAINS_ primary_expression
963
+      {
964
+#ifdef REAL_YARA
965
+        CHECK_TYPE($1, EXPRESSION_TYPE_STRING, "contains");
966
+        CHECK_TYPE($3, EXPRESSION_TYPE_STRING, "contains");
967
+
968
+        compiler->last_result = yr_parser_emit(
969
+            yyscanner,
970
+            OP_CONTAINS,
971
+            NULL);
972
+
973
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
974
+
975
+        $$ = EXPRESSION_TYPE_BOOLEAN;
976
+#endif
977
+      }
978
+    | _STRING_IDENTIFIER_
979
+      {
980
+#ifdef REAL_YARA
981
+        int result = yr_parser_reduce_string_identifier(
982
+            yyscanner,
983
+            $1,
984
+            OP_STR_FOUND);
985
+
986
+        yr_free($1);
987
+
988
+        ERROR_IF(result != ERROR_SUCCESS);
989
+
990
+        $$ = EXPRESSION_TYPE_BOOLEAN;
991
+#endif
992
+      }
993
+    | _STRING_IDENTIFIER_ _AT_ primary_expression
994
+      {
995
+#ifdef REAL_YARA
996
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "at");
997
+
998
+        compiler->last_result = yr_parser_reduce_string_identifier(
999
+            yyscanner,
1000
+            $1,
1001
+            OP_STR_FOUND_AT);
1002
+
1003
+        yr_free($1);
1004
+
1005
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1006
+
1007
+        $$ = EXPRESSION_TYPE_BOOLEAN;
1008
+#endif
1009
+      }
1010
+    | _STRING_IDENTIFIER_ _IN_ range
1011
+      {
1012
+#ifdef REAL_YARA
1013
+        compiler->last_result = yr_parser_reduce_string_identifier(
1014
+            yyscanner,
1015
+            $1,
1016
+            OP_STR_FOUND_IN);
1017
+
1018
+        yr_free($1);
1019
+
1020
+        ERROR_IF(compiler->last_result!= ERROR_SUCCESS);
1021
+
1022
+        $$ = EXPRESSION_TYPE_BOOLEAN;
1023
+#endif
1024
+      }
1025
+    | _FOR_ for_expression _IDENTIFIER_ _IN_
1026
+      {
1027
+#ifdef REAL_YARA
1028
+        int var_index;
1029
+
1030
+        if (compiler->loop_depth == MAX_LOOP_NESTING)
1031
+          compiler->last_result = \
1032
+              ERROR_LOOP_NESTING_LIMIT_EXCEEDED;
1033
+
1034
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1035
+
1036
+        var_index = yr_parser_lookup_loop_variable(
1037
+            yyscanner,
1038
+            $3);
1039
+
1040
+        if (var_index >= 0)
1041
+        {
1042
+          yr_compiler_set_error_extra_info(
1043
+              compiler,
1044
+              $3);
1045
+
1046
+          compiler->last_result = \
1047
+              ERROR_DUPLICATE_LOOP_IDENTIFIER;
1048
+        }
1049
+
1050
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1051
+
1052
+        // Push end-of-list marker
1053
+        compiler->last_result = yr_parser_emit_with_arg(
1054
+            yyscanner,
1055
+            OP_PUSH,
1056
+            UNDEFINED,
1057
+            NULL);
1058
+
1059
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1060
+      }
1061
+      integer_set ':'
1062
+      {
1063
+        int mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
1064
+        int8_t* addr;
1065
+
1066
+        // Clear counter for number of expressions evaluating
1067
+        // to TRUE.
1068
+        yr_parser_emit_with_arg(
1069
+            yyscanner, OP_CLEAR_M, mem_offset + 1, NULL);
1070
+
1071
+        // Clear iterations counter
1072
+        yr_parser_emit_with_arg(
1073
+            yyscanner, OP_CLEAR_M, mem_offset + 2, NULL);
1074
+
1075
+        if ($6 == INTEGER_SET_ENUMERATION)
1076
+        {
1077
+          // Pop the first integer
1078
+          yr_parser_emit_with_arg(
1079
+              yyscanner, OP_POP_M, mem_offset, &addr);
1080
+        }
1081
+        else // INTEGER_SET_RANGE
1082
+        {
1083
+          // Pop higher bound of set range
1084
+          yr_parser_emit_with_arg(
1085
+              yyscanner, OP_POP_M, mem_offset + 3, &addr);
1086
+
1087
+          // Pop lower bound of set range
1088
+          yr_parser_emit_with_arg(
1089
+              yyscanner, OP_POP_M, mem_offset, NULL);
1090
+        }
1091
+
1092
+        compiler->loop_address[compiler->loop_depth] = addr;
1093
+        compiler->loop_identifier[compiler->loop_depth] = $3;
1094
+        compiler->loop_depth++;
1095
+      }
1096
+      '(' boolean_expression ')'
1097
+      {
1098
+        int mem_offset;
1099
+
1100
+        compiler->loop_depth--;
1101
+        mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
1102
+
1103
+        // The value at the top of the stack is 1 if latest
1104
+        // expression was true or 0 otherwise. Add this value
1105
+        // to the counter for number of expressions evaluating
1106
+        // to true.
1107
+        yr_parser_emit_with_arg(
1108
+            yyscanner, OP_ADD_M, mem_offset + 1, NULL);
1109
+
1110
+        // Increment iterations counter
1111
+        yr_parser_emit_with_arg(
1112
+            yyscanner, OP_INCR_M, mem_offset + 2, NULL);
1113
+
1114
+        if ($6 == INTEGER_SET_ENUMERATION)
1115
+        {
1116
+          yr_parser_emit_with_arg_reloc(
1117
+              yyscanner,
1118
+              OP_JNUNDEF,
1119
+              PTR_TO_UINT64(
1120
+                  compiler->loop_address[compiler->loop_depth]),
1121
+              NULL);
1122
+        }
1123
+        else // INTEGER_SET_RANGE
1124
+        {
1125
+          // Increment lower bound of integer set
1126
+          yr_parser_emit_with_arg(
1127
+              yyscanner, OP_INCR_M, mem_offset, NULL);
1128
+
1129
+          // Push lower bound of integer set
1130
+          yr_parser_emit_with_arg(
1131
+              yyscanner, OP_PUSH_M, mem_offset, NULL);
1132
+
1133
+          // Push higher bound of integer set
1134
+          yr_parser_emit_with_arg(
1135
+              yyscanner, OP_PUSH_M, mem_offset + 3, NULL);
1136
+
1137
+          // Compare higher bound with lower bound, do loop again
1138
+          // if lower bound is still lower or equal than higher bound
1139
+          yr_parser_emit_with_arg_reloc(
1140
+              yyscanner,
1141
+              OP_JLE,
1142
+              PTR_TO_UINT64(
1143
+                compiler->loop_address[compiler->loop_depth]),
1144
+              NULL);
1145
+
1146
+          yr_parser_emit(yyscanner, OP_POP, NULL);
1147
+          yr_parser_emit(yyscanner, OP_POP, NULL);
1148
+        }
1149
+
1150
+        // Pop end-of-list marker.
1151
+        yr_parser_emit(yyscanner, OP_POP, NULL);
1152
+
1153
+        // At this point the loop quantifier (any, all, 1, 2,..)
1154
+        // is at the top of the stack. Check if the quantifier
1155
+        // is undefined (meaning "all") and replace it with the
1156
+        // iterations counter in that case.
1157
+        yr_parser_emit_with_arg(
1158
+            yyscanner, OP_SWAPUNDEF, mem_offset + 2, NULL);
1159
+
1160
+        // Compare the loop quantifier with the number of
1161
+        // expressions evaluating to TRUE.
1162
+        yr_parser_emit_with_arg(
1163
+            yyscanner, OP_PUSH_M, mem_offset + 1, NULL);
1164
+
1165
+        yr_parser_emit(yyscanner, OP_LE, NULL);
1166
+
1167
+        compiler->loop_identifier[compiler->loop_depth] = NULL;
1168
+        yr_free($3);
1169
+
1170
+        $$ = EXPRESSION_TYPE_BOOLEAN;
1171
+#endif
1172
+      }
1173
+    | _FOR_ for_expression _OF_ string_set ':'
1174
+      {
1175
+#ifdef REAL_YARA
1176
+        int mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
1177
+        int8_t* addr;
1178
+
1179
+        if (compiler->loop_depth == MAX_LOOP_NESTING)
1180
+          compiler->last_result = \
1181
+            ERROR_LOOP_NESTING_LIMIT_EXCEEDED;
1182
+
1183
+        if (compiler->loop_for_of_mem_offset != -1)
1184
+          compiler->last_result = \
1185
+            ERROR_NESTED_FOR_OF_LOOP;
1186
+
1187
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1188
+
1189
+        yr_parser_emit_with_arg(
1190
+            yyscanner, OP_CLEAR_M, mem_offset + 1, NULL);
1191
+
1192
+        yr_parser_emit_with_arg(
1193
+            yyscanner, OP_CLEAR_M, mem_offset + 2, NULL);
1194
+
1195
+        // Pop the first string.
1196
+        yr_parser_emit_with_arg(
1197
+            yyscanner, OP_POP_M, mem_offset, &addr);
1198
+
1199
+        compiler->loop_for_of_mem_offset = mem_offset;
1200
+        compiler->loop_address[compiler->loop_depth] = addr;
1201
+        compiler->loop_identifier[compiler->loop_depth] = NULL;
1202
+        compiler->loop_depth++;
1203
+#endif
1204
+      }
1205
+      '(' boolean_expression ')'
1206
+      {
1207
+#ifdef REAL_YARA
1208
+        int mem_offset;
1209
+
1210
+        compiler->loop_depth--;
1211
+        compiler->loop_for_of_mem_offset = -1;
1212
+
1213
+        mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
1214
+
1215
+        // Increment counter by the value returned by the
1216
+        // boolean expression (0 or 1).
1217
+        yr_parser_emit_with_arg(
1218
+            yyscanner, OP_ADD_M, mem_offset + 1, NULL);
1219
+
1220
+        // Increment iterations counter.
1221
+        yr_parser_emit_with_arg(
1222
+            yyscanner, OP_INCR_M, mem_offset + 2, NULL);
1223
+
1224
+        // If next string is not undefined, go back to the
1225
+        // begining of the loop.
1226
+        yr_parser_emit_with_arg_reloc(
1227
+            yyscanner,
1228
+            OP_JNUNDEF,
1229
+            PTR_TO_UINT64(
1230
+                compiler->loop_address[compiler->loop_depth]),
1231
+            NULL);
1232
+
1233
+        // Pop end-of-list marker.
1234
+        yr_parser_emit(yyscanner, OP_POP, NULL);
1235
+
1236
+        // At this point the loop quantifier (any, all, 1, 2,..)
1237
+        // is at top of the stack. Check if the quantifier is
1238
+        // undefined (meaning "all") and replace it with the
1239
+        // iterations counter in that case.
1240
+        yr_parser_emit_with_arg(
1241
+            yyscanner, OP_SWAPUNDEF, mem_offset + 2, NULL);
1242
+
1243
+        // Compare the loop quantifier with the number of
1244
+        // expressions evaluating to TRUE.
1245
+        yr_parser_emit_with_arg(
1246
+            yyscanner, OP_PUSH_M, mem_offset + 1, NULL);
1247
+
1248
+        yr_parser_emit(yyscanner, OP_LE, NULL);
1249
+
1250
+        $$ = EXPRESSION_TYPE_BOOLEAN;
1251
+
1252
+#endif
1253
+      }
1254
+    | for_expression _OF_ string_set
1255
+      {
1256
+#ifdef REAL_YARA
1257
+        yr_parser_emit(yyscanner, OP_OF, NULL);
1258
+
1259
+        $$ = EXPRESSION_TYPE_BOOLEAN;
1260
+#endif
1261
+      }
1262
+    | _NOT_ boolean_expression
1263
+      {
1264
+#ifdef REAL_YARA
1265
+        yr_parser_emit(yyscanner, OP_NOT, NULL);
1266
+
1267
+        $$ = EXPRESSION_TYPE_BOOLEAN;
1268
+#endif
1269
+      }
1270
+    | boolean_expression _AND_ boolean_expression
1271
+      {
1272
+#ifdef REAL_YARA
1273
+        yr_parser_emit(yyscanner, OP_AND, NULL);
1274
+
1275
+        $$ = EXPRESSION_TYPE_BOOLEAN;
1276
+#endif
1277
+      }
1278
+    | boolean_expression _OR_ boolean_expression
1279
+      {
1280
+#ifdef REAL_YARA
1281
+        CHECK_TYPE($1, EXPRESSION_TYPE_BOOLEAN, "or");
1282
+
1283
+        yr_parser_emit(yyscanner, OP_OR, NULL);
1284
+
1285
+        $$ = EXPRESSION_TYPE_BOOLEAN;
1286
+#endif
1287
+      }
1288
+    | primary_expression _LT_ primary_expression
1289
+      {
1290
+#ifdef REAL_YARA
1291
+        CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "<");
1292
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "<");
1293
+
1294
+        yr_parser_emit(yyscanner, OP_LT, NULL);
1295
+
1296
+        $$ = EXPRESSION_TYPE_BOOLEAN;
1297
+#endif
1298
+      }
1299
+    | primary_expression _GT_ primary_expression
1300
+      {
1301
+#ifdef REAL_YARA
1302
+        CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, ">");
1303
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, ">");
1304
+
1305
+        yr_parser_emit(yyscanner, OP_GT, NULL);
1306
+
1307
+        $$ = EXPRESSION_TYPE_BOOLEAN;
1308
+#endif
1309
+      }
1310
+    | primary_expression _LE_ primary_expression
1311
+      {
1312
+#ifdef REAL_YARA
1313
+        CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "<=");
1314
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "<=");
1315
+
1316
+        yr_parser_emit(yyscanner, OP_LE, NULL);
1317
+
1318
+        $$ = EXPRESSION_TYPE_BOOLEAN;
1319
+#endif
1320
+      }
1321
+    | primary_expression _GE_ primary_expression
1322
+      {
1323
+#ifdef REAL_YARA
1324
+        CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, ">=");
1325
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, ">=");
1326
+
1327
+        yr_parser_emit(yyscanner, OP_GE, NULL);
1328
+
1329
+        $$ = EXPRESSION_TYPE_BOOLEAN;
1330
+#endif
1331
+      }
1332
+    | primary_expression _EQ_ primary_expression
1333
+      {
1334
+#ifdef REAL_YARA
1335
+        if ($1 != $3)
1336
+        {
1337
+          yr_compiler_set_error_extra_info(
1338
+              compiler, "mismatching types for == operator");
1339
+          compiler->last_result = ERROR_WRONG_TYPE;
1340
+        }
1341
+        else if ($1 == EXPRESSION_TYPE_STRING)
1342
+        {
1343
+          compiler->last_result = yr_parser_emit(
1344
+              yyscanner,
1345
+              OP_SZ_EQ,
1346
+              NULL);
1347
+        }
1348
+        else
1349
+        {
1350
+          compiler->last_result = yr_parser_emit(
1351
+              yyscanner,
1352
+              OP_EQ,
1353
+              NULL);
1354
+        }
1355
+
1356
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1357
+
1358
+        $$ = EXPRESSION_TYPE_BOOLEAN;
1359
+#endif
1360
+      }
1361
+    | primary_expression _IS_ primary_expression
1362
+      {
1363
+#ifdef REAL_YARA
1364
+        if ($1 != $3)
1365
+        {
1366
+          yr_compiler_set_error_extra_info(
1367
+              compiler, "mismatching types for == operator");
1368
+          compiler->last_result = ERROR_WRONG_TYPE;
1369
+        }
1370
+        else if ($1 == EXPRESSION_TYPE_STRING)
1371
+        {
1372
+          compiler->last_result = yr_parser_emit(
1373
+              yyscanner,
1374
+              OP_SZ_EQ,
1375
+              NULL);
1376
+        }
1377
+        else
1378
+        {
1379
+          compiler->last_result = yr_parser_emit(
1380
+              yyscanner,
1381
+              OP_EQ,
1382
+              NULL);
1383
+        }
1384
+
1385
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1386
+
1387
+        $$ = EXPRESSION_TYPE_BOOLEAN;
1388
+#endif
1389
+      }
1390
+    | primary_expression _NEQ_ primary_expression
1391
+      {
1392
+#ifdef REAL_YARA
1393
+        if ($1 != $3)
1394
+        {
1395
+          yr_compiler_set_error_extra_info(
1396
+              compiler, "mismatching types for != operator");
1397
+          compiler->last_result = ERROR_WRONG_TYPE;
1398
+        }
1399
+        else if ($1 == EXPRESSION_TYPE_STRING)
1400
+        {
1401
+          compiler->last_result = yr_parser_emit(
1402
+              yyscanner,
1403
+              OP_SZ_NEQ,
1404
+              NULL);
1405
+        }
1406
+        else
1407
+        {
1408
+          compiler->last_result = yr_parser_emit(
1409
+              yyscanner,
1410
+              OP_NEQ,
1411
+              NULL);
1412
+        }
1413
+
1414
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1415
+
1416
+        $$ = EXPRESSION_TYPE_BOOLEAN;
1417
+#endif
1418
+      }
1419
+    | primary_expression
1420
+      {
1421
+#ifdef REAL_YARA
1422
+        $$ = $1;
1423
+#endif
1424
+      }
1425
+    |'(' expression ')'
1426
+      {
1427
+#ifdef REAL_YARA
1428
+        $$ = $2;
1429
+#endif
1430
+      }
1431
+    ;
1432
+
1433
+
1434
+integer_set
1435
+    : '(' integer_enumeration ')'  { $$ = INTEGER_SET_ENUMERATION; }
1436
+    | range                        { $$ = INTEGER_SET_RANGE; }
1437
+    ;
1438
+
1439
+
1440
+range
1441
+    : '(' primary_expression '.' '.'  primary_expression ')'
1442
+      {
1443
+#ifdef REAL_YARA
1444
+        if ($2 != EXPRESSION_TYPE_INTEGER)
1445
+        {
1446
+          yr_compiler_set_error_extra_info(
1447
+              compiler, "wrong type for range's lower bound");
1448
+          compiler->last_result = ERROR_WRONG_TYPE;
1449
+        }
1450
+
1451
+        if ($5 != EXPRESSION_TYPE_INTEGER)
1452
+        {
1453
+          yr_compiler_set_error_extra_info(
1454
+              compiler, "wrong type for range's upper bound");
1455
+          compiler->last_result = ERROR_WRONG_TYPE;
1456
+        }
1457
+
1458
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1459
+#endif
1460
+      }
1461
+    ;
1462
+
1463
+
1464
+integer_enumeration
1465
+    : primary_expression
1466
+      {
1467
+#ifdef REAL_YARA
1468
+        if ($1 != EXPRESSION_TYPE_INTEGER)
1469
+        {
1470
+          yr_compiler_set_error_extra_info(
1471
+              compiler, "wrong type for enumeration item");
1472
+          compiler->last_result = ERROR_WRONG_TYPE;
1473
+
1474
+        }
1475
+
1476
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1477
+#endif
1478
+      }
1479
+    | integer_enumeration ',' primary_expression
1480
+      {
1481
+#ifdef REAL_YARA
1482
+        if ($3 != EXPRESSION_TYPE_INTEGER)
1483
+        {
1484
+          yr_compiler_set_error_extra_info(
1485
+              compiler, "wrong type for enumeration item");
1486
+          compiler->last_result = ERROR_WRONG_TYPE;
1487
+        }
1488
+
1489
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1490
+#endif
1491
+      }
1492
+    ;
1493
+
1494
+
1495
+string_set
1496
+    : '('
1497
+      {
1498
+#ifdef REAL_YARA
1499
+        // Push end-of-list marker
1500
+        yr_parser_emit_with_arg(yyscanner, OP_PUSH, UNDEFINED, NULL);
1501
+#endif
1502
+      }
1503
+      string_enumeration ')'
1504
+    | _THEM_
1505
+      {
1506
+#ifdef REAL_YARA
1507
+        yr_parser_emit_with_arg(yyscanner, OP_PUSH, UNDEFINED, NULL);
1508
+        yr_parser_emit_pushes_for_strings(yyscanner, "$*");
1509
+#endif
1510
+      }
1511
+    ;
1512
+
1513
+
1514
+string_enumeration
1515
+    : string_enumeration_item
1516
+    | string_enumeration ',' string_enumeration_item
1517
+    ;
1518
+
1519
+
1520
+string_enumeration_item
1521
+    : _STRING_IDENTIFIER_
1522
+      {
1523
+#ifdef REAL_YARA
1524
+        yr_parser_emit_pushes_for_strings(yyscanner, $1);
1525
+        yr_free($1);
1526
+#endif
1527
+      }
1528
+    | _STRING_IDENTIFIER_WITH_WILDCARD_
1529
+      {
1530
+#ifdef REAL_YARA
1531
+        yr_parser_emit_pushes_for_strings(yyscanner, $1);
1532
+        yr_free($1);
1533
+#endif
1534
+      }
1535
+    ;
1536
+
1537
+
1538
+for_expression
1539
+    : primary_expression
1540
+    | _ALL_
1541
+      {
1542
+#ifdef REAL_YARA
1543
+        yr_parser_emit_with_arg(yyscanner, OP_PUSH, UNDEFINED, NULL);
1544
+#endif
1545
+      }
1546
+    | _ANY_
1547
+      {
1548
+#ifdef REAL_YARA
1549
+        yr_parser_emit_with_arg(yyscanner, OP_PUSH, 1, NULL);
1550
+#endif
1551
+      }
1552
+    ;
1553
+
1554
+
1555
+primary_expression
1556
+    : '(' primary_expression ')'
1557
+      {
1558
+#ifdef REAL_YARA
1559
+        $$ = $2;
1560
+#endif
1561
+      }
1562
+    | _FILESIZE_
1563
+      {
1564
+#ifdef REAL_YARA
1565
+        compiler->last_result = yr_parser_emit(
1566
+            yyscanner, OP_FILESIZE, NULL);
1567
+
1568
+        $$ = EXPRESSION_TYPE_INTEGER;
1569
+
1570
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1571
+#endif
1572
+      }
1573
+    | _ENTRYPOINT_
1574
+      {
1575
+#ifdef REAL_YARA
1576
+        yywarning(yyscanner,
1577
+            "Using deprecated \"entrypoint\" keyword. Use the \"entry_point\" " "function from PE module instead.");
1578
+
1579
+        compiler->last_result = yr_parser_emit(
1580
+            yyscanner, OP_ENTRYPOINT, NULL);
1581
+
1582
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1583
+
1584
+        $$ = EXPRESSION_TYPE_INTEGER;
1585
+#endif
1586
+      }
1587
+    | _INT8_  '(' primary_expression ')'
1588
+      {
1589
+#ifdef REAL_YARA
1590
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "int8");
1591
+
1592
+        compiler->last_result = yr_parser_emit(
1593
+            yyscanner, OP_INT8, NULL);
1594
+
1595
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1596
+
1597
+        $$ = EXPRESSION_TYPE_INTEGER;
1598
+#endif
1599
+      }
1600
+    | _INT16_ '(' primary_expression ')'
1601
+      {
1602
+#ifdef REAL_YARA
1603
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "int16");
1604
+
1605
+        compiler->last_result = yr_parser_emit(
1606
+            yyscanner, OP_INT16, NULL);
1607
+
1608
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1609
+
1610
+        $$ = EXPRESSION_TYPE_INTEGER;
1611
+#endif
1612
+      }
1613
+    | _INT32_ '(' primary_expression ')'
1614
+      {
1615
+#ifdef REAL_YARA
1616
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "int32");
1617
+
1618
+        compiler->last_result = yr_parser_emit(
1619
+            yyscanner, OP_INT32, NULL);
1620
+
1621
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1622
+
1623
+        $$ = EXPRESSION_TYPE_INTEGER;
1624
+#endif
1625
+      }
1626
+    | _UINT8_ '(' primary_expression ')'
1627
+      {
1628
+#ifdef REAL_YARA
1629
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "uint8");
1630
+
1631
+        compiler->last_result = yr_parser_emit(
1632
+            yyscanner, OP_UINT8, NULL);
1633
+
1634
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1635
+
1636
+        $$ = EXPRESSION_TYPE_INTEGER;
1637
+#endif
1638
+      }
1639
+    | _UINT16_ '(' primary_expression ')'
1640
+      {
1641
+#ifdef REAL_YARA
1642
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "uint16");
1643
+
1644
+        compiler->last_result = yr_parser_emit(
1645
+            yyscanner, OP_UINT16, NULL);
1646
+
1647
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1648
+
1649
+        $$ = EXPRESSION_TYPE_INTEGER;
1650
+#endif
1651
+      }
1652
+    | _UINT32_ '(' primary_expression ')'
1653
+      {
1654
+#ifdef REAL_YARA
1655
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "uint32");
1656
+
1657
+        compiler->last_result = yr_parser_emit(
1658
+            yyscanner, OP_UINT32, NULL);
1659
+
1660
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1661
+
1662
+        $$ = EXPRESSION_TYPE_INTEGER;
1663
+#endif
1664
+      }
1665
+    | _NUMBER_
1666
+      {
1667
+#ifdef REAL_YARA
1668
+        compiler->last_result = yr_parser_emit_with_arg(
1669
+            yyscanner, OP_PUSH, $1, NULL);
1670
+
1671
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1672
+
1673
+        $$ = EXPRESSION_TYPE_INTEGER;
1674
+#endif
1675
+      }
1676
+    | _TEXT_STRING_
1677
+      {
1678
+#ifdef REAL_YARA
1679
+        SIZED_STRING* sized_string = $1;
1680
+        char* string;
1681
+
1682
+        compiler->last_result = yr_arena_write_string(
1683
+            compiler->sz_arena,
1684
+            sized_string->c_string,
1685
+            &string);
1686
+
1687
+        yr_free($1);
1688
+
1689
+        if (compiler->last_result == ERROR_SUCCESS)
1690
+          compiler->last_result = yr_parser_emit_with_arg_reloc(
1691
+              yyscanner,
1692
+              OP_PUSH,
1693
+              PTR_TO_UINT64(string),
1694
+              NULL);
1695
+
1696
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1697
+
1698
+        $$ = EXPRESSION_TYPE_STRING;
1699
+#endif
1700
+      }
1701
+    | _STRING_COUNT_
1702
+      {
1703
+#ifdef REAL_YARA
1704
+        compiler->last_result = yr_parser_reduce_string_identifier(
1705
+            yyscanner,
1706
+            $1,
1707
+            OP_STR_COUNT);
1708
+
1709
+        yr_free($1);
1710
+
1711
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1712
+
1713
+        $$ = EXPRESSION_TYPE_INTEGER;
1714
+#endif
1715
+      }
1716
+    | _STRING_OFFSET_ '[' primary_expression ']'
1717
+      {
1718
+#ifdef REAL_YARA
1719
+        compiler->last_result = yr_parser_reduce_string_identifier(
1720
+            yyscanner,
1721
+            $1,
1722
+            OP_STR_OFFSET);
1723
+
1724
+        yr_free($1);
1725
+
1726
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1727
+
1728
+        $$ = EXPRESSION_TYPE_INTEGER;
1729
+#endif
1730
+      }
1731
+    | _STRING_OFFSET_
1732
+      {
1733
+#ifdef REAL_YARA
1734
+        compiler->last_result = yr_parser_emit_with_arg(
1735
+            yyscanner,
1736
+            OP_PUSH,
1737
+            1,
1738
+            NULL);
1739
+
1740
+        if (compiler->last_result == ERROR_SUCCESS)
1741
+          compiler->last_result = yr_parser_reduce_string_identifier(
1742
+              yyscanner,
1743
+              $1,
1744
+              OP_STR_OFFSET);
1745
+
1746
+        yr_free($1);
1747
+
1748
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1749
+
1750
+        $$ = EXPRESSION_TYPE_INTEGER;
1751
+#endif
1752
+      }
1753
+    | identifier
1754
+      {
1755
+#ifdef REAL_YARA
1756
+        if ($1 == (YR_OBJECT*) -1)  // loop identifier
1757
+        {
1758
+          $$ = EXPRESSION_TYPE_INTEGER;
1759
+        }
1760
+        else if ($1 == (YR_OBJECT*) -2)  // rule identifier
1761
+        {
1762
+          $$ = EXPRESSION_TYPE_BOOLEAN;
1763
+        }
1764
+        else if ($1 != NULL)
1765
+        {
1766
+          compiler->last_result = yr_parser_emit(
1767
+              yyscanner, OP_OBJ_VALUE, NULL);
1768
+
1769
+          switch($1->type)
1770
+          {
1771
+            case OBJECT_TYPE_INTEGER:
1772
+              $$ = EXPRESSION_TYPE_INTEGER;
1773
+              break;
1774
+            case OBJECT_TYPE_STRING:
1775
+              $$ = EXPRESSION_TYPE_STRING;
1776
+              break;
1777
+            default:
1778
+              assert(FALSE);
1779
+          }
1780
+        }
1781
+        else
1782
+        {
1783
+          yr_compiler_set_error_extra_info(compiler, $1->identifier);
1784
+          compiler->last_result = ERROR_WRONG_TYPE;
1785
+        }
1786
+
1787
+        ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1788
+#endif
1789
+      }
1790
+    | primary_expression '+' primary_expression
1791
+      {
1792
+#ifdef REAL_YARA
1793
+        CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "+");
1794
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "+");
1795
+
1796
+        yr_parser_emit(yyscanner, OP_ADD, NULL);
1797
+
1798
+        $$ = EXPRESSION_TYPE_INTEGER;
1799
+#endif
1800
+      }
1801
+    | primary_expression '-' primary_expression
1802
+      {
1803
+#ifdef REAL_YARA
1804
+        CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "-");
1805
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "-");
1806
+
1807
+        yr_parser_emit(yyscanner, OP_SUB, NULL);
1808
+
1809
+        $$ = EXPRESSION_TYPE_INTEGER;
1810
+#endif
1811
+      }
1812
+    | primary_expression '*' primary_expression
1813
+      {
1814
+#ifdef REAL_YARA
1815
+        CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "*");
1816
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "*");
1817
+
1818
+        yr_parser_emit(yyscanner, OP_MUL, NULL);
1819
+
1820
+        $$ = EXPRESSION_TYPE_INTEGER;
1821
+#endif
1822
+      }
1823
+    | primary_expression '\\' primary_expression
1824
+      {
1825
+#ifdef REAL_YARA
1826
+        CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "\\");
1827
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "\\");
1828
+
1829
+        yr_parser_emit(yyscanner, OP_DIV, NULL);
1830
+
1831
+        $$ = EXPRESSION_TYPE_INTEGER;
1832
+#endif
1833
+      }
1834
+    | primary_expression '%' primary_expression
1835
+      {
1836
+#ifdef REAL_YARA
1837
+        CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "%");
1838
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "%");
1839
+
1840
+        yr_parser_emit(yyscanner, OP_MOD, NULL);
1841
+
1842
+        $$ = EXPRESSION_TYPE_INTEGER;
1843
+#endif
1844
+      }
1845
+    | primary_expression '^' primary_expression
1846
+      {
1847
+#ifdef REAL_YARA
1848
+        CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "^");
1849
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "^");
1850
+
1851
+        yr_parser_emit(yyscanner, OP_XOR, NULL);
1852
+
1853
+        $$ = EXPRESSION_TYPE_INTEGER;
1854
+#endif
1855
+      }
1856
+    | primary_expression '&' primary_expression
1857
+      {
1858
+#ifdef REAL_YARA
1859
+        CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "^");
1860
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "^");
1861
+
1862
+        yr_parser_emit(yyscanner, OP_AND, NULL);
1863
+
1864
+        $$ = EXPRESSION_TYPE_INTEGER;
1865
+#endif
1866
+      }
1867
+    | primary_expression '|' primary_expression
1868
+      {
1869
+#ifdef REAL_YARA
1870
+        CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "|");
1871
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "|");
1872
+
1873
+        yr_parser_emit(yyscanner, OP_OR, NULL);
1874
+
1875
+        $$ = EXPRESSION_TYPE_INTEGER;
1876
+#endif
1877
+      }
1878
+    | '~' primary_expression
1879
+      {
1880
+#ifdef REAL_YARA
1881
+        CHECK_TYPE($2, EXPRESSION_TYPE_INTEGER, "~");
1882
+
1883
+        yr_parser_emit(yyscanner, OP_NEG, NULL);
1884
+
1885
+        $$ = EXPRESSION_TYPE_INTEGER;
1886
+#endif
1887
+      }
1888
+    | primary_expression _SHIFT_LEFT_ primary_expression
1889
+      {
1890
+#ifdef REAL_YARA
1891
+        CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "<<");
1892
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "<<");
1893
+
1894
+        yr_parser_emit(yyscanner, OP_SHL, NULL);
1895
+
1896
+        $$ = EXPRESSION_TYPE_INTEGER;
1897
+#endif
1898
+      }
1899
+    | primary_expression _SHIFT_RIGHT_ primary_expression
1900
+      {
1901
+#ifdef REAL_YARA
1902
+        CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, ">>");
1903
+        CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, ">>");
1904
+
1905
+        yr_parser_emit(yyscanner, OP_SHR, NULL);
1906
+
1907
+        $$ = EXPRESSION_TYPE_INTEGER;
1908
+#endif
1909
+      }
1910
+    | regexp
1911
+      {
1912
+#ifdef REAL_YARA
1913
+        $$ = $1;
1914
+#endif
1915
+      }
1916
+    ;
1917
+
1918
+%%
0 1919
new file mode 100644
... ...
@@ -0,0 +1,100 @@
0
+/*
1
+Copyright (c) 2007. Victor M. Alvarez [plusvic@gmail.com].
2
+
3
+Licensed under the Apache License, Version 2.0 (the "License");
4
+you may not use this file except in compliance with the License.
5
+You may obtain a copy of the License at
6
+
7
+   http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+Unless required by applicable law or agreed to in writing, software
10
+distributed under the License is distributed on an "AS IS" BASIS,
11
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+See the License for the specific language governing permissions and
13
+limitations under the License.
14
+*/
15
+
16
+#ifdef REAL_YARA
17
+#include <yara/compiler.h>
18
+#include <grammar.h>
19
+#else
20
+#include "libclamav/yara_clam.h"
21
+#endif
22
+
23
+#undef yyparse
24
+#undef yylex
25
+#undef yyerror
26
+#undef yyfatal
27
+#undef yychar
28
+#undef yydebug
29
+#undef yynerrs
30
+#undef yyget_extra
31
+#undef yyget_lineno
32
+
33
+#undef YY_DECL
34
+#undef YY_FATAL_ERROR
35
+#undef YY_EXTRA_TYPE
36
+
37
+#define yyparse       yara_yyparse
38
+#define yylex         yara_yylex
39
+#define yyerror       yara_yyerror
40
+#define yyfatal       yara_yyfatal
41
+#define yywarning     yara_yywarning
42
+#define yychar        yara_yychar
43
+#define yydebug       yara_yydebug
44
+#define yynerrs       yara_yynerrs
45
+#define yyget_extra   yara_yyget_extra
46
+#define yyget_lineno  yara_yyget_lineno
47
+
48
+
49
+#ifndef YY_TYPEDEF_YY_SCANNER_T
50
+#define YY_TYPEDEF_YY_SCANNER_T
51
+typedef void* yyscan_t;
52
+#endif
53
+
54
+
55
+#define YY_DECL int yylex( \
56
+    YYSTYPE* yylval_param, yyscan_t yyscanner, YR_COMPILER* compiler)
57
+
58
+
59
+#define YY_FATAL_ERROR(msg) yara_yyfatal(yyscanner, msg)
60
+
61
+
62
+#define YY_EXTRA_TYPE YR_COMPILER*
63
+#define YY_USE_CONST
64
+
65
+
66
+int yyget_lineno(yyscan_t yyscanner);
67
+
68
+int yylex(
69
+    YYSTYPE* yylval_param,
70
+    yyscan_t yyscanner,
71
+    YR_COMPILER* compiler);
72
+
73
+int yyparse(
74
+    void *yyscanner,
75
+    YR_COMPILER* compiler);
76
+
77
+void yyerror(
78
+    yyscan_t yyscanner,
79
+    YR_COMPILER* compiler,
80
+    const char *error_message);
81
+
82
+void yywarning(
83
+    yyscan_t yyscanner,
84
+    const char *warning_message);
85
+
86
+void yyfatal(
87
+    yyscan_t yyscanner,
88
+    const char *error_message);
89
+
90
+YY_EXTRA_TYPE yyget_extra(
91
+    yyscan_t yyscanner);
92
+
93
+int yr_lex_parse_rules_string(
94
+    const char* rules_string,
95
+    YR_COMPILER* compiler);
96
+
97
+int yr_lex_parse_rules_file(
98
+    FILE* rules_file,
99
+    YR_COMPILER* compiler);
0 100
new file mode 100644
... ...
@@ -0,0 +1,805 @@
0
+/*
1
+ * YARA rule lexer for ClamAV
2
+ * 
3
+ * Copyright (C) 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
4
+ * 
5
+ * Authors: Steven Morgan
6
+ * 
7
+ * This program is free software; you can redistribute it and/or modify it under
8
+ * the terms of the GNU General Public License version 2 as published by the
9
+ * Free Software Foundation.
10
+ * 
11
+ * This program is distributed in the hope that it will be useful, but WITHOUT
12
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14
+ * more details.
15
+ * 
16
+ * You should have received a copy of the GNU General Public License along with
17
+ * this program; if not, write to the Free Software Foundation, Inc., 51
18
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
+ */
20
+/* This file was originally derived from yara 3.1.0 libyara/lexer.l and is
21
+   revised for running YARA rules in ClamAV. Following is the YARA copyright. */
22
+/*
23
+Copyright (c) 2007-2013. The YARA Authors. All Rights Reserved.
24
+
25
+Licensed under the Apache License, Version 2.0 (the "License");
26
+you may not use this file except in compliance with the License.
27
+You may obtain a copy of the License at
28
+
29
+   http://www.apache.org/licenses/LICENSE-2.0
30
+
31
+Unless required by applicable law or agreed to in writing, software
32
+distributed under the License is distributed on an "AS IS" BASIS,
33
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34
+See the License for the specific language governing permissions and
35
+limitations under the License.
36
+*/
37
+
38
+/* Lexical analyzer for YARA */
39
+
40
+%{
41
+
42
+#include <math.h>
43
+#include <stdio.h>
44
+#include <stdint.h>
45
+#include <string.h>
46
+#include <setjmp.h>
47
+
48
+#ifdef REAL_YARA
49
+#include <yara/lexer.h>
50
+#include <yara/rules.h>
51
+#include <yara/sizedstr.h>
52
+#include <yara/error.h>
53
+#include <yara/mem.h>
54
+#include <yara/utils.h>
55
+
56
+#include "grammar.h"
57
+#else
58
+#include "others.h"
59
+#include "yara_clam.h"
60
+#include "yara_grammar.h"
61
+#include "yara_lexer.h"
62
+#endif
63
+
64
+#define LEX_CHECK_SPACE_OK(data, current_size, max_length) \
65
+    if (strlen(data) + current_size >= max_length - 1) \
66
+    { \
67
+      yyerror(yyscanner, compiler, "out of space in lex_buf"); \
68
+      yyterminate(); \
69
+    }
70
+
71
+#define YYTEXT_TO_BUFFER \
72
+    { \
73
+      char *yptr = yytext; \
74
+      LEX_CHECK_SPACE_OK(yptr, yyextra->lex_buf_len, LEX_BUF_SIZE); \
75
+      while(*yptr) \
76
+      { \
77
+        *yyextra->lex_buf_ptr++ = *yptr++; \
78
+        yyextra->lex_buf_len++; \
79
+      } \
80
+    }
81
+
82
+#ifdef _WIN32
83
+#define snprintf _snprintf
84
+#endif
85
+
86
+%}
87
+
88
+%option reentrant bison-bridge
89
+%option noyywrap
90
+%option nounistd
91
+%option noinput
92
+%option nounput
93
+%option yylineno
94
+%option prefix="yara_yy"
95
+%option outfile="lex.yy.c"
96
+
97
+%option verbose
98
+%option warn
99
+
100
+%x str
101
+%x regexp
102
+%x include
103
+%x comment
104
+
105
+digit         [0-9]
106
+letter        [a-zA-Z]
107
+hexdigit      [a-fA-F0-9]
108
+
109
+%%
110
+
111
+"<"                     { return _LT_;          }
112
+">"                     { return _GT_;          }
113
+"<="                    { return _LE_;          }
114
+">="                    { return _GE_;          }
115
+"=="                    { return _EQ_;          }
116
+"!="                    { return _NEQ_;         }
117
+"<<"                    { return _SHIFT_LEFT_;  }
118
+">>"                    { return _SHIFT_RIGHT_; }
119
+"private"               { return _PRIVATE_;     }
120
+"global"                { return _GLOBAL_;      }
121
+"rule"                  { return _RULE_;        }
122
+"meta"                  { return _META_;        }
123
+"strings"               { return _STRINGS_;     }
124
+"ascii"                 { return _ASCII_;       }
125
+"wide"                  { return _WIDE_;        }
126
+"fullword"              { return _FULLWORD_;    }
127
+"nocase"                { return _NOCASE_;      }
128
+"condition"             { return _CONDITION_;   }
129
+"true"                  { return _TRUE_;        }
130
+"false"                 { return _FALSE_;       }
131
+"not"                   { return _NOT_;         }
132
+"and"                   { return _AND_;         }
133
+"or"                    { return _OR_;          }
134
+"at"                    { return _AT_;          }
135
+"in"                    { return _IN_;          }
136
+"of"                    { return _OF_;          }
137
+"them"                  { return _THEM_;        }
138
+"for"                   { return _FOR_;         }
139
+"all"                   { return _ALL_;         }
140
+"any"                   { return _ANY_;         }
141
+"entrypoint"            { return _ENTRYPOINT_;  }
142
+"filesize"              { return _FILESIZE_;    }
143
+"uint8"                 { return _UINT8_;       }
144
+"uint16"                { return _UINT16_;      }
145
+"uint32"                { return _UINT32_;      }
146
+"int8"                  { return _INT8_;        }
147
+"int16"                 { return _INT16_;       }
148
+"int32"                 { return _INT32_;       }
149
+"matches"               { return _MATCHES_;     }
150
+"contains"              { return _CONTAINS_;    }
151
+"import"                { return _IMPORT_;      }
152
+
153
+
154
+"/*"                    { BEGIN(comment);       }
155
+<comment>"*/"           { BEGIN(INITIAL);       }
156
+<comment>(.|\n)         { /* skip comments */   }
157
+
158
+
159
+"//"[^\n]*              { /* skip single-line comments */ }
160
+
161
+
162
+include[ \t]+\"         {
163
+                          yyextra->lex_buf_ptr = yyextra->lex_buf;
164
+                          yyextra->lex_buf_len = 0;
165
+                          BEGIN(include);
166
+                        }
167
+
168
+
169
+<include>[^\"]+         { YYTEXT_TO_BUFFER; }
170
+
171
+
172
+<include>\"             {
173
+#ifdef REAL_YARA
174
+
175
+  char            buffer[1024];
176
+  char            *current_file_name;
177
+  char            *s = NULL;
178
+  char            *b = NULL;
179
+  char            *f;
180
+  FILE*           fh;
181
+
182
+  if (compiler->allow_includes)
183
+  {
184
+    *yyextra->lex_buf_ptr = '\0'; // null-terminate included file path
185
+
186
+    // move path of current source file into buffer
187
+    current_file_name = yr_compiler_get_current_file_name(compiler);
188
+
189
+    if (current_file_name != NULL)
190
+    {
191
+      strlcpy(buffer, current_file_name, sizeof(buffer));
192
+    }
193
+    else
194
+    {
195
+      buffer[0] = '\0';
196
+    }
197
+
198
+    // make included file path relative to current source file
199
+    s = strrchr(buffer, '/');
200
+
201
+    #ifdef _WIN32
202
+    b = strrchr(buffer, '\\'); // in Windows both path delimiters are accepted
203
+    #endif
204
+
205
+    if (s != NULL || b != NULL)
206
+    {
207
+      f = (b > s)? (b + 1): (s + 1);
208
+
209
+      strlcpy(f, yyextra->lex_buf, sizeof(buffer) - (f - buffer));
210
+
211
+      f = buffer;
212
+
213
+      // SECURITY: Potential for directory traversal here.
214
+      fh = fopen(buffer, "r");
215
+
216
+      // if include file was not found relative to current source file,
217
+      // try to open it with path as specified by user (maybe user wrote
218
+      // a full path)
219
+
220
+      if (fh == NULL)
221
+      {
222
+        f = yyextra->lex_buf;
223
+
224
+        // SECURITY: Potential for directory traversal here.
225
+        fh = fopen(yyextra->lex_buf, "r");
226
+      }
227
+    }
228
+    else
229
+    {
230
+      f = yyextra->lex_buf;
231
+
232
+      // SECURITY: Potential for directory traversal here.
233
+      fh = fopen(yyextra->lex_buf, "r");
234
+    }
235
+
236
+    if (fh != NULL)
237
+    {
238
+      int error_code = _yr_compiler_push_file_name(compiler, f);
239
+
240
+      if (error_code != ERROR_SUCCESS)
241
+      {
242
+        if (error_code == ERROR_INCLUDES_CIRCULAR_REFERENCE)
243
+        {
244
+          yyerror(yyscanner, compiler, "includes circular reference");
245
+        }
246
+        else if (error_code == ERROR_INCLUDE_DEPTH_EXCEEDED)
247
+        {
248
+          yyerror(yyscanner, compiler, "includes depth exceeded");
249
+        }
250
+
251
+        yyterminate();
252
+      }
253
+
254
+      _yr_compiler_push_file(compiler, fh);
255
+      yypush_buffer_state(
256
+          yy_create_buffer(fh, YY_BUF_SIZE, yyscanner), yyscanner);
257
+    }
258
+    else
259
+    {
260
+      snprintf(buffer, sizeof(buffer),
261
+               "can't open include file: %s", yyextra->lex_buf);
262
+      yyerror(yyscanner, compiler, buffer);
263
+    }
264
+  }
265
+  else // not allowing includes
266
+  {
267
+    yyerror(yyscanner, compiler, "includes are disabled");
268
+    yyterminate();
269
+  }
270
+
271
+  BEGIN(INITIAL);
272
+#else
273
+  yyerror(yyscanner, compiler, "includes are disabled");
274
+  yyterminate();
275
+#endif
276
+}
277
+
278
+
279
+<<EOF>> {
280
+#ifdef REAL_YARA
281
+
282
+  YR_COMPILER* compiler = yyget_extra(yyscanner);
283
+  FILE* file = _yr_compiler_pop_file(compiler);
284
+
285
+  if (file != NULL)
286
+  {
287
+    fclose(file);
288
+  }
289
+
290
+  _yr_compiler_pop_file_name(compiler);
291
+  yypop_buffer_state(yyscanner);
292
+
293
+  if (!YY_CURRENT_BUFFER)
294
+  {
295
+    yyterminate();
296
+  }
297
+#endif
298
+}
299
+
300
+
301
+$({letter}|{digit}|_)*"*"  {
302
+#ifdef REAL_YARA
303
+
304
+  yylval->c_string = yr_strdup(yytext);
305
+
306
+  if (yylval->c_string == NULL)
307
+  {
308
+    yyerror(yyscanner, compiler, "not enough memory");
309
+    yyterminate();
310
+  }
311
+
312
+#endif
313
+  return _STRING_IDENTIFIER_WITH_WILDCARD_;
314
+}
315
+
316
+
317
+$({letter}|{digit}|_)*  {
318
+#ifdef REAL_YARA
319
+
320
+  yylval->c_string = yr_strdup(yytext);
321
+
322
+  if (yylval->c_string == NULL)
323
+  {
324
+    yyerror(yyscanner, compiler, "not enough memory");
325
+    yyterminate();
326
+  }
327
+
328
+#endif
329
+  return _STRING_IDENTIFIER_;
330
+}
331
+
332
+
333
+#({letter}|{digit}|_)*  {
334
+#ifdef REAL_YARA
335
+
336
+  yylval->c_string = yr_strdup(yytext);
337
+
338
+  if (yylval->c_string == NULL)
339
+  {
340
+    yyerror(yyscanner, compiler, "not enough memory");
341
+    yyterminate();
342
+  }
343
+
344
+  yylval->c_string[0] = '$'; /* replace # by $*/
345
+#endif
346
+  return _STRING_COUNT_;
347
+}
348
+
349
+
350
+@({letter}|{digit}|_)*  {
351
+#ifdef REAL_YARA
352
+
353
+  yylval->c_string = yr_strdup(yytext);
354
+
355
+  if (yylval->c_string == NULL)
356
+  {
357
+    yyerror(yyscanner, compiler, "not enough memory");
358
+    yyterminate();
359
+  }
360
+
361
+  yylval->c_string[0] = '$'; /* replace @ by $*/
362
+#endif
363
+  return _STRING_OFFSET_;
364
+}
365
+
366
+
367
+({letter}|_)({letter}|{digit}|_)*  {
368
+#ifdef REAL_YARA
369
+
370
+  if (strlen(yytext) > 128)
371
+  {
372
+    yyerror(yyscanner, compiler, "indentifier too long");
373
+  }
374
+
375
+  yylval->c_string = yr_strdup(yytext);
376
+
377
+  if (yylval->c_string == NULL)
378
+  {
379
+    yyerror(yyscanner, compiler, "not enough memory");
380
+    yyterminate();
381
+  }
382
+#endif
383
+  return _IDENTIFIER_;
384
+}
385
+
386
+
387
+{digit}+(MB|KB){0,1}  {
388
+#ifdef REAL_YARA
389
+
390
+  yylval->integer = (size_t) atol(yytext);
391
+
392
+  if (strstr(yytext, "KB") != NULL)
393
+  {
394
+     yylval->integer *= 1024;
395
+  }
396
+  else if (strstr(yytext, "MB") != NULL)
397
+  {
398
+     yylval->integer *= 1048576;
399
+  }
400
+#endif
401
+  return _NUMBER_;
402
+}
403
+
404
+
405
+0x{hexdigit}+  {
406
+#ifdef REAL_YARA
407
+
408
+  yylval->integer = xtoi(yytext + 2);
409
+  return _NUMBER_;
410
+#endif
411
+}
412
+
413
+
414
+<str>\"   {     /* saw closing quote - all done */
415
+#ifdef REAL_YARA
416
+
417
+  SIZED_STRING* s;
418
+
419
+  if (yyextra->lex_buf_len == 0)
420
+  {
421
+    yyerror(yyscanner, compiler, "empty string");
422
+  }
423
+
424
+  *yyextra->lex_buf_ptr = '\0';
425
+
426
+  BEGIN(INITIAL);
427
+
428
+  s = (SIZED_STRING*) yr_malloc(yyextra->lex_buf_len + sizeof(SIZED_STRING));
429
+  s->length = yyextra->lex_buf_len;
430
+  s->flags = 0;
431
+
432
+  memcpy(s->c_string, yyextra->lex_buf, yyextra->lex_buf_len + 1);
433
+  yylval->sized_string = s;
434
+
435
+#endif
436
+  return _TEXT_STRING_;
437
+}
438
+
439
+
440
+<str>\\t   {
441
+#ifdef REAL_YARA
442
+
443
+  LEX_CHECK_SPACE_OK("\t", yyextra->lex_buf_len, LEX_BUF_SIZE);
444
+  *yyextra->lex_buf_ptr++ = '\t';
445
+  yyextra->lex_buf_len++;
446
+#endif
447
+}
448
+
449
+
450
+<str>\\n   {
451
+#ifdef REAL_YARA
452
+
453
+  LEX_CHECK_SPACE_OK("\n", yyextra->lex_buf_len, LEX_BUF_SIZE);
454
+  *yyextra->lex_buf_ptr++ = '\n';
455
+  yyextra->lex_buf_len++;
456
+#endif
457
+}
458
+
459
+
460
+<str>\\\"   {
461
+#ifdef REAL_YARA
462
+
463
+  LEX_CHECK_SPACE_OK("\"", yyextra->lex_buf_len, LEX_BUF_SIZE);
464
+  *yyextra->lex_buf_ptr++ = '\"';
465
+  yyextra->lex_buf_len++;
466
+#endif
467
+}
468
+
469
+
470
+<str>\\\\   {
471
+#ifdef REAL_YARA
472
+
473
+  LEX_CHECK_SPACE_OK("\\", yyextra->lex_buf_len, LEX_BUF_SIZE);
474
+  *yyextra->lex_buf_ptr++ = '\\';
475
+  yyextra->lex_buf_len++;
476
+#endif
477
+}
478
+
479
+
480
+<str>\\x{hexdigit}{2} {
481
+#ifdef REAL_YARA
482
+
483
+   int result;
484
+
485
+   sscanf( yytext + 2, "%x", &result );
486
+   LEX_CHECK_SPACE_OK("X", yyextra->lex_buf_len, LEX_BUF_SIZE);
487
+   *yyextra->lex_buf_ptr++ = result;
488
+   yyextra->lex_buf_len++;
489
+#endif
490
+}
491
+
492
+
493
+<str>[^\\\n\"]+   { YYTEXT_TO_BUFFER; }
494
+
495
+
496
+<str>\n  {
497
+#ifdef REAL_YARA
498
+
499
+  yyerror(yyscanner, compiler, "unterminated string");
500
+  yyterminate();
501
+#endif
502
+}
503
+
504
+<str>\\(.|\n) {
505
+#ifdef REAL_YARA
506
+
507
+  yyerror(yyscanner, compiler, "illegal escape sequence");
508
+#endif
509
+}
510
+
511
+
512
+<regexp>\/i?s?  {
513
+#ifdef REAL_YARA
514
+
515
+  SIZED_STRING* s;
516
+
517
+  if (yyextra->lex_buf_len == 0)
518
+  {
519
+    yyerror(yyscanner, compiler, "empty regular expression");
520
+  }
521
+
522
+  *yyextra->lex_buf_ptr = '\0';
523
+
524
+  BEGIN(INITIAL);
525
+
526
+  s = (SIZED_STRING*) yr_malloc(yyextra->lex_buf_len + sizeof(SIZED_STRING));
527
+  s->flags = 0;
528
+
529
+  if (yytext[1] == 'i')
530
+    s->flags |= SIZED_STRING_FLAGS_NO_CASE;
531
+
532
+  if (yytext[1] == 's' || yytext[2] == 's')
533
+    s->flags |= SIZED_STRING_FLAGS_DOT_ALL;
534
+
535
+  s->length = yyextra->lex_buf_len;
536
+  strlcpy(s->c_string, yyextra->lex_buf, s->length + 1);
537
+
538
+  yylval->sized_string = s;
539
+
540
+#endif
541
+  return _REGEXP_;
542
+}
543
+
544
+
545
+<regexp>\\\/  {
546
+#ifdef REAL_YARA
547
+
548
+  LEX_CHECK_SPACE_OK("/", yyextra->lex_buf_len, LEX_BUF_SIZE);
549
+  *yyextra->lex_buf_ptr++ = '/';
550
+  yyextra->lex_buf_len++ ;
551
+#endif
552
+}
553
+
554
+
555
+<regexp>\\. {
556
+#ifdef REAL_YARA
557
+
558
+  LEX_CHECK_SPACE_OK("\\.", yyextra->lex_buf_len, LEX_BUF_SIZE);
559
+  *yyextra->lex_buf_ptr++ = yytext[0];
560
+  *yyextra->lex_buf_ptr++ = yytext[1];
561
+  yyextra->lex_buf_len += 2;
562
+#endif
563
+}
564
+
565
+
566
+<regexp>[^/\n\\]+ { YYTEXT_TO_BUFFER; }
567
+
568
+
569
+<regexp>\n  {
570
+#ifdef REAL_YARA
571
+
572
+  yyerror(yyscanner, compiler, "unterminated regular expression");
573
+  yyterminate();
574
+#endif
575
+}
576
+
577
+
578
+\"  {
579
+#ifdef REAL_YARA
580
+
581
+  yyextra->lex_buf_ptr = yyextra->lex_buf;
582
+  yyextra->lex_buf_len = 0;
583
+  BEGIN(str);
584
+#endif
585
+}
586
+
587
+
588
+"/"  {
589
+#ifdef REAL_YARA
590
+
591
+  yyextra->lex_buf_ptr = yyextra->lex_buf;
592
+  yyextra->lex_buf_len = 0;
593
+  BEGIN(regexp);
594
+#endif
595
+}
596
+
597
+
598
+\{({hexdigit}|[ \-|\?\[\]\(\)\n\t])+\}  {
599
+#ifdef REAL_YARA
600
+
601
+  int len = strlen(yytext);
602
+  SIZED_STRING* s = (SIZED_STRING*) yr_malloc(len + sizeof(SIZED_STRING));
603
+
604
+  s->length = len;
605
+  s->flags = 0;
606
+
607
+  strlcpy(s->c_string, yytext, s->length + 1);
608
+  yylval->sized_string = s;
609
+
610
+  return _HEX_STRING_;
611
+#endif
612
+}
613
+
614
+
615
+[ \t\r\n]   /* skip whitespace */
616
+
617
+.   {
618
+
619
+  if (yytext[0] >= 32 && yytext[0] < 127)
620
+  {
621
+    return yytext[0];
622
+  }
623
+  else
624
+  {
625
+    yyerror(yyscanner, compiler, "non-ascii character");
626
+    yyterminate();
627
+  }
628
+}
629
+
630
+%%
631
+
632
+
633
+void yywarning(
634
+    yyscan_t yyscanner,
635
+    const char *warning_message)
636
+{
637
+#ifdef REAL_YARA
638
+  YR_COMPILER* compiler = yyget_extra(yyscanner);
639
+  char* file_name;
640
+
641
+  if (compiler->file_name_stack_ptr > 0)
642
+    file_name = compiler->file_name_stack[compiler->file_name_stack_ptr - 1];
643
+  else
644
+    file_name = NULL;
645
+
646
+  compiler->callback(
647
+      YARA_ERROR_LEVEL_WARNING,
648
+      file_name,
649
+      yyget_lineno(yyscanner),
650
+      warning_message);
651
+#else
652
+  cli_errmsg("yara_lexer:yywarning() %s\n", warning_message);
653
+#endif
654
+}
655
+
656
+
657
+void yyfatal(
658
+    yyscan_t yyscanner,
659
+    const char *error_message)
660
+{
661
+#ifdef REAL_YARA
662
+  YR_COMPILER* compiler = yyget_extra(yyscanner);
663
+
664
+  yyerror(yyscanner, compiler, error_message);
665
+  longjmp(compiler->error_recovery, 1);
666
+#else
667
+  cli_errmsg("yara_lexer:yyfatal() %s\n", error_message);
668
+#endif
669
+}
670
+
671
+
672
+void yyerror(
673
+    yyscan_t yyscanner,
674
+    YR_COMPILER* compiler,
675
+    const char *error_message)
676
+{
677
+#ifdef REAL_YARA
678
+  char message[512] = {'\0'};
679
+  char* file_name = NULL;
680
+
681
+  /*
682
+    if error_message != NULL the error comes from yyparse internal code
683
+    else the error comes from my code and the error code is set in
684
+    compiler->last_result
685
+  */
686
+
687
+  compiler->errors++;
688
+
689
+  if (compiler->error_line != 0)
690
+    compiler->last_error_line = compiler->error_line;
691
+  else
692
+    compiler->last_error_line = yyget_lineno(yyscanner);
693
+
694
+  compiler->error_line = 0;
695
+
696
+  if (compiler->file_name_stack_ptr > 0)
697
+  {
698
+    file_name = compiler->file_name_stack[compiler->file_name_stack_ptr - 1];
699
+  }
700
+  else
701
+  {
702
+    file_name = NULL;
703
+  }
704
+
705
+  if (error_message != NULL)
706
+  {
707
+    yr_compiler_set_error_extra_info(compiler, error_message);
708
+    compiler->last_error = ERROR_SYNTAX_ERROR;
709
+
710
+    if (compiler->callback != NULL)
711
+    {
712
+      compiler->callback(
713
+          YARA_ERROR_LEVEL_ERROR,
714
+          file_name,
715
+          compiler->last_error_line,
716
+          error_message);
717
+    }
718
+  }
719
+  else
720
+  {
721
+    compiler->last_error = compiler->last_result;
722
+
723
+    if (compiler->callback != NULL)
724
+    {
725
+      yr_compiler_get_error_message(compiler, message, sizeof(message));
726
+
727
+      compiler->callback(
728
+        YARA_ERROR_LEVEL_ERROR,
729
+        file_name,
730
+        compiler->last_error_line,
731
+        message);
732
+    }
733
+  }
734
+
735
+  compiler->last_result = ERROR_SUCCESS;
736
+#else
737
+  cli_errmsg("yara_lexer:yyerror() %s\n", error_message);
738
+#endif
739
+}
740
+
741
+
742
+int yr_lex_parse_rules_string(
743
+  const char* rules_string,
744
+  YR_COMPILER* compiler)
745
+{
746
+#ifdef REAL_YARA
747
+  yyscan_t yyscanner;
748
+
749
+  compiler->errors = 0;
750
+
751
+  if (setjmp(compiler->error_recovery) != 0)
752
+    return compiler->errors;
753
+
754
+  yylex_init(&yyscanner);
755
+
756
+  yyset_debug(1, yyscanner);
757
+
758
+  yyset_extra(compiler, yyscanner);
759
+
760
+  yy_scan_string(rules_string, yyscanner);
761
+
762
+  yyset_lineno(1, yyscanner);
763
+  yyparse(yyscanner, compiler);
764
+  yylex_destroy(yyscanner);
765
+
766
+  return compiler->errors;
767
+#else
768
+  return 0;
769
+#endif
770
+}
771
+
772
+
773
+int yr_lex_parse_rules_file(
774
+  FILE* rules_file,
775
+  YR_COMPILER* compiler)
776
+{
777
+  yyscan_t yyscanner;
778
+
779
+#ifdef REAL_YARA
780
+  compiler->errors = 0;
781
+
782
+  if (setjmp(compiler->error_recovery) != 0)
783
+    return compiler->errors;
784
+#endif
785
+
786
+  yylex_init(&yyscanner);
787
+
788
+  #if YYDEBUG
789
+  printf("debug enabled");
790
+  #endif
791
+
792
+  yyset_debug(1, yyscanner);
793
+
794
+  yyset_in(rules_file, yyscanner);
795
+  yyset_extra(compiler, yyscanner);
796
+  yyparse(yyscanner, compiler);
797
+  yylex_destroy(yyscanner);
798
+
799
+#ifdef REAL_YARA
800
+  return compiler->errors;
801
+#else
802
+  return 0;
803
+#endif
804
+}