Browse code

YARA work in progress: add parser skeleton, add string and rule queuing.

Steven Morgan authored on 2014/10/15 08:18:46
Showing 8 changed files
... ...
@@ -446,6 +446,8 @@ libclamav_la_SOURCES = \
446 446
 	yara_grammar.y \
447 447
 	yara_lexer.l \
448 448
 	yara_lexer.h \
449
+	yara_parser.c \
450
+	yara_parser.h \
449 451
 	yara_clam.h
450 452
 
451 453
 libclamav_la_SOURCES += bignum.h\
... ...
@@ -240,13 +240,13 @@ am_libclamav_la_OBJECTS = libclamav_la-matcher-ac.lo \
240 240
 	libclamav_la-www.lo libclamav_la-stats_json.lo \
241 241
 	libclamav_la-hostid.lo libclamav_la-openioc.lo \
242 242
 	libclamav_la-yara_grammar.lo libclamav_la-yara_lexer.lo \
243
-	libclamav_la-fp_add.lo libclamav_la-fp_add_d.lo \
244
-	libclamav_la-fp_addmod.lo libclamav_la-fp_cmp.lo \
245
-	libclamav_la-fp_cmp_d.lo libclamav_la-fp_cmp_mag.lo \
246
-	libclamav_la-fp_sub.lo libclamav_la-fp_sub_d.lo \
247
-	libclamav_la-fp_submod.lo libclamav_la-s_fp_add.lo \
248
-	libclamav_la-s_fp_sub.lo libclamav_la-fp_radix_size.lo \
249
-	libclamav_la-fp_read_radix.lo \
243
+	libclamav_la-yara_parser.lo libclamav_la-fp_add.lo \
244
+	libclamav_la-fp_add_d.lo libclamav_la-fp_addmod.lo \
245
+	libclamav_la-fp_cmp.lo libclamav_la-fp_cmp_d.lo \
246
+	libclamav_la-fp_cmp_mag.lo libclamav_la-fp_sub.lo \
247
+	libclamav_la-fp_sub_d.lo libclamav_la-fp_submod.lo \
248
+	libclamav_la-s_fp_add.lo libclamav_la-s_fp_sub.lo \
249
+	libclamav_la-fp_radix_size.lo libclamav_la-fp_read_radix.lo \
250 250
 	libclamav_la-fp_read_signed_bin.lo \
251 251
 	libclamav_la-fp_read_unsigned_bin.lo \
252 252
 	libclamav_la-fp_reverse.lo libclamav_la-fp_s_rmap.lo \
... ...
@@ -828,10 +828,11 @@ libclamav_la_SOURCES = matcher-ac.c matcher-ac.h matcher-bm.c \
828 828
 	iso9660.h arc4.c arc4.h rijndael.c rijndael.h crtmgr.c \
829 829
 	crtmgr.h asn1.c asn1.h fpu.c fpu.h stats.c stats.h www.c www.h \
830 830
 	stats_json.c stats_json.h hostid.c hostid.h openioc.c \
831
-	openioc.h yara_grammar.y yara_lexer.l yara_lexer.h yara_clam.h \
832
-	bignum.h bignum_fast.h tomsfastmath/addsub/fp_add.c \
833
-	tomsfastmath/addsub/fp_add_d.c tomsfastmath/addsub/fp_addmod.c \
834
-	tomsfastmath/addsub/fp_cmp.c tomsfastmath/addsub/fp_cmp_d.c \
831
+	openioc.h yara_grammar.y yara_lexer.l yara_lexer.h \
832
+	yara_parser.c yara_parser.h yara_clam.h bignum.h bignum_fast.h \
833
+	tomsfastmath/addsub/fp_add.c tomsfastmath/addsub/fp_add_d.c \
834
+	tomsfastmath/addsub/fp_addmod.c tomsfastmath/addsub/fp_cmp.c \
835
+	tomsfastmath/addsub/fp_cmp_d.c \
835 836
 	tomsfastmath/addsub/fp_cmp_mag.c tomsfastmath/addsub/fp_sub.c \
836 837
 	tomsfastmath/addsub/fp_sub_d.c tomsfastmath/addsub/fp_submod.c \
837 838
 	tomsfastmath/addsub/s_fp_add.c tomsfastmath/addsub/s_fp_sub.c \
... ...
@@ -1236,6 +1237,7 @@ distclean-compile:
1236 1236
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-xz_iface.Plo@am__quote@
1237 1237
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-yara_grammar.Plo@am__quote@
1238 1238
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-yara_lexer.Plo@am__quote@
1239
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-yara_parser.Plo@am__quote@
1239 1240
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-yc.Plo@am__quote@
1240 1241
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_nocxx_la-bytecode_nojit.Plo@am__quote@
1241 1242
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unrar.Plo@am__quote@
... ...
@@ -2242,6 +2244,13 @@ libclamav_la-yara_lexer.lo: yara_lexer.c
2242 2242
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2243 2243
 @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
2244 2244
 
2245
+libclamav_la-yara_parser.lo: yara_parser.c
2246
+@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_parser.lo -MD -MP -MF $(DEPDIR)/libclamav_la-yara_parser.Tpo -c -o libclamav_la-yara_parser.lo `test -f 'yara_parser.c' || echo '$(srcdir)/'`yara_parser.c
2247
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-yara_parser.Tpo $(DEPDIR)/libclamav_la-yara_parser.Plo
2248
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='yara_parser.c' object='libclamav_la-yara_parser.lo' libtool=yes @AMDEPBACKSLASH@
2249
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2250
+@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_parser.lo `test -f 'yara_parser.c' || echo '$(srcdir)/'`yara_parser.c
2251
+
2245 2252
 libclamav_la-fp_add.lo: tomsfastmath/addsub/fp_add.c
2246 2253
 @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
2247 2254
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-fp_add.Tpo $(DEPDIR)/libclamav_la-fp_add.Plo
... ...
@@ -2630,15 +2630,34 @@ static int cli_loadyara(FILE *fs, const char *dbname, struct cl_engine *engine,
2630 2630
     char * current_condition = NULL;
2631 2631
     int rc = CL_SUCCESS;
2632 2632
     uint32_t line = 0;
2633
-    uint32_t rule = 0;
2634 2633
     uint8_t is_comment;
2635 2634
     uint8_t rule_state;
2636 2635
     YR_COMPILER compiler;
2636
+    YR_RULE * rule;
2637
+    YR_STRING * string;
2637 2638
 
2638
-    cli_errmsg("Loading yara signatures\n");
2639
+    compiler.last_result = ERROR_SUCCESS;
2640
+    STAILQ_INIT(&compiler.rules);
2641
+    STAILQ_INIT(&compiler.current_rule_strings);
2642
+
2643
+    //    cli_errmsg("Loading yara signatures\n");
2639 2644
 #if 0 /* for compilation */
2640 2645
     yr_lex_parse_rules_file(fs, &compiler);
2641 2646
 #endif
2647
+    while (!STAILQ_EMPTY(&compiler.rules)) {
2648
+        rule = STAILQ_FIRST(&compiler.rules);
2649
+        STAILQ_REMOVE(&compiler.rules, rule, _yc_rule, link);
2650
+        printf ("rule: %s+++++++++\n", rule->id);
2651
+        while (!STAILQ_EMPTY(&rule->strings)) {
2652
+            string = STAILQ_FIRST(&rule->strings);
2653
+            STAILQ_REMOVE(&rule->strings, string, _yc_string, link);
2654
+            printf ("    %s = \"%s\"\n", string->id, string->string);
2655
+            free(string->id);
2656
+            free(string);            
2657
+        }
2658
+        free(rule->id);
2659
+        free(rule);
2660
+    }
2642 2661
     return rc;
2643 2662
 }
2644 2663
 #endif
... ...
@@ -40,6 +40,8 @@ limitations under the License.
40 40
 #ifndef _YARA_CLAM_H_
41 41
 #define _YARA_CLAM_H_
42 42
 
43
+#include "shared/queue.h"
44
+ 
43 45
 #define LEX_BUF_SIZE  1024
44 46
 
45 47
 #define EXTERNAL_VARIABLE_TYPE_NULL          0
... ...
@@ -241,6 +243,7 @@ typedef struct _YR_META
241 241
 
242 242
 } YR_META;
243 243
 
244
+#if REAL_YARA
244 245
 typedef struct _YR_STRING
245 246
 {
246 247
   int32_t g_flags;
... ...
@@ -257,6 +260,7 @@ typedef struct _YR_STRING
257 257
     //  YR_MATCHES unconfirmed_matches[MAX_THREADS];
258 258
 
259 259
 } YR_STRING;
260
+#endif
260 261
 
261 262
 typedef struct _YR_EXTERNAL_VARIABLE
262 263
 {
... ...
@@ -318,13 +322,34 @@ struct RE {
318 318
 #define xtoi cli_hex2num
319 319
 #define strlcpy cli_strlcpy
320 320
 
321
+struct _yc_rule {
322
+    STAILQ_ENTRY(_yc_rule) link;
323
+    STAILQ_HEAD(sq, _yc_string) strings;
324
+    char * id;
325
+};
326
+typedef struct _yc_rule yc_rule;
327
+typedef struct _yc_string {
328
+    STAILQ_ENTRY(_yc_string) link;
329
+    char * id;
330
+    int32_t g_flags;
331
+    int32_t length;
332
+    
333
+    char* identifier;
334
+    uint8_t* string;
335
+} yc_string;
336
+
321 337
 typedef struct _yc_compiler {
322 338
   char                lex_buf[LEX_BUF_SIZE];
323 339
   char*               lex_buf_ptr;
324 340
   unsigned short      lex_buf_len;
341
+  int last_result;
342
+  STAILQ_HEAD(rq, _yc_rule) rules;
343
+  STAILQ_HEAD(cs, _yc_string) current_rule_strings;
325 344
 } yc_compiler;
326 345
 
327
-#define YR_COMPILER yc_compiler
346
+typedef yc_compiler YR_COMPILER;
347
+typedef yc_rule YR_RULE;
348
+typedef yc_string YR_STRING;
328 349
 
329 350
 #endif
330 351
 
... ...
@@ -59,6 +59,9 @@ limitations under the License.
59 59
 #define YYDEBUG 1 /* Set for development testing */
60 60
 #include "libclamav/yara_clam.h"
61 61
 #include "clamav-config.h"
62
+#include "libclamav/yara_grammar.h"
63
+#include "libclamav/yara_lexer.h"
64
+#include "libclamav/yara_parser.h"
62 65
 #endif
63 66
 
64 67
 #define YYERROR_VERBOSE
... ...
@@ -247,7 +250,6 @@ import
247 247
 rule
248 248
     : rule_modifiers _RULE_ _IDENTIFIER_ tags '{' meta strings condition '}'
249 249
       {
250
-#ifdef REAL_YARA
251 250
         int result = yr_parser_reduce_rule_declaration(
252 251
             yyscanner,
253 252
             $1,
... ...
@@ -259,10 +261,6 @@ rule
259 259
         yr_free($3);
260 260
 
261 261
         ERROR_IF(result != ERROR_SUCCESS);
262
-#else
263
-        cli_errmsg("parsing rule %s %s %s %s %s\n",
264
-                   $1,  $3, $4,  $6, $7 );
265
-#endif
266 262
       }
267 263
     ;
268 264
 
... ...
@@ -270,9 +268,7 @@ rule
270 270
 meta
271 271
     : /* empty */
272 272
       {
273
-          //#ifdef REAL_YARA
274 273
         $$ = NULL;
275
-        //#endif
276 274
       }
277 275
     | _META_ ':' meta_declarations
278 276
       {
... ...
@@ -518,7 +514,6 @@ string_declarations
518 518
 string_declaration
519 519
     : _STRING_IDENTIFIER_ '=' _TEXT_STRING_ string_modifiers
520 520
       {
521
-#ifdef REAL_YARA
522 521
         $$ = yr_parser_reduce_string_declaration(
523 522
             yyscanner,
524 523
             $4,
... ...
@@ -529,9 +524,6 @@ string_declaration
529 529
         yr_free($3);
530 530
 
531 531
         ERROR_IF($$ == NULL);
532
-#else
533
-        cli_errmsg("String delaration %s = %s, %s\n", $1, $3, $4);
534
-#endif
535 532
       }
536 533
     | _STRING_IDENTIFIER_ '='
537 534
       {
... ...
@@ -541,7 +533,6 @@ string_declaration
541 541
       }
542 542
       _REGEXP_ string_modifiers
543 543
       {
544
-#ifdef REAL_YARA
545 544
         $$ = yr_parser_reduce_string_declaration(
546 545
             yyscanner,
547 546
             $5 | STRING_GFLAGS_REGEXP,
... ...
@@ -552,11 +543,9 @@ string_declaration
552 552
         yr_free($4);
553 553
 
554 554
         ERROR_IF($$ == NULL);
555
-#endif
556 555
       }
557 556
     | _STRING_IDENTIFIER_ '=' _HEX_STRING_
558 557
       {
559
-#ifdef REAL_YARA
560 558
         $$ = yr_parser_reduce_string_declaration(
561 559
             yyscanner,
562 560
             STRING_GFLAGS_HEXADECIMAL,
... ...
@@ -567,7 +556,6 @@ string_declaration
567 567
         yr_free($3);
568 568
 
569 569
         ERROR_IF($$ == NULL);
570
-#endif
571 570
       }
572 571
     ;
573 572
 
... ...
@@ -296,6 +296,12 @@ include[ \t]+\"         {
296 296
     yyterminate();
297 297
   }
298 298
 #endif
299
+  yypop_buffer_state(yyscanner);
300
+
301
+  if (!YY_CURRENT_BUFFER)
302
+  {
303
+    yyterminate();
304
+  }
299 305
 }
300 306
 
301 307
 
302 308
new file mode 100644
... ...
@@ -0,0 +1,988 @@
0
+/*
1
+ * YARA parser for ClamAV: back-end functions
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
+    /*
21
+Copyright (c) 2013. The YARA Authors. All Rights Reserved.
22
+
23
+Licensed under the Apache License, Version 2.0 (the "License");
24
+you may not use this file except in compliance with the License.
25
+You may obtain a copy of the License at
26
+
27
+   http://www.apache.org/licenses/LICENSE-2.0
28
+
29
+Unless required by applicable law or agreed to in writing, software
30
+distributed under the License is distributed on an "AS IS" BASIS,
31
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
32
+See the License for the specific language governing permissions and
33
+limitations under the License.
34
+*/
35
+
36
+#include <stddef.h>
37
+#include <string.h>
38
+
39
+
40
+#ifdef REAL_YARA
41
+#include <yara/ahocorasick.h>
42
+#include <yara/arena.h>
43
+#include <yara/re.h>
44
+#include <yara/error.h>
45
+#include <yara/exec.h>
46
+#include <yara/object.h>
47
+#include <yara/utils.h>
48
+#include <yara/modules.h>
49
+#include <yara/parser.h>
50
+#include <yara/mem.h>
51
+#else
52
+#include <stdint.h>
53
+#include <stdio.h>
54
+#include "yara_clam.h"
55
+#include "yara_grammar.h"
56
+#include "yara_lexer.h"
57
+#include "others.h"
58
+#endif
59
+
60
+#define todigit(x)  ((x) >='A'&& (x) <='F')? \
61
+                    ((uint8_t) (x - 'A' + 10)) : \
62
+                    ((uint8_t) (x - '0'))
63
+
64
+
65
+#ifdef REAL_YARA
66
+int yr_parser_emit(
67
+    yyscan_t yyscanner,
68
+    int8_t instruction,
69
+    int8_t** instruction_address)
70
+{
71
+  return yr_arena_write_data(
72
+      yyget_extra(yyscanner)->code_arena,
73
+      &instruction,
74
+      sizeof(int8_t),
75
+      (void**) instruction_address);
76
+}
77
+
78
+
79
+int yr_parser_emit_with_arg(
80
+    yyscan_t yyscanner,
81
+    int8_t instruction,
82
+    int64_t argument,
83
+    int8_t** instruction_address)
84
+{
85
+  int result = yr_arena_write_data(
86
+      yyget_extra(yyscanner)->code_arena,
87
+      &instruction,
88
+      sizeof(int8_t),
89
+      (void**) instruction_address);
90
+
91
+  if (result == ERROR_SUCCESS)
92
+    result = yr_arena_write_data(
93
+        yyget_extra(yyscanner)->code_arena,
94
+        &argument,
95
+        sizeof(int64_t),
96
+        NULL);
97
+
98
+  return result;
99
+}
100
+
101
+
102
+int yr_parser_emit_with_arg_reloc(
103
+    yyscan_t yyscanner,
104
+    int8_t instruction,
105
+    int64_t argument,
106
+    int8_t** instruction_address)
107
+{
108
+  void* ptr;
109
+
110
+  int result = yr_arena_write_data(
111
+      yyget_extra(yyscanner)->code_arena,
112
+      &instruction,
113
+      sizeof(int8_t),
114
+      (void**) instruction_address);
115
+
116
+  if (result == ERROR_SUCCESS)
117
+    result = yr_arena_write_data(
118
+        yyget_extra(yyscanner)->code_arena,
119
+        &argument,
120
+        sizeof(int64_t),
121
+        &ptr);
122
+
123
+  if (result == ERROR_SUCCESS)
124
+    result = yr_arena_make_relocatable(
125
+        yyget_extra(yyscanner)->code_arena,
126
+        ptr,
127
+        0,
128
+        EOL);
129
+
130
+  return result;
131
+}
132
+
133
+
134
+int yr_parser_emit_pushes_for_strings(
135
+    yyscan_t yyscanner,
136
+    const char* identifier)
137
+{
138
+  YR_COMPILER* compiler = yyget_extra(yyscanner);
139
+  YR_STRING* string = compiler->current_rule_strings;
140
+
141
+  const char* string_identifier;
142
+  const char* target_identifier;
143
+
144
+  int matching = 0;
145
+
146
+  while(!STRING_IS_NULL(string))
147
+  {
148
+    // Don't generate pushes for strings chained to another one, we are
149
+    // only interested in non-chained strings or the head of the chain.
150
+
151
+    if (string->chained_to == NULL)
152
+    {
153
+      string_identifier = string->identifier;
154
+      target_identifier = identifier;
155
+
156
+      while (*target_identifier != '\0' &&
157
+             *string_identifier != '\0' &&
158
+             *target_identifier == *string_identifier)
159
+      {
160
+        target_identifier++;
161
+        string_identifier++;
162
+      }
163
+
164
+      if ((*target_identifier == '\0' && *string_identifier == '\0') ||
165
+           *target_identifier == '*')
166
+      {
167
+        yr_parser_emit_with_arg_reloc(
168
+            yyscanner,
169
+            OP_PUSH,
170
+            PTR_TO_UINT64(string),
171
+            NULL);
172
+
173
+        string->g_flags |= STRING_GFLAGS_REFERENCED;
174
+        matching++;
175
+      }
176
+    }
177
+
178
+    string = yr_arena_next_address(
179
+        compiler->strings_arena,
180
+        string,
181
+        sizeof(YR_STRING));
182
+  }
183
+
184
+  if (matching == 0)
185
+  {
186
+    yr_compiler_set_error_extra_info(compiler, identifier);
187
+    compiler->last_result = ERROR_UNDEFINED_STRING;
188
+  }
189
+
190
+  return compiler->last_result;
191
+}
192
+
193
+
194
+int yr_parser_check_types(
195
+    YR_COMPILER* compiler,
196
+    YR_OBJECT_FUNCTION* function,
197
+    const char* actual_args_fmt)
198
+{
199
+  int i;
200
+
201
+  char message[MAX_COMPILER_ERROR_EXTRA_INFO];
202
+
203
+  const char* expected = function->arguments_fmt;
204
+  const char* actual = actual_args_fmt;
205
+
206
+  i = 0;
207
+
208
+  while (*expected != '\0' || *actual != '\0')
209
+  {
210
+    i++;
211
+
212
+    if (*expected != *actual)
213
+    {
214
+      if (*expected == '\0' || *actual == '\0')
215
+      {
216
+        snprintf(
217
+            message,
218
+            sizeof(message),
219
+            "wrong number of arguments for \"%s\"",
220
+            function->identifier);
221
+
222
+        compiler->last_result = ERROR_WRONG_NUMBER_OF_ARGUMENTS;
223
+      }
224
+      else
225
+      {
226
+        snprintf(
227
+            message,
228
+            sizeof(message),
229
+            "wrong type for argument %i of \"%s\"",
230
+            i,
231
+            function->identifier);
232
+
233
+        compiler->last_result = ERROR_WRONG_TYPE;
234
+      }
235
+
236
+      yr_compiler_set_error_extra_info(compiler, message);
237
+      break;
238
+    }
239
+
240
+    expected++;
241
+    actual++;
242
+  }
243
+
244
+  return compiler->last_result;
245
+}
246
+
247
+
248
+YR_STRING* yr_parser_lookup_string(
249
+    yyscan_t yyscanner,
250
+    const char* identifier)
251
+{
252
+  YR_STRING* string;
253
+  YR_COMPILER* compiler = yyget_extra(yyscanner);
254
+
255
+  string = compiler->current_rule_strings;
256
+
257
+  while(!STRING_IS_NULL(string))
258
+  {
259
+    // If some string $a gets fragmented into multiple chained
260
+    // strings, all those fragments have the same $a identifier
261
+    // but we are interested in the heading fragment, which is
262
+    // that with chained_to == NULL
263
+
264
+    if (strcmp(string->identifier, identifier) == 0 &&
265
+        string->chained_to == NULL)
266
+    {
267
+      return string;
268
+    }
269
+
270
+    string = yr_arena_next_address(
271
+        compiler->strings_arena,
272
+        string,
273
+        sizeof(YR_STRING));
274
+  }
275
+
276
+  yr_compiler_set_error_extra_info(compiler, identifier);
277
+  compiler->last_result = ERROR_UNDEFINED_STRING;
278
+
279
+  return NULL;
280
+}
281
+
282
+
283
+int yr_parser_lookup_loop_variable(
284
+    yyscan_t yyscanner,
285
+    const char* identifier)
286
+{
287
+  YR_COMPILER* compiler = yyget_extra(yyscanner);
288
+  int i;
289
+
290
+  for (i = 0; i < compiler->loop_depth; i++)
291
+  {
292
+    if (compiler->loop_identifier[i] != NULL &&
293
+        strcmp(identifier, compiler->loop_identifier[i]) == 0)
294
+      return i;
295
+  }
296
+
297
+  return -1;
298
+}
299
+
300
+
301
+int _yr_parser_write_string(
302
+    const char* identifier,
303
+    int flags,
304
+    YR_COMPILER* compiler,
305
+    SIZED_STRING* str,
306
+    RE* re,
307
+    YR_STRING** string,
308
+    int* min_atom_length)
309
+{
310
+  SIZED_STRING* literal_string;
311
+  YR_AC_MATCH* new_match;
312
+
313
+  YR_ATOM_LIST_ITEM* atom;
314
+  YR_ATOM_LIST_ITEM* atom_list = NULL;
315
+
316
+  int result;
317
+  int max_string_len;
318
+  int free_literal = FALSE;
319
+
320
+  *string = NULL;
321
+
322
+  result = yr_arena_allocate_struct(
323
+      compiler->strings_arena,
324
+      sizeof(YR_STRING),
325
+      (void**) string,
326
+      offsetof(YR_STRING, identifier),
327
+      offsetof(YR_STRING, string),
328
+      offsetof(YR_STRING, chained_to),
329
+      EOL);
330
+
331
+  if (result != ERROR_SUCCESS)
332
+    return result;
333
+
334
+  result = yr_arena_write_string(
335
+      compiler->sz_arena,
336
+      identifier,
337
+      &(*string)->identifier);
338
+
339
+  if (result != ERROR_SUCCESS)
340
+    return result;
341
+
342
+  if (flags & STRING_GFLAGS_HEXADECIMAL ||
343
+      flags & STRING_GFLAGS_REGEXP)
344
+  {
345
+    literal_string = yr_re_extract_literal(re);
346
+
347
+    if (literal_string != NULL)
348
+    {
349
+      flags |= STRING_GFLAGS_LITERAL;
350
+      free_literal = TRUE;
351
+    }
352
+  }
353
+  else
354
+  {
355
+    literal_string = str;
356
+    flags |= STRING_GFLAGS_LITERAL;
357
+  }
358
+
359
+  (*string)->g_flags = flags;
360
+  (*string)->chained_to = NULL;
361
+
362
+  #ifdef PROFILING_ENABLED
363
+  (*string)->clock_ticks = 0;
364
+  #endif
365
+
366
+  memset((*string)->matches, 0,
367
+         sizeof((*string)->matches));
368
+
369
+  memset((*string)->unconfirmed_matches, 0,
370
+         sizeof((*string)->unconfirmed_matches));
371
+
372
+  if (flags & STRING_GFLAGS_LITERAL)
373
+  {
374
+    (*string)->length = literal_string->length;
375
+
376
+    result = yr_arena_write_data(
377
+        compiler->sz_arena,
378
+        literal_string->c_string,
379
+        literal_string->length,
380
+        (void*) &(*string)->string);
381
+
382
+    if (result == ERROR_SUCCESS)
383
+    {
384
+      result = yr_atoms_extract_from_string(
385
+          (uint8_t*) literal_string->c_string,
386
+          literal_string->length,
387
+          flags,
388
+          &atom_list);
389
+    }
390
+  }
391
+  else
392
+  {
393
+    result = yr_re_emit_code(re, compiler->re_code_arena);
394
+
395
+    if (result == ERROR_SUCCESS)
396
+      result = yr_atoms_extract_from_re(re, flags, &atom_list);
397
+  }
398
+
399
+  if (result == ERROR_SUCCESS)
400
+  {
401
+    // Add the string to Aho-Corasick automaton.
402
+
403
+    if (atom_list != NULL)
404
+    {
405
+      result = yr_ac_add_string(
406
+          compiler->automaton_arena,
407
+          compiler->automaton,
408
+          *string,
409
+          atom_list);
410
+    }
411
+    else
412
+    {
413
+      result = yr_arena_allocate_struct(
414
+          compiler->automaton_arena,
415
+          sizeof(YR_AC_MATCH),
416
+          (void**) &new_match,
417
+          offsetof(YR_AC_MATCH, string),
418
+          offsetof(YR_AC_MATCH, forward_code),
419
+          offsetof(YR_AC_MATCH, backward_code),
420
+          offsetof(YR_AC_MATCH, next),
421
+          EOL);
422
+
423
+      if (result == ERROR_SUCCESS)
424
+      {
425
+        new_match->backtrack = 0;
426
+        new_match->string = *string;
427
+        new_match->forward_code = re->root_node->forward_code;
428
+        new_match->backward_code = NULL;
429
+        new_match->next = compiler->automaton->root->matches;
430
+        compiler->automaton->root->matches = new_match;
431
+      }
432
+    }
433
+  }
434
+
435
+  atom = atom_list;
436
+
437
+  if (atom != NULL)
438
+    *min_atom_length = MAX_ATOM_LENGTH;
439
+  else
440
+    *min_atom_length = 0;
441
+
442
+  while (atom != NULL)
443
+  {
444
+    if (atom->atom_length < *min_atom_length)
445
+      *min_atom_length = atom->atom_length;
446
+    atom = atom->next;
447
+  }
448
+
449
+  if (flags & STRING_GFLAGS_LITERAL)
450
+  {
451
+    if (flags & STRING_GFLAGS_WIDE)
452
+      max_string_len = (*string)->length * 2;
453
+    else
454
+      max_string_len = (*string)->length;
455
+
456
+    if (max_string_len == *min_atom_length)
457
+      (*string)->g_flags |= STRING_GFLAGS_FITS_IN_ATOM;
458
+  }
459
+
460
+  if (free_literal)
461
+    yr_free(literal_string);
462
+
463
+  if (atom_list != NULL)
464
+    yr_atoms_list_destroy(atom_list);
465
+
466
+  return result;
467
+}
468
+
469
+#endif
470
+
471
+
472
+#include <stdint.h>
473
+#include <limits.h>
474
+
475
+
476
+YR_STRING* yr_parser_reduce_string_declaration(
477
+    yyscan_t yyscanner,
478
+    int32_t string_flags,
479
+    const char* identifier,
480
+    SIZED_STRING* str)
481
+{
482
+  int min_atom_length;
483
+  int min_atom_length_aux;
484
+  int re_flags = 0;
485
+
486
+  int32_t min_gap;
487
+  int32_t max_gap;
488
+
489
+  char message[512];
490
+
491
+  YR_COMPILER* compiler = yyget_extra(yyscanner);
492
+  YR_STRING* string = NULL;
493
+  YR_STRING* aux_string;
494
+  YR_STRING* prev_string;
495
+
496
+  RE* re = NULL;
497
+  RE* remainder_re;
498
+
499
+#if REAL_YARA
500
+  RE_ERROR re_error;
501
+
502
+  if (str->flags & SIZED_STRING_FLAGS_NO_CASE)
503
+    string_flags |= STRING_GFLAGS_NO_CASE;
504
+
505
+  if (str->flags & SIZED_STRING_FLAGS_DOT_ALL)
506
+    re_flags |= RE_FLAGS_DOT_ALL;
507
+
508
+  if (strcmp(identifier,"$") == 0)
509
+    string_flags |= STRING_GFLAGS_ANONYMOUS;
510
+
511
+  if (!(string_flags & STRING_GFLAGS_WIDE))
512
+    string_flags |= STRING_GFLAGS_ASCII;
513
+
514
+  if (string_flags & STRING_GFLAGS_NO_CASE)
515
+    re_flags |= RE_FLAGS_NO_CASE;
516
+#endif
517
+  // The STRING_GFLAGS_SINGLE_MATCH flag indicates that finding
518
+  // a single match for the string is enough. This is true in
519
+  // most cases, except when the string count (#) and string offset (@)
520
+  // operators are used. All strings are marked STRING_FLAGS_SINGLE_MATCH
521
+  // initially, and unmarked later if required.
522
+
523
+  string_flags |= STRING_GFLAGS_SINGLE_MATCH;
524
+
525
+  if (string_flags & STRING_GFLAGS_HEXADECIMAL ||
526
+      string_flags & STRING_GFLAGS_REGEXP)
527
+  {
528
+#if REAL_YARA
529
+    if (string_flags & STRING_GFLAGS_HEXADECIMAL)
530
+      compiler->last_result = yr_re_parse_hex(
531
+          str->c_string, re_flags, &re, &re_error);
532
+    else
533
+      compiler->last_result = yr_re_parse(
534
+          str->c_string, re_flags, &re, &re_error);
535
+
536
+    if (compiler->last_result != ERROR_SUCCESS)
537
+    {
538
+      snprintf(
539
+          message,
540
+          sizeof(message),
541
+          "invalid %s \"%s\": %s",
542
+          (string_flags & STRING_GFLAGS_HEXADECIMAL) ?
543
+              "hex string" : "regular expression",
544
+          identifier,
545
+          re_error.message);
546
+
547
+      yr_compiler_set_error_extra_info(
548
+          compiler, message);
549
+
550
+      goto _exit;
551
+    }
552
+
553
+    if (re->flags & RE_FLAGS_FAST_HEX_REGEXP)
554
+      string_flags |= STRING_GFLAGS_FAST_HEX_REGEXP;
555
+
556
+    compiler->last_result = yr_re_split_at_chaining_point(
557
+        re, &re, &remainder_re, &min_gap, &max_gap);
558
+
559
+    if (compiler->last_result != ERROR_SUCCESS)
560
+      goto _exit;
561
+
562
+    compiler->last_result = _yr_parser_write_string(
563
+        identifier,
564
+        string_flags,
565
+        compiler,
566
+        NULL,
567
+        re,
568
+        &string,
569
+        &min_atom_length);
570
+
571
+    if (compiler->last_result != ERROR_SUCCESS)
572
+      goto _exit;
573
+
574
+    if (remainder_re != NULL)
575
+    {
576
+      string->g_flags |= STRING_GFLAGS_CHAIN_TAIL | STRING_GFLAGS_CHAIN_PART;
577
+      string->chain_gap_min = min_gap;
578
+      string->chain_gap_max = max_gap;
579
+    }
580
+
581
+    // Use "aux_string" from now on, we want to keep the value of "string"
582
+    // because it will returned.
583
+
584
+    aux_string = string;
585
+
586
+    while (remainder_re != NULL)
587
+    {
588
+      // Destroy regexp pointed by 're' before yr_re_split_at_jmp
589
+      // overwrites 're' with another value.
590
+
591
+      yr_re_destroy(re);
592
+
593
+      compiler->last_result = yr_re_split_at_chaining_point(
594
+          remainder_re, &re, &remainder_re, &min_gap, &max_gap);
595
+
596
+      if (compiler->last_result != ERROR_SUCCESS)
597
+        goto _exit;
598
+
599
+      prev_string = aux_string;
600
+
601
+      compiler->last_result = _yr_parser_write_string(
602
+          identifier,
603
+          string_flags,
604
+          compiler,
605
+          NULL,
606
+          re,
607
+          &aux_string,
608
+          &min_atom_length_aux);
609
+
610
+      if (compiler->last_result != ERROR_SUCCESS)
611
+        goto _exit;
612
+
613
+      if (min_atom_length_aux < min_atom_length)
614
+        min_atom_length = min_atom_length_aux;
615
+
616
+      aux_string->g_flags |= STRING_GFLAGS_CHAIN_PART;
617
+      aux_string->chain_gap_min = min_gap;
618
+      aux_string->chain_gap_max = max_gap;
619
+
620
+      prev_string->chained_to = aux_string;
621
+    }
622
+#endif
623
+  }
624
+  else
625
+  {
626
+#if REAL_YARA
627
+    compiler->last_result = _yr_parser_write_string(
628
+        identifier,
629
+        string_flags,
630
+        compiler,
631
+        str,
632
+        NULL,
633
+        &string,
634
+        &min_atom_length);
635
+
636
+    if (compiler->last_result != ERROR_SUCCESS)
637
+      goto _exit;
638
+#endif
639
+  }
640
+
641
+
642
+  string = cli_calloc(1, sizeof(struct _yc_string));
643
+  if (string == NULL) {
644
+      cli_errmsg("yara_parser: no mem for struct _yc_string.\n");
645
+      compiler->last_result = CL_EMEM;
646
+      return NULL;
647
+  } 
648
+
649
+  string->id = cli_strdup(identifier);
650
+  if (str->length > 0) {
651
+      string->string = cli_calloc(1, str->length+1);
652
+      if (string->string == NULL) {
653
+          cli_errmsg("yara_parser: no mem for string->string.\n");
654
+          compiler->last_result = CL_EMEM;
655
+          return NULL;
656
+      } 
657
+      memcpy(string->string, (char *)&str->c_string, str->length);
658
+  }
659
+  STAILQ_INSERT_TAIL(&compiler->current_rule_strings, string, link);
660
+
661
+#if REAL_YARA
662
+  if (min_atom_length < 2 && compiler->callback != NULL)
663
+  {
664
+    snprintf(
665
+        message,
666
+        sizeof(message),
667
+        "%s is slowing down scanning%s",
668
+        string->identifier,
669
+        min_atom_length == 0 ? " (critical!)" : "");
670
+
671
+    yywarning(yyscanner, message);
672
+  }
673
+
674
+_exit:
675
+
676
+  if (re != NULL)
677
+    yr_re_destroy(re);
678
+#endif
679
+
680
+  if (compiler->last_result != ERROR_SUCCESS)
681
+    return NULL;
682
+
683
+  return string;
684
+}
685
+
686
+
687
+int yr_parser_reduce_rule_declaration(
688
+    yyscan_t yyscanner,
689
+    int32_t flags,
690
+    const char* identifier,
691
+    char* tags,
692
+    YR_STRING* strings,
693
+    YR_META* metas)
694
+{
695
+  YR_COMPILER* compiler = yyget_extra(yyscanner);
696
+
697
+  YR_RULE* rule;
698
+  YR_STRING* string;
699
+
700
+#if REAL_YARA
701
+  if (yr_hash_table_lookup(
702
+        compiler->rules_table,
703
+        identifier,
704
+        compiler->current_namespace->name) != NULL ||
705
+      yr_hash_table_lookup(
706
+        compiler->objects_table,
707
+        identifier,
708
+        compiler->current_namespace->name) != NULL)
709
+  {
710
+    // A rule or variable with the same identifier already exists, return the
711
+    // appropriate error.
712
+
713
+    yr_compiler_set_error_extra_info(compiler, identifier);
714
+    compiler->last_result = ERROR_DUPLICATE_IDENTIFIER;
715
+    return compiler->last_result;
716
+  }
717
+#else
718
+  //TBD: Scan the queue for duplicate.
719
+#endif
720
+
721
+  // Check for unreferenced (unused) strings.
722
+
723
+#if REAL_YARA
724
+  string = compiler->current_rule_strings;
725
+#else
726
+  string = STAILQ_FIRST(&compiler->current_rule_strings);
727
+#endif
728
+
729
+  while(!STRING_IS_NULL(string))
730
+  {
731
+    // Only the heading fragment in a chain of strings (the one with
732
+    // chained_to == NULL) must be referenced. All other fragments
733
+    // are never marked as referenced.
734
+
735
+#if REAL_YARA
736
+    if (!STRING_IS_REFERENCED(string) &&
737
+        string->chained_to == NULL)
738
+    {
739
+      yr_compiler_set_error_extra_info(compiler, string->identifier);
740
+      compiler->last_result = ERROR_UNREFERENCED_STRING;
741
+      break;
742
+    }
743
+
744
+    string = yr_arena_next_address(
745
+        compiler->strings_arena,
746
+        string,
747
+        sizeof(YR_STRING));
748
+#else
749
+  //TBD: String link.
750
+    //    STAILQ_REMOVE_HEAD(&compiler->current_rule_strings, link);
751
+    string = STAILQ_NEXT(string, link);
752
+#endif
753
+  }
754
+
755
+  if (compiler->last_result != ERROR_SUCCESS)
756
+    return compiler->last_result;
757
+
758
+#if REAL_YARA
759
+  FAIL_ON_COMPILER_ERROR(yr_arena_allocate_struct(
760
+      compiler->rules_arena,
761
+      sizeof(YR_RULE),
762
+      (void**) &rule,
763
+      offsetof(YR_RULE, identifier),
764
+      offsetof(YR_RULE, tags),
765
+      offsetof(YR_RULE, strings),
766
+      offsetof(YR_RULE, metas),
767
+      offsetof(YR_RULE, ns),
768
+      EOL));
769
+#else
770
+  rule = cli_calloc(1, sizeof(struct _yc_rule));
771
+  if (rule == NULL) {
772
+      cli_errmsg("yara_parser: no mem for struct _yc_rule.\n");
773
+      return CL_EMEM;
774
+  }
775
+  STAILQ_INIT(&rule->strings);
776
+  STAILQ_CONCAT(&rule->strings, &compiler->current_rule_strings);
777
+  STAILQ_INIT(&compiler->current_rule_strings);
778
+  rule->id = cli_strdup(identifier);
779
+
780
+#endif
781
+
782
+#if REAL_YARA
783
+  rule->g_flags = flags | compiler->current_rule_flags;
784
+  rule->tags = tags;
785
+  rule->strings = strings;
786
+  rule->metas = metas;
787
+  rule->ns = compiler->current_namespace;
788
+
789
+  #ifdef PROFILING_ENABLED
790
+  rule->clock_ticks = 0;
791
+  #endif
792
+
793
+  FAIL_ON_COMPILER_ERROR(yr_arena_write_string(
794
+      compiler->sz_arena,
795
+      identifier,
796
+      (char**) &rule->identifier));
797
+
798
+  FAIL_ON_COMPILER_ERROR(yr_parser_emit_with_arg_reloc(
799
+      yyscanner,
800
+      OP_MATCH_RULE,
801
+      PTR_TO_UINT64(rule),
802
+      NULL));
803
+
804
+  FAIL_ON_COMPILER_ERROR(yr_hash_table_add(
805
+      compiler->rules_table,
806
+      identifier,
807
+      compiler->current_namespace->name,
808
+      (void*) rule));
809
+
810
+  compiler->current_rule_flags = 0;
811
+  compiler->current_rule_strings = NULL;
812
+#else
813
+  STAILQ_INSERT_TAIL(&compiler->rules, rule, link); 
814
+#endif
815
+  return compiler->last_result;
816
+}
817
+
818
+int yr_parser_reduce_string_identifier(
819
+    yyscan_t yyscanner,
820
+    const char* identifier,
821
+    int8_t instruction)
822
+{
823
+  YR_STRING* string;
824
+  YR_COMPILER* compiler = yyget_extra(yyscanner);
825
+
826
+#if REAL_YARA
827
+  if (strcmp(identifier, "$") == 0)
828
+  {
829
+    if (compiler->loop_for_of_mem_offset >= 0)
830
+    {
831
+      yr_parser_emit_with_arg(
832
+          yyscanner,
833
+          OP_PUSH_M,
834
+          compiler->loop_for_of_mem_offset,
835
+          NULL);
836
+
837
+      yr_parser_emit(yyscanner, instruction, NULL);
838
+
839
+      if (instruction != OP_STR_FOUND)
840
+      {
841
+        string = compiler->current_rule_strings;
842
+
843
+        while(!STRING_IS_NULL(string))
844
+        {
845
+          string->g_flags &= ~STRING_GFLAGS_SINGLE_MATCH;
846
+          string = yr_arena_next_address(
847
+              compiler->strings_arena,
848
+              string,
849
+              sizeof(YR_STRING));
850
+        }
851
+      }
852
+    }
853
+    else
854
+    {
855
+      compiler->last_result = ERROR_MISPLACED_ANONYMOUS_STRING;
856
+    }
857
+  }
858
+  else
859
+  {
860
+    string = yr_parser_lookup_string(yyscanner, identifier);
861
+
862
+    if (string != NULL)
863
+    {
864
+      yr_parser_emit_with_arg_reloc(
865
+          yyscanner,
866
+          OP_PUSH,
867
+          PTR_TO_UINT64(string),
868
+          NULL);
869
+
870
+      if (instruction != OP_STR_FOUND)
871
+        string->g_flags &= ~STRING_GFLAGS_SINGLE_MATCH;
872
+
873
+      yr_parser_emit(yyscanner, instruction, NULL);
874
+
875
+      string->g_flags |= STRING_GFLAGS_REFERENCED;
876
+    }
877
+  }
878
+#endif
879
+  return compiler->last_result;
880
+}
881
+
882
+#if 0
883
+YR_META* yr_parser_reduce_meta_declaration(
884
+    yyscan_t yyscanner,
885
+    int32_t type,
886
+    const char* identifier,
887
+    const char* string,
888
+    int32_t integer)
889
+{
890
+  YR_COMPILER* compiler = yyget_extra(yyscanner);
891
+  YR_META* meta;
892
+
893
+  compiler->last_result = yr_arena_allocate_struct(
894
+      compiler->metas_arena,
895
+      sizeof(YR_META),
896
+      (void**) &meta,
897
+      offsetof(YR_META, identifier),
898
+      offsetof(YR_META, string),
899
+      EOL);
900
+
901
+  if (compiler->last_result != ERROR_SUCCESS)
902
+    return NULL;
903
+
904
+  compiler->last_result = yr_arena_write_string(
905
+      compiler->sz_arena,
906
+      identifier,
907
+      (char**) &meta->identifier);
908
+
909
+  if (compiler->last_result != ERROR_SUCCESS)
910
+    return NULL;
911
+
912
+  if (string != NULL)
913
+    compiler->last_result = yr_arena_write_string(
914
+        compiler->sz_arena,
915
+        string,
916
+        &meta->string);
917
+  else
918
+    meta->string = NULL;
919
+
920
+  if (compiler->last_result != ERROR_SUCCESS)
921
+    return NULL;
922
+
923
+  meta->integer = integer;
924
+  meta->type = type;
925
+
926
+  return meta;
927
+}
928
+
929
+
930
+int yr_parser_reduce_import(
931
+    yyscan_t yyscanner,
932
+    SIZED_STRING* module_name)
933
+{
934
+  YR_COMPILER* compiler = yyget_extra(yyscanner);
935
+  ///  YR_OBJECT* module_structure;
936
+
937
+  char* name;
938
+
939
+  module_structure = yr_hash_table_lookup(
940
+      compiler->objects_table,
941
+      module_name->c_string,
942
+      compiler->current_namespace->name);
943
+
944
+  // if module already imported, do nothing
945
+
946
+  if (module_structure != NULL)
947
+    return ERROR_SUCCESS;
948
+
949
+  compiler->last_result = yr_object_create(
950
+      OBJECT_TYPE_STRUCTURE,
951
+      module_name->c_string,
952
+      NULL,
953
+      &module_structure);
954
+
955
+  if (compiler->last_result == ERROR_SUCCESS)
956
+    compiler->last_result = yr_hash_table_add(
957
+        compiler->objects_table,
958
+        module_name->c_string,
959
+        compiler->current_namespace->name,
960
+        module_structure);
961
+
962
+  if (compiler->last_result == ERROR_SUCCESS)
963
+  {
964
+    compiler->last_result = yr_modules_do_declarations(
965
+        module_name->c_string,
966
+        module_structure);
967
+
968
+    if (compiler->last_result == ERROR_UNKNOWN_MODULE)
969
+      yr_compiler_set_error_extra_info(compiler, module_name->c_string);
970
+  }
971
+
972
+  if (compiler->last_result == ERROR_SUCCESS)
973
+    compiler->last_result = yr_arena_write_string(
974
+        compiler->sz_arena,
975
+        module_name->c_string,
976
+        &name);
977
+
978
+  if (compiler->last_result == ERROR_SUCCESS)
979
+    compiler->last_result = yr_parser_emit_with_arg_reloc(
980
+        yyscanner,
981
+        OP_IMPORT,
982
+        PTR_TO_UINT64(name),
983
+        NULL);
984
+
985
+  return compiler->last_result;
986
+}
987
+#endif
0 988
new file mode 100644
... ...
@@ -0,0 +1,102 @@
0
+/*
1
+Copyright (c) 2013. The YARA Authors. All Rights Reserved.
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
+#ifndef YR_PARSER_H
17
+#define YR_PARSER_H
18
+
19
+
20
+int yr_parser_emit(
21
+    yyscan_t yyscanner,
22
+    int8_t instruction,
23
+    int8_t** instruction_address);
24
+
25
+
26
+int yr_parser_emit_with_arg(
27
+    yyscan_t yyscanner,
28
+    int8_t instruction,
29
+    int64_t argument,
30
+    int8_t** instruction_address);
31
+
32
+
33
+int yr_parser_emit_with_arg_reloc(
34
+    yyscan_t yyscanner,
35
+    int8_t instruction,
36
+    int64_t argument,
37
+    int8_t** instruction_address);
38
+
39
+#if REAL_YARA
40
+int yr_parser_check_types(
41
+    YR_COMPILER* compiler,
42
+    YR_OBJECT_FUNCTION* function,
43
+    const char* actual_args_fmt);
44
+#endif
45
+
46
+YR_STRING* yr_parser_lookup_string(
47
+  yyscan_t yyscanner,
48
+  const char* identifier);
49
+
50
+
51
+int yr_parser_lookup_loop_variable(
52
+    yyscan_t yyscanner,
53
+    const char* identifier);
54
+
55
+
56
+int yr_parser_reduce_rule_declaration(
57
+    yyscan_t yyscanner,
58
+    int flags,
59
+    const char* identifier,
60
+    char* tags,
61
+    YR_STRING* strings,
62
+    YR_META* metas);
63
+
64
+
65
+YR_STRING* yr_parser_reduce_string_declaration(
66
+    yyscan_t yyscanner,
67
+    int flags,
68
+    const char* identifier,
69
+    SIZED_STRING* str);
70
+
71
+
72
+YR_META* yr_parser_reduce_meta_declaration(
73
+    yyscan_t yyscanner,
74
+    int32_t type,
75
+    const char* identifier,
76
+    const char* string,
77
+    int32_t integer);
78
+
79
+
80
+int yr_parser_reduce_string_identifier(
81
+    yyscan_t yyscanner,
82
+    const char* identifier,
83
+    int8_t instruction);
84
+
85
+
86
+int yr_parser_emit_pushes_for_strings(
87
+    yyscan_t yyscanner,
88
+    const char* identifier);
89
+
90
+
91
+int yr_parser_reduce_external(
92
+    yyscan_t yyscanner,
93
+    const char* identifier,
94
+    int8_t intruction);
95
+
96
+
97
+int yr_parser_reduce_import(
98
+    yyscan_t yyscanner,
99
+    SIZED_STRING* module_name);
100
+
101
+#endif