1 /*
2  * YARA rule parser for ClamAV
3  *
4  * Copyright (C) 2014-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5  *
6  * Authors: Steven Morgan
7  *
8  * This program is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License version 2 as published by the
10  * Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along with
18  * this program; if not, write to the Free Software Foundation, Inc., 51
19  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21 /* This file was originally derived from yara 3.1.0 libyara/parser.y and is
22    revised for running YARA rules in ClamAV. Following is the YARA copyright. */
23 /*
24 Copyright (c) 2007-2013. The YARA Authors. All Rights Reserved.
25 
26 Licensed under the Apache License, Version 2.0 (the "License");
27 you may not use this file except in compliance with the License.
28 You may obtain a copy of the License at
29 
30    http://www.apache.org/licenses/LICENSE-2.0
31 
32 Unless required by applicable law or agreed to in writing, software
33 distributed under the License is distributed on an "AS IS" BASIS,
34 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
35 See the License for the specific language governing permissions and
36 limitations under the License.
37 */
38 
39 %code requires {
40 #include "yara_compiler.h"
41 }
42 
43 %{
44 
45 #include <assert.h>
46 #include <stdio.h>
47 #include <stdint.h>
48 #include <string.h>
49 #include <limits.h>
50 #include <stddef.h>
51 
52 #ifdef REAL_YARA
53 #include <yara/utils.h>
54 #include <yara/compiler.h>
55 #include <yara/object.h>
56 #include <yara/sizedstr.h>
57 #include <yara/exec.h>
58 #include <yara/error.h>
59 #include <yara/mem.h>
60 #include <yara/lexer.h>
61 #include <yara/parser.h>
62 #else
63 #include "yara_clam.h"
64 #include "yara_compiler.h"
65 #include "clamav-config.h"
66 #include "yara_grammar.h"
67 #include "yara_lexer.h"
68 #include "yara_parser.h"
69 #include "yara_exec.h"
70 #endif
71 
72 #define YYERROR_VERBOSE
73 
74 #define INTEGER_SET_ENUMERATION   1
75 #define INTEGER_SET_RANGE         2
76 
77 #define EXPRESSION_TYPE_BOOLEAN   1
78 #define EXPRESSION_TYPE_INTEGER   2
79 #define EXPRESSION_TYPE_STRING    3
80 #define EXPRESSION_TYPE_REGEXP    4
81 
82 
83 #define ERROR_IF(x) \
84     if (x) \
85     { \
86       yyerror(yyscanner, compiler, NULL); \
87       YYERROR; \
88     } \
89 
90 #define CHECK_TYPE_WITH_CLEANUP(actual_type, expected_type, op, cleanup) \
91     if (actual_type != expected_type) \
92     { \
93       switch(actual_type) \
94       { \
95         case EXPRESSION_TYPE_INTEGER: \
96           yr_compiler_set_error_extra_info( \
97               compiler, "wrong type \"integer\" for " op " operator"); \
98           break; \
99         case EXPRESSION_TYPE_STRING: \
100           yr_compiler_set_error_extra_info( \
101               compiler, "wrong type \"string\" for \"" op "\" operator"); \
102           break; \
103       } \
104       compiler->last_result = ERROR_WRONG_TYPE; \
105       cleanup; \
106       yyerror(yyscanner, compiler, NULL); \
107       YYERROR; \
108     }
109 
110 #define CHECK_TYPE(actual_type, expected_type, op) \
111     CHECK_TYPE_WITH_CLEANUP(actual_type, expected_type, op, ) \
112 
113 
114 #define MSG(op)  "wrong type \"string\" for \"" op "\" operator"
115 
116 %}
117 
118 
119 %expect 2   // expect 2 shift/reduce conflicts
120 
121 // %debug
122 %name-prefix="yara_yy"
123 %output "yara_grammar.c"
124 %pure-parser
125 %parse-param {void *yyscanner}
126 %parse-param {YR_COMPILER* compiler}
127 %lex-param {yyscan_t yyscanner}
128 %lex-param {YR_COMPILER* compiler}
129 
130 %token _RULE_
131 %token _PRIVATE_
132 %token _GLOBAL_
133 %token _META_
134 %token <string> _STRINGS_
135 %token _CONDITION_
136 %token <c_string> _IDENTIFIER_
137 %token <c_string> _STRING_IDENTIFIER_
138 %token <c_string> _STRING_COUNT_
139 %token <c_string> _STRING_OFFSET_
140 %token <c_string> _STRING_IDENTIFIER_WITH_WILDCARD_
141 %token <integer> _NUMBER_
142 %token <sized_string> _TEXT_STRING_
143 %token <sized_string> _HEX_STRING_
144 %token <sized_string> _REGEXP_
145 %token _ASCII_
146 %token _WIDE_
147 %token _NOCASE_
148 %token _FULLWORD_
149 %token _AT_
150 %token _FILESIZE_
151 %token _ENTRYPOINT_
152 %token _ALL_
153 %token _ANY_
154 %token _IN_
155 %token _OF_
156 %token _FOR_
157 %token _THEM_
158 %token _INT8_
159 %token _INT16_
160 %token _INT32_
161 %token _UINT8_
162 %token _UINT16_
163 %token _UINT32_
164 %token _MATCHES_
165 %token _CONTAINS_
166 %token _IMPORT_
167 
168 %token _TRUE_
169 %token _FALSE_
170 
171 %left _OR_
172 %left _AND_
173 %left '&' '|' '^'
174 %left _LT_ _LE_ _GT_ _GE_ _EQ_ _NEQ_ _IS_
175 %left _SHIFT_LEFT_ _SHIFT_RIGHT_
176 %left '+' '-'
177 %left '*' '\\' '%'
178 %right _NOT_
179 %right '~'
180 
181 %type <string> strings
182 %type <string> string_declaration
183 %type <string> string_declarations
184 
185 %type <meta> meta
186 %type <meta> meta_declaration
187 %type <meta> meta_declarations
188 
189 %type <c_string> tags
190 %type <c_string> tag_list
191 
192 %type <integer> string_modifier
193 %type <integer> string_modifiers
194 
195 %type <integer> integer_set
196 
197 %type <integer> rule_modifier
198 %type <integer> rule_modifiers
199 
200 %type <object> identifier
201 
202 %type <expression_type> primary_expression
203 %type <expression_type> boolean_expression
204 %type <expression_type> expression
205 %type <expression_type> regexp
206 
207 %type <c_string> arguments_list
208 
209 
210 %destructor { yr_free($$); } _IDENTIFIER_
211 %destructor { yr_free($$); } _STRING_IDENTIFIER_
212 %destructor { yr_free($$); } _STRING_COUNT_
213 %destructor { yr_free($$); } _STRING_OFFSET_
214 %destructor { yr_free($$); } _STRING_IDENTIFIER_WITH_WILDCARD_
215 %destructor { yr_free($$); } _TEXT_STRING_
216 %destructor { yr_free($$); } _HEX_STRING_
217 %destructor { yr_free($$); } _REGEXP_
218 
219 %union {
220   SIZED_STRING*   sized_string;
221   char*           c_string;
222   int8_t          expression_type;
223   int64_t         integer;
224   YR_STRING*      string;
225   YR_META*        meta;
226   YR_OBJECT*      object;
227 }
228 
229 
230 %%
231 
232 rules
233     : /* empty */
234     | rules rule
235     | rules import
236     | rules error rule      /* on error skip until next rule..*/
237     | rules error "include" /* .. or include statement */
238     ;
239 
240 
241 import
242     : _IMPORT_ _TEXT_STRING_
243       {
244         int result = yr_parser_reduce_import(yyscanner, $2);
245 
246         yr_free($2);
247 
248         ERROR_IF(result != ERROR_SUCCESS);
249       }
250     ;
251 
252 
253 rule
254     : rule_modifiers _RULE_ _IDENTIFIER_ tags '{' meta strings condition '}'
255       {
256         int result = yr_parser_reduce_rule_declaration(
257             yyscanner,
258             $1,
259             $3,
260             $4,
261             $7,
262             $6);
263 
264         yr_free($3);
265 
266         ERROR_IF(result != ERROR_SUCCESS);
267       }
268     ;
269 
270 
271 meta
272     : /* empty */
273       {
274         $$ = NULL;
275       }
276     | _META_ ':' meta_declarations
277       {
278 #if REAL_YARA //Meta not supported
279         // Each rule have a list of meta-data info, consisting in a
280         // sequence of YR_META structures. The last YR_META structure does
281         // not represent a real meta-data, it's just a end-of-list marker
282         // identified by a specific type (META_TYPE_NULL). Here we
283         // write the end-of-list marker.
284 
285         YR_META null_meta;
286 
287         memset(&null_meta, 0xFF, sizeof(YR_META));
288         null_meta.type = META_TYPE_NULL;
289 
290         compiler->last_result = yr_arena_write_data(
291             compiler->metas_arena,
292             &null_meta,
293             sizeof(YR_META),
294             NULL);
295 
296 #endif
297         $$ = $3;
298 
299         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
300       }
301     ;
302 
303 
304 strings
305     : /* empty */
306       {
307         $$ = NULL;
308         compiler->current_rule_strings = $$;
309       }
310     | _STRINGS_ ':' string_declarations
311       {
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       }
334     ;
335 
336 
337 condition
338     : _CONDITION_ ':' boolean_expression
339     ;
340 
341 
342 rule_modifiers
343     : /* empty */                      { $$ = 0;  }
344     | rule_modifiers rule_modifier     { $$ = $1 | $2; }
345     ;
346 
347 
348 rule_modifier
349     : _PRIVATE_      { $$ = RULE_GFLAGS_PRIVATE; }
350     | _GLOBAL_       { $$ = RULE_GFLAGS_GLOBAL; }
351     ;
352 
353 
354 tags
355     : /* empty */
356       {
357         $$ = NULL;
358       }
359     | ':' tag_list
360       {
361 #if REAL_YARA //tags not supported
362         // Tags list is represented in the arena as a sequence
363         // of null-terminated strings, the sequence ends with an
364         // additional null character. Here we write the ending null
365         //character. Example: tag1\0tag2\0tag3\0\0
366 
367         compiler->last_result = yr_arena_write_string(
368             yyget_extra(yyscanner)->sz_arena, "", NULL);
369 
370         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
371 #endif
372 
373         $$ = $2;
374       }
375     ;
376 
377 
378 tag_list
379     : _IDENTIFIER_
380       {
381 #if REAL_YARA //tags not supported
382         char* identifier;
383 
384         compiler->last_result = yr_arena_write_string(
385             yyget_extra(yyscanner)->sz_arena, $1, &identifier);
386 
387 #endif
388         yr_free($1);
389 
390 #if REAL_YARA //tags not supported
391         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
392 
393         $$ = identifier;
394 #endif
395       }
396     | tag_list _IDENTIFIER_
397       {
398 #if REAL_YARA //tags not supported
399         char* tag_name = $1;
400         size_t tag_length = tag_name != NULL ? strlen(tag_name) : 0;
401 
402         while (tag_length > 0)
403         {
404           if (strcmp(tag_name, $2) == 0)
405           {
406             yr_compiler_set_error_extra_info(compiler, tag_name);
407             compiler->last_result = ERROR_DUPLICATE_TAG_IDENTIFIER;
408             break;
409           }
410 
411           tag_name = yr_arena_next_address(
412               yyget_extra(yyscanner)->sz_arena,
413               tag_name,
414               tag_length + 1);
415 
416           tag_length = tag_name != NULL ? strlen(tag_name) : 0;
417         }
418 
419         if (compiler->last_result == ERROR_SUCCESS)
420           compiler->last_result = yr_arena_write_string(
421               yyget_extra(yyscanner)->sz_arena, $2, NULL);
422 
423 #endif
424         yr_free($2);
425 
426         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
427 
428         $$ = $1;
429       }
430     ;
431 
432 
433 
434 meta_declarations
435     : meta_declaration                    {  $$ = $1; }
436     | meta_declarations meta_declaration  {  $$ = $1; }
437     ;
438 
439 
440 meta_declaration
441     : _IDENTIFIER_ '=' _TEXT_STRING_
442       {
443         SIZED_STRING* sized_string = $3;
444 
445         $$ = yr_parser_reduce_meta_declaration(
446             yyscanner,
447             META_TYPE_STRING,
448             $1,
449             sized_string->c_string,
450             0);
451 
452         yr_free($1);
453         yr_free($3);
454 
455         ERROR_IF($$ == NULL);
456       }
457     | _IDENTIFIER_ '=' _NUMBER_
458       {
459         $$ = yr_parser_reduce_meta_declaration(
460             yyscanner,
461             META_TYPE_INTEGER,
462             $1,
463             NULL,
464             $3);
465 
466         yr_free($1);
467 
468         ERROR_IF($$ == NULL);
469       }
470     | _IDENTIFIER_ '=' _TRUE_
471       {
472         $$ = yr_parser_reduce_meta_declaration(
473             yyscanner,
474             META_TYPE_BOOLEAN,
475             $1,
476             NULL,
477             TRUE);
478 
479         yr_free($1);
480 
481         ERROR_IF($$ == NULL);
482       }
483     | _IDENTIFIER_ '=' _FALSE_
484       {
485         $$ = yr_parser_reduce_meta_declaration(
486             yyscanner,
487             META_TYPE_BOOLEAN,
488             $1,
489             NULL,
490             FALSE);
491 
492         yr_free($1);
493 
494         ERROR_IF($$ == NULL);
495       }
496     ;
497 
498 
499 string_declarations
500     : string_declaration                      { $$ = $1; }
501     | string_declarations string_declaration  { $$ = $1; }
502     ;
503 
504 
505 string_declaration
506     : _STRING_IDENTIFIER_ '=' _TEXT_STRING_ string_modifiers
507       {
508         $$ = yr_parser_reduce_string_declaration(
509             yyscanner,
510             $4,
511             $1,
512             $3);
513 
514         yr_free($1);
515         yr_free($3);
516 
517         ERROR_IF($$ == NULL);
518       }
519     | _STRING_IDENTIFIER_ '='
520       {
521         compiler->error_line = yyget_lineno(yyscanner);
522       }
523       _REGEXP_ string_modifiers
524       {
525         $$ = yr_parser_reduce_string_declaration(
526             yyscanner,
527             $5 | STRING_GFLAGS_REGEXP,
528             $1,
529             $4);
530 
531         yr_free($1);
532         yr_free($4);
533 
534         ERROR_IF($$ == NULL);
535       }
536     | _STRING_IDENTIFIER_ '=' _HEX_STRING_
537       {
538         $$ = yr_parser_reduce_string_declaration(
539             yyscanner,
540             STRING_GFLAGS_HEXADECIMAL,
541             $1,
542             $3);
543 
544         yr_free($1);
545         yr_free($3);
546 
547         ERROR_IF($$ == NULL);
548       }
549     ;
550 
551 
552 string_modifiers
553     : /* empty */                         { $$ = 0; }
554     | string_modifiers string_modifier    { $$ = $1 | $2; }
555     ;
556 
557 
558 string_modifier
559     : _WIDE_        { $$ = STRING_GFLAGS_WIDE; }
560     | _ASCII_       { $$ = STRING_GFLAGS_ASCII; }
561     | _NOCASE_      { $$ = STRING_GFLAGS_NO_CASE; }
562     | _FULLWORD_    { $$ = STRING_GFLAGS_FULL_WORD; }
563     ;
564 
565 
566 identifier
567     : _IDENTIFIER_
568       {
569         YR_OBJECT* object = NULL;
570         YR_RULE* rule;
571 
572         char* id;
573         char* ns = NULL;
574 
575         int var_index;
576 
577         var_index = yr_parser_lookup_loop_variable(yyscanner, $1);
578 
579         if (var_index >= 0)
580         {
581          compiler->last_result = yr_parser_emit_with_arg(
582             yyscanner,
583             OP_PUSH_M,
584             LOOP_LOCAL_VARS * var_index,
585             NULL);
586 
587           $$ = (YR_OBJECT*) -1;
588         }
589         else
590         {
591           // Search for identifier within the global namespace, where the
592           // externals variables reside.
593           object = (YR_OBJECT*) yr_hash_table_lookup(
594                 compiler->objects_table,
595                 $1,
596                 NULL);
597           if (object == NULL)
598           {
599             // If not found, search within the current namespace.
600 
601             ns = compiler->current_namespace->name;
602             object = (YR_OBJECT*) yr_hash_table_lookup(
603                 compiler->objects_table,
604                 $1,
605                 ns);
606           }
607 
608           if (object != NULL)
609           {
610             compiler->last_result = yr_arena_write_string(
611                 compiler->sz_arena,
612                 $1,
613                 &id);
614 
615             if (compiler->last_result == ERROR_SUCCESS)
616               compiler->last_result = yr_parser_emit_with_arg_reloc(
617                   yyscanner,
618                   OP_OBJ_LOAD,
619                   PTR_TO_UINT64(id),
620                   NULL);
621 
622             $$ = object;
623           }
624           else
625           {
626            rule = (YR_RULE*) yr_hash_table_lookup(
627                 compiler->rules_table,
628                 $1,
629                 compiler->current_namespace->name);
630             if (rule != NULL)
631             {
632               compiler->last_result = yr_parser_emit_with_arg_reloc(
633                   yyscanner,
634                   OP_PUSH_RULE,
635                   PTR_TO_UINT64(rule),
636                   NULL);
637             }
638             else
639             {
640               yr_compiler_set_error_extra_info(compiler, $1);
641               compiler->last_result = ERROR_UNDEFINED_IDENTIFIER;
642             }
643 
644             $$ = (YR_OBJECT*) -2;
645           }
646         }
647 
648         yr_free($1);
649 
650         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
651       }
652     | identifier '.' _IDENTIFIER_
653       {
654         YR_OBJECT* object = $1;
655         YR_OBJECT* field = NULL;
656 
657         char* ident;
658 
659         if (object != NULL &&
660             object != (YR_OBJECT*) -1 &&    // not a loop variable identifier
661             object != (YR_OBJECT*) -2 &&    // not a rule identifier
662             object->type == OBJECT_TYPE_STRUCTURE)
663         {
664 #if REAL_YARA
665          field = yr_object_lookup_field(object, $3);
666 #endif
667           if (field != NULL)
668           {
669             compiler->last_result = yr_arena_write_string(
670               compiler->sz_arena,
671               $3,
672               &ident);
673 
674             if (compiler->last_result == ERROR_SUCCESS)
675               compiler->last_result = yr_parser_emit_with_arg_reloc(
676                   yyscanner,
677                   OP_OBJ_FIELD,
678                   PTR_TO_UINT64(ident),
679                   NULL);
680           }
681           else
682           {
683             yr_compiler_set_error_extra_info(compiler, $3);
684             compiler->last_result = ERROR_INVALID_FIELD_NAME;
685           }
686         }
687         else
688         {
689           yr_compiler_set_error_extra_info(
690               compiler,
691               object->identifier);
692 
693           compiler->last_result = ERROR_NOT_A_STRUCTURE;
694         }
695 
696         $$ = field;
697 
698         yr_free($3);
699 
700         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
701       }
702     | identifier '[' primary_expression ']'
703       {
704         if ($1 != NULL && $1->type == OBJECT_TYPE_ARRAY)
705         {
706           compiler->last_result = yr_parser_emit(
707               yyscanner,
708               OP_INDEX_ARRAY,
709               NULL);
710 
711           $$ = ((YR_OBJECT_ARRAY*) $1)->items->objects[0];
712         }
713         else
714         {
715           yr_compiler_set_error_extra_info(
716               compiler,
717               $1->identifier);
718 
719           compiler->last_result = ERROR_NOT_AN_ARRAY;
720         }
721 
722         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
723       }
724 
725     | identifier '(' arguments_list ')'
726       {
727         int args_count;
728 
729         if ($1 != NULL && $1->type == OBJECT_TYPE_FUNCTION)
730         {
731           compiler->last_result = yr_parser_check_types(
732               compiler, (YR_OBJECT_FUNCTION*) $1, $3);
733 
734           if (compiler->last_result == ERROR_SUCCESS)
735           {
736             args_count = strlen($3);
737 
738             compiler->last_result = yr_parser_emit_with_arg(
739                 yyscanner,
740                 OP_CALL,
741                 args_count,
742                 NULL);
743           }
744 
745           $$ = ((YR_OBJECT_FUNCTION*) $1)->return_obj;
746         }
747         else
748         {
749           yr_compiler_set_error_extra_info(
750               compiler,
751               $1->identifier);
752 
753           compiler->last_result = ERROR_NOT_A_FUNCTION;
754         }
755 
756         yr_free($3);
757 
758         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
759       }
760     ;
761 
762 
763 arguments_list
764     : /* empty */
765       {
766         $$ = yr_strdup("");
767       }
768     | expression
769       {
770         $$ = yr_malloc(MAX_FUNCTION_ARGS + 1);
771 
772         switch($1)
773         {
774           case EXPRESSION_TYPE_INTEGER:
775             strlcpy($$, "i", MAX_FUNCTION_ARGS);
776             break;
777           case EXPRESSION_TYPE_BOOLEAN:
778             strlcpy($$, "b", MAX_FUNCTION_ARGS);
779             break;
780           case EXPRESSION_TYPE_STRING:
781             strlcpy($$, "s", MAX_FUNCTION_ARGS);
782             break;
783           case EXPRESSION_TYPE_REGEXP:
784             strlcpy($$, "r", MAX_FUNCTION_ARGS);
785             break;
786         }
787 
788         ERROR_IF($$ == NULL);
789       }
790     | arguments_list ',' expression
791       {
792         if (strlen($1) == MAX_FUNCTION_ARGS)
793         {
794           compiler->last_result = ERROR_TOO_MANY_ARGUMENTS;
795         }
796         else
797         {
798           switch($3)
799           {
800             case EXPRESSION_TYPE_INTEGER:
801               strlcat($1, "i", MAX_FUNCTION_ARGS);
802               break;
803             case EXPRESSION_TYPE_BOOLEAN:
804               strlcat($1, "b", MAX_FUNCTION_ARGS);
805               break;
806             case EXPRESSION_TYPE_STRING:
807               strlcat($1, "s", MAX_FUNCTION_ARGS);
808               break;
809             case EXPRESSION_TYPE_REGEXP:
810               strlcat($1, "r", MAX_FUNCTION_ARGS);
811               break;
812           }
813         }
814 
815         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
816 
817         $$ = $1;
818       }
819     ;
820 
821 
822 regexp
823     : _REGEXP_
824       {
825 #ifdef REAL_YARA
826         SIZED_STRING* sized_string = $1;
827         RE* re;
828         RE_ERROR error;
829 
830         int re_flags = 0;
831 
832         if (sized_string->flags & SIZED_STRING_FLAGS_NO_CASE)
833           re_flags |= RE_FLAGS_NO_CASE;
834 
835         if (sized_string->flags & SIZED_STRING_FLAGS_DOT_ALL)
836           re_flags |= RE_FLAGS_DOT_ALL;
837 
838         compiler->last_result = yr_re_compile(
839             sized_string->c_string,
840             re_flags,
841             compiler->re_code_arena,
842             &re,
843             &error);
844 
845         yr_free($1);
846 
847         if (compiler->last_result == ERROR_INVALID_REGULAR_EXPRESSION)
848           yr_compiler_set_error_extra_info(compiler, error.message);
849 
850         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
851 
852         if (compiler->last_result == ERROR_SUCCESS)
853           compiler->last_result = yr_parser_emit_with_arg_reloc(
854               yyscanner,
855               OP_PUSH,
856               PTR_TO_UINT64(re->root_node->forward_code),
857               NULL);
858 
859         yr_re_destroy(re);
860 
861         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
862 #endif
863 
864         $$ = EXPRESSION_TYPE_REGEXP;
865       }
866     ;
867 
868 
869 boolean_expression
870     : expression
871       {
872         if ($1 == EXPRESSION_TYPE_STRING)
873         {
874           compiler->last_result = yr_parser_emit(
875               yyscanner,
876               OP_SZ_TO_BOOL,
877               NULL);
878 
879           ERROR_IF(compiler->last_result != ERROR_SUCCESS);
880         }
881 
882 
883         $$ = EXPRESSION_TYPE_BOOLEAN;
884       }
885     ;
886 
887 expression
888     : _TRUE_
889       {
890         compiler->last_result = yr_parser_emit_with_arg(
891             yyscanner, OP_PUSH, 1, NULL);
892 
893         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
894 
895         $$ = EXPRESSION_TYPE_BOOLEAN;
896       }
897     | _FALSE_
898       {
899         compiler->last_result = yr_parser_emit_with_arg(
900             yyscanner, OP_PUSH, 0, NULL);
901 
902         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
903 
904         $$ = EXPRESSION_TYPE_BOOLEAN;
905       }
906     | primary_expression _MATCHES_ regexp
907       {
908         CHECK_TYPE($1, EXPRESSION_TYPE_STRING, "matches");
909         CHECK_TYPE($3, EXPRESSION_TYPE_REGEXP, "matches");
910 
911         if (compiler->last_result == ERROR_SUCCESS)
912           compiler->last_result = yr_parser_emit(
913               yyscanner,
914               OP_MATCHES,
915               NULL);
916 
917         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
918 
919         $$ = EXPRESSION_TYPE_BOOLEAN;
920       }
921     | primary_expression _CONTAINS_ primary_expression
922       {
923         CHECK_TYPE($1, EXPRESSION_TYPE_STRING, "contains");
924         CHECK_TYPE($3, EXPRESSION_TYPE_STRING, "contains");
925 
926         compiler->last_result = yr_parser_emit(
927             yyscanner,
928             OP_CONTAINS,
929             NULL);
930 
931         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
932 
933         $$ = EXPRESSION_TYPE_BOOLEAN;
934       }
935     | _STRING_IDENTIFIER_
936       {
937         int result = yr_parser_reduce_string_identifier(
938             yyscanner,
939             $1,
940             OP_STR_FOUND);
941 
942         yr_free($1);
943 
944         ERROR_IF(result != ERROR_SUCCESS);
945 
946         $$ = EXPRESSION_TYPE_BOOLEAN;
947       }
948     | _STRING_IDENTIFIER_ _AT_ primary_expression
949       {
950         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "at");
951 
952         compiler->last_result = yr_parser_reduce_string_identifier(
953             yyscanner,
954             $1,
955             OP_STR_FOUND_AT);
956 
957         yr_free($1);
958 
959         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
960 
961         compiler->current_rule_clflags |= RULE_OFFSETS;
962 
963         $$ = EXPRESSION_TYPE_BOOLEAN;
964       }
965     | _STRING_IDENTIFIER_ _IN_ range
966       {
967         compiler->last_result = yr_parser_reduce_string_identifier(
968             yyscanner,
969             $1,
970             OP_STR_FOUND_IN);
971 
972         yr_free($1);
973 
974         ERROR_IF(compiler->last_result!= ERROR_SUCCESS);
975 
976         compiler->current_rule_clflags |= RULE_OFFSETS;
977 
978         $$ = EXPRESSION_TYPE_BOOLEAN;
979       }
980     | _FOR_ for_expression _IDENTIFIER_ _IN_
981       {
982         int var_index;
983 
984         if (compiler->loop_depth == MAX_LOOP_NESTING)
985           compiler->last_result = \
986               ERROR_LOOP_NESTING_LIMIT_EXCEEDED;
987 
988         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
989 
990         var_index = yr_parser_lookup_loop_variable(
991             yyscanner,
992             $3);
993 
994         if (var_index >= 0)
995         {
996           yr_compiler_set_error_extra_info(
997               compiler,
998               $3);
999 
1000           compiler->last_result = \
1001               ERROR_DUPLICATE_LOOP_IDENTIFIER;
1002         }
1003         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1004 
1005         // Push end-of-list marker
1006         compiler->last_result = yr_parser_emit_with_arg(
1007             yyscanner,
1008             OP_PUSH,
1009             UNDEFINED,
1010             NULL);
1011 
1012         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1013       }
1014       integer_set ':'
1015       {
1016         int mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
1017 
1018         int8_t* addr;
1019 
1020         // Clear counter for number of expressions evaluating
1021         // to TRUE.
1022         yr_parser_emit_with_arg(
1023             yyscanner, OP_CLEAR_M, mem_offset + 1, NULL);
1024 
1025         // Clear iterations counter
1026         yr_parser_emit_with_arg(
1027             yyscanner, OP_CLEAR_M, mem_offset + 2, NULL);
1028 
1029         if ($6 == INTEGER_SET_ENUMERATION)
1030         {
1031           // Pop the first integer
1032           yr_parser_emit_with_arg(
1033               yyscanner, OP_POP_M, mem_offset, &addr);
1034         }
1035         else // INTEGER_SET_RANGE
1036         {
1037           // Pop higher bound of set range
1038           yr_parser_emit_with_arg(
1039               yyscanner, OP_POP_M, mem_offset + 3, &addr);
1040 
1041           // Pop lower bound of set range
1042           yr_parser_emit_with_arg(
1043               yyscanner, OP_POP_M, mem_offset, NULL);
1044         }
1045         compiler->loop_address[compiler->loop_depth] = addr;
1046         compiler->loop_identifier[compiler->loop_depth] = $3;
1047         compiler->loop_depth++;
1048       }
1049       '(' boolean_expression ')'
1050       {
1051         int mem_offset;
1052 
1053         compiler->loop_depth--;
1054         mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
1055 
1056         // The value at the top of the stack is 1 if latest
1057         // expression was true or 0 otherwise. Add this value
1058         // to the counter for number of expressions evaluating
1059         // to true.
1060         yr_parser_emit_with_arg(
1061             yyscanner, OP_ADD_M, mem_offset + 1, NULL);
1062 
1063         // Increment iterations counter
1064         yr_parser_emit_with_arg(
1065             yyscanner, OP_INCR_M, mem_offset + 2, NULL);
1066 
1067         if ($6 == INTEGER_SET_ENUMERATION)
1068         {
1069           yr_parser_emit_with_arg_reloc(
1070               yyscanner,
1071               OP_JNUNDEF,
1072               PTR_TO_UINT64(
1073                   compiler->loop_address[compiler->loop_depth]),
1074               NULL);
1075         }
1076         else // INTEGER_SET_RANGE
1077         {
1078           // Increment lower bound of integer set
1079           yr_parser_emit_with_arg(
1080               yyscanner, OP_INCR_M, mem_offset, NULL);
1081 
1082           // Push lower bound of integer set
1083           yr_parser_emit_with_arg(
1084               yyscanner, OP_PUSH_M, mem_offset, NULL);
1085 
1086           // Push higher bound of integer set
1087           yr_parser_emit_with_arg(
1088               yyscanner, OP_PUSH_M, mem_offset + 3, NULL);
1089 
1090           // Compare higher bound with lower bound, do loop again
1091           // if lower bound is still lower or equal than higher bound
1092           yr_parser_emit_with_arg_reloc(
1093               yyscanner,
1094               OP_JLE,
1095               PTR_TO_UINT64(
1096                 compiler->loop_address[compiler->loop_depth]),
1097               NULL);
1098 
1099           yr_parser_emit(yyscanner, OP_POP, NULL);
1100           yr_parser_emit(yyscanner, OP_POP, NULL);
1101         }
1102 
1103         // Pop end-of-list marker.
1104         yr_parser_emit(yyscanner, OP_POP, NULL);
1105 
1106         // At this point the loop quantifier (any, all, 1, 2,..)
1107         // is at the top of the stack. Check if the quantifier
1108         // is undefined (meaning "all") and replace it with the
1109         // iterations counter in that case.
1110         yr_parser_emit_with_arg(
1111             yyscanner, OP_SWAPUNDEF, mem_offset + 2, NULL);
1112 
1113         // Compare the loop quantifier with the number of
1114         // expressions evaluating to TRUE.
1115         yr_parser_emit_with_arg(
1116             yyscanner, OP_PUSH_M, mem_offset + 1, NULL);
1117 
1118         yr_parser_emit(yyscanner, OP_LE, NULL);
1119 
1120         compiler->loop_identifier[compiler->loop_depth] = NULL;
1121         yr_free($3);
1122 
1123         $$ = EXPRESSION_TYPE_BOOLEAN;
1124       }
1125     | _FOR_ for_expression _OF_ string_set ':'
1126       {
1127         int mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
1128         int8_t* addr;
1129 
1130         if (compiler->loop_depth == MAX_LOOP_NESTING)
1131           compiler->last_result = \
1132             ERROR_LOOP_NESTING_LIMIT_EXCEEDED;
1133 
1134         if (compiler->loop_for_of_mem_offset != -1)
1135           compiler->last_result = \
1136             ERROR_NESTED_FOR_OF_LOOP;
1137 
1138         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1139 
1140         yr_parser_emit_with_arg(
1141             yyscanner, OP_CLEAR_M, mem_offset + 1, NULL);
1142 
1143         yr_parser_emit_with_arg(
1144             yyscanner, OP_CLEAR_M, mem_offset + 2, NULL);
1145 
1146         // Pop the first string.
1147         yr_parser_emit_with_arg(
1148             yyscanner, OP_POP_M, mem_offset, &addr);
1149 
1150         compiler->loop_for_of_mem_offset = mem_offset;
1151         compiler->loop_address[compiler->loop_depth] = addr;
1152         compiler->loop_identifier[compiler->loop_depth] = NULL;
1153         compiler->loop_depth++;
1154       }
1155       '(' boolean_expression ')'
1156       {
1157         int mem_offset;
1158 
1159         compiler->loop_depth--;
1160         compiler->loop_for_of_mem_offset = -1;
1161 
1162         mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
1163 
1164         // Increment counter by the value returned by the
1165         // boolean expression (0 or 1).
1166         yr_parser_emit_with_arg(
1167             yyscanner, OP_ADD_M, mem_offset + 1, NULL);
1168 
1169         // Increment iterations counter.
1170         yr_parser_emit_with_arg(
1171             yyscanner, OP_INCR_M, mem_offset + 2, NULL);
1172 
1173         // If next string is not undefined, go back to the
1174         // beginning of the loop.
1175         yr_parser_emit_with_arg_reloc(
1176             yyscanner,
1177             OP_JNUNDEF,
1178             PTR_TO_UINT64(
1179                 compiler->loop_address[compiler->loop_depth]),
1180             NULL);
1181 
1182         // Pop end-of-list marker.
1183         yr_parser_emit(yyscanner, OP_POP, NULL);
1184 
1185         // At this point the loop quantifier (any, all, 1, 2,..)
1186         // is at top of the stack. Check if the quantifier is
1187         // undefined (meaning "all") and replace it with the
1188         // iterations counter in that case.
1189         yr_parser_emit_with_arg(
1190             yyscanner, OP_SWAPUNDEF, mem_offset + 2, NULL);
1191 
1192         // Compare the loop quantifier with the number of
1193         // expressions evaluating to TRUE.
1194         yr_parser_emit_with_arg(
1195             yyscanner, OP_PUSH_M, mem_offset + 1, NULL);
1196 
1197         yr_parser_emit(yyscanner, OP_LE, NULL);
1198         $$ = EXPRESSION_TYPE_BOOLEAN;
1199 
1200       }
1201     | for_expression _OF_ string_set
1202       {
1203         yr_parser_emit(yyscanner, OP_OF, NULL);
1204 
1205         $$ = EXPRESSION_TYPE_BOOLEAN;
1206       }
1207     | _NOT_ boolean_expression
1208       {
1209         yr_parser_emit(yyscanner, OP_NOT, NULL);
1210 
1211         $$ = EXPRESSION_TYPE_BOOLEAN;
1212       }
1213     | boolean_expression _AND_ boolean_expression
1214       {
1215         yr_parser_emit(yyscanner, OP_AND, NULL);
1216 
1217         $$ = EXPRESSION_TYPE_BOOLEAN;
1218       }
1219     | boolean_expression _OR_ boolean_expression
1220       {
1221         CHECK_TYPE($1, EXPRESSION_TYPE_BOOLEAN, "or");
1222 
1223         yr_parser_emit(yyscanner, OP_OR, NULL);
1224 
1225         $$ = EXPRESSION_TYPE_BOOLEAN;
1226       }
1227     | primary_expression _LT_ primary_expression
1228       {
1229         CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "<");
1230         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "<");
1231 
1232         yr_parser_emit(yyscanner, OP_LT, NULL);
1233 
1234         $$ = EXPRESSION_TYPE_BOOLEAN;
1235       }
1236     | primary_expression _GT_ primary_expression
1237       {
1238         CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, ">");
1239         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, ">");
1240 
1241         yr_parser_emit(yyscanner, OP_GT, NULL);
1242 
1243         $$ = EXPRESSION_TYPE_BOOLEAN;
1244       }
1245     | primary_expression _LE_ primary_expression
1246       {
1247         CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "<=");
1248         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "<=");
1249 
1250         yr_parser_emit(yyscanner, OP_LE, NULL);
1251 
1252         $$ = EXPRESSION_TYPE_BOOLEAN;
1253       }
1254     | primary_expression _GE_ primary_expression
1255       {
1256         CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, ">=");
1257         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, ">=");
1258 
1259         yr_parser_emit(yyscanner, OP_GE, NULL);
1260 
1261         $$ = EXPRESSION_TYPE_BOOLEAN;
1262       }
1263     | primary_expression _EQ_ primary_expression
1264       {
1265         if ($1 != $3)
1266         {
1267           yr_compiler_set_error_extra_info(
1268               compiler, "mismatching types for == operator");
1269           compiler->last_result = ERROR_WRONG_TYPE;
1270         }
1271         else if ($1 == EXPRESSION_TYPE_STRING)
1272         {
1273           compiler->last_result = yr_parser_emit(
1274               yyscanner,
1275               OP_SZ_EQ,
1276               NULL);
1277         }
1278         else
1279         {
1280           compiler->last_result = yr_parser_emit(
1281               yyscanner,
1282               OP_EQ,
1283               NULL);
1284         }
1285 
1286         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1287 
1288         $$ = EXPRESSION_TYPE_BOOLEAN;
1289       }
1290     | primary_expression _IS_ primary_expression
1291       {
1292         if ($1 != $3)
1293         {
1294           yr_compiler_set_error_extra_info(
1295               compiler, "mismatching types for == operator");
1296           compiler->last_result = ERROR_WRONG_TYPE;
1297         }
1298         else if ($1 == EXPRESSION_TYPE_STRING)
1299         {
1300           compiler->last_result = yr_parser_emit(
1301               yyscanner,
1302               OP_SZ_EQ,
1303               NULL);
1304         }
1305         else
1306         {
1307           compiler->last_result = yr_parser_emit(
1308               yyscanner,
1309               OP_EQ,
1310               NULL);
1311         }
1312 
1313         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1314 
1315         $$ = EXPRESSION_TYPE_BOOLEAN;
1316       }
1317     | primary_expression _NEQ_ primary_expression
1318       {
1319         if ($1 != $3)
1320         {
1321           yr_compiler_set_error_extra_info(
1322               compiler, "mismatching types for != operator");
1323           compiler->last_result = ERROR_WRONG_TYPE;
1324         }
1325         else if ($1 == EXPRESSION_TYPE_STRING)
1326         {
1327           compiler->last_result = yr_parser_emit(
1328               yyscanner,
1329               OP_SZ_NEQ,
1330               NULL);
1331         }
1332         else
1333         {
1334           compiler->last_result = yr_parser_emit(
1335               yyscanner,
1336               OP_NEQ,
1337               NULL);
1338         }
1339 
1340         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1341 
1342         $$ = EXPRESSION_TYPE_BOOLEAN;
1343       }
1344     | primary_expression
1345       {
1346         $$ = $1;
1347       }
1348     |'(' expression ')'
1349       {
1350         $$ = $2;
1351       }
1352     ;
1353 
1354 
1355 integer_set
1356     : '(' integer_enumeration ')'  { $$ = INTEGER_SET_ENUMERATION; }
1357     | range                        { $$ = INTEGER_SET_RANGE; }
1358     ;
1359 
1360 
1361 range
1362     : '(' primary_expression '.' '.'  primary_expression ')'
1363       {
1364         if ($2 != EXPRESSION_TYPE_INTEGER)
1365         {
1366           yr_compiler_set_error_extra_info(
1367               compiler, "wrong type for range's lower bound");
1368           compiler->last_result = ERROR_WRONG_TYPE;
1369         }
1370 
1371         if ($5 != EXPRESSION_TYPE_INTEGER)
1372         {
1373           yr_compiler_set_error_extra_info(
1374               compiler, "wrong type for range's upper bound");
1375           compiler->last_result = ERROR_WRONG_TYPE;
1376         }
1377 
1378         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1379       }
1380     ;
1381 
1382 
1383 integer_enumeration
1384     : primary_expression
1385       {
1386         if ($1 != EXPRESSION_TYPE_INTEGER)
1387         {
1388           yr_compiler_set_error_extra_info(
1389               compiler, "wrong type for enumeration item");
1390           compiler->last_result = ERROR_WRONG_TYPE;
1391 
1392         }
1393 
1394         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1395       }
1396     | integer_enumeration ',' primary_expression
1397       {
1398         if ($3 != EXPRESSION_TYPE_INTEGER)
1399         {
1400           yr_compiler_set_error_extra_info(
1401               compiler, "wrong type for enumeration item");
1402           compiler->last_result = ERROR_WRONG_TYPE;
1403         }
1404 
1405         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1406       }
1407     ;
1408 
1409 
1410 string_set
1411     : '('
1412       {
1413         // Push end-of-list marker
1414         yr_parser_emit_with_arg(yyscanner, OP_PUSH, UNDEFINED, NULL);
1415       }
1416       string_enumeration ')'
1417     | _THEM_
1418       {
1419         yr_parser_emit_with_arg(yyscanner, OP_PUSH, UNDEFINED, NULL);
1420         yr_parser_emit_pushes_for_strings(yyscanner, "$*");
1421 #ifdef YARA_PROTO
1422         compiler->current_rule_clflags |= RULE_THEM;
1423 #endif
1424       }
1425     ;
1426 
1427 
1428 string_enumeration
1429     : string_enumeration_item
1430     | string_enumeration ',' string_enumeration_item
1431     ;
1432 
1433 
1434 string_enumeration_item
1435     : _STRING_IDENTIFIER_
1436       {
1437         yr_parser_emit_pushes_for_strings(yyscanner, $1);
1438         yr_free($1);
1439       }
1440     | _STRING_IDENTIFIER_WITH_WILDCARD_
1441       {
1442         yr_parser_emit_pushes_for_strings(yyscanner, $1);
1443         yr_free($1);
1444       }
1445     ;
1446 
1447 
1448 for_expression
1449     : primary_expression
1450     | _ALL_
1451       {
1452         yr_parser_emit_with_arg(yyscanner, OP_PUSH, UNDEFINED, NULL);
1453 #ifdef YARA_PROTO
1454         compiler->current_rule_clflags |= RULE_ALL;
1455 #endif
1456       }
1457     | _ANY_
1458       {
1459         yr_parser_emit_with_arg(yyscanner, OP_PUSH, 1, NULL);
1460 #ifdef YARA_PROTO
1461         compiler->current_rule_clflags |= RULE_ANY;
1462 #endif
1463       }
1464     ;
1465 
1466 
1467 primary_expression
1468     : '(' primary_expression ')'
1469       {
1470         $$ = $2;
1471       }
1472     | _FILESIZE_
1473       {
1474         compiler->last_result = yr_parser_emit(
1475             yyscanner, OP_FILESIZE, NULL);
1476 
1477         $$ = EXPRESSION_TYPE_INTEGER;
1478 
1479         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1480       }
1481     | _ENTRYPOINT_
1482       {
1483 #ifndef YARA_PROTO
1484         yywarning(yyscanner,
1485             "Using deprecated \"entrypoint\" keyword. Use the \"entry_point\" " "function from PE module instead.");
1486 #else
1487         compiler->current_rule_clflags |= RULE_EP;
1488 #endif
1489         compiler->last_result = yr_parser_emit(
1490             yyscanner, OP_ENTRYPOINT, NULL);
1491 
1492         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1493 
1494         $$ = EXPRESSION_TYPE_INTEGER;
1495       }
1496     | _INT8_  '(' primary_expression ')'
1497       {
1498         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "int8");
1499 
1500         compiler->last_result = yr_parser_emit(
1501             yyscanner, OP_INT8, NULL);
1502 
1503         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1504 
1505         $$ = EXPRESSION_TYPE_INTEGER;
1506       }
1507     | _INT16_ '(' primary_expression ')'
1508       {
1509         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "int16");
1510 
1511         compiler->last_result = yr_parser_emit(
1512             yyscanner, OP_INT16, NULL);
1513 
1514         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1515 
1516         $$ = EXPRESSION_TYPE_INTEGER;
1517       }
1518     | _INT32_ '(' primary_expression ')'
1519       {
1520         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "int32");
1521 
1522         compiler->last_result = yr_parser_emit(
1523             yyscanner, OP_INT32, NULL);
1524 
1525         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1526 
1527         $$ = EXPRESSION_TYPE_INTEGER;
1528       }
1529     | _UINT8_ '(' primary_expression ')'
1530       {
1531         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "uint8");
1532 
1533         compiler->last_result = yr_parser_emit(
1534             yyscanner, OP_UINT8, NULL);
1535 
1536         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1537 
1538         $$ = EXPRESSION_TYPE_INTEGER;
1539       }
1540     | _UINT16_ '(' primary_expression ')'
1541       {
1542         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "uint16");
1543 
1544         compiler->last_result = yr_parser_emit(
1545             yyscanner, OP_UINT16, NULL);
1546 
1547         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1548 
1549         $$ = EXPRESSION_TYPE_INTEGER;
1550       }
1551     | _UINT32_ '(' primary_expression ')'
1552       {
1553         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "uint32");
1554 
1555         compiler->last_result = yr_parser_emit(
1556             yyscanner, OP_UINT32, NULL);
1557 
1558         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1559 
1560         $$ = EXPRESSION_TYPE_INTEGER;
1561       }
1562     | _NUMBER_
1563       {
1564         compiler->last_result = yr_parser_emit_with_arg(
1565             yyscanner, OP_PUSH, $1, NULL);
1566 
1567         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1568 
1569         $$ = EXPRESSION_TYPE_INTEGER;
1570       }
1571     | _TEXT_STRING_
1572       {
1573 #if REAL_YARA
1574         SIZED_STRING* sized_string = $1;
1575 #endif
1576         char* string = NULL;
1577 
1578 #if REAL_YARA
1579         compiler->last_result = yr_arena_write_string(
1580             compiler->sz_arena,
1581             sized_string->c_string,
1582             &string);
1583 #endif
1584 
1585         yr_free($1);
1586 
1587         if (compiler->last_result == ERROR_SUCCESS)
1588           compiler->last_result = yr_parser_emit_with_arg_reloc(
1589               yyscanner,
1590               OP_PUSH,
1591               PTR_TO_UINT64(string),
1592               NULL);
1593 
1594         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1595 
1596         $$ = EXPRESSION_TYPE_STRING;
1597       }
1598     | _STRING_COUNT_
1599       {
1600         compiler->last_result = yr_parser_reduce_string_identifier(
1601             yyscanner,
1602             $1,
1603             OP_STR_COUNT);
1604 
1605         yr_free($1);
1606 
1607         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1608 
1609         $$ = EXPRESSION_TYPE_INTEGER;
1610       }
1611     | _STRING_OFFSET_ '[' primary_expression ']'
1612       {
1613         compiler->last_result = yr_parser_reduce_string_identifier(
1614             yyscanner,
1615             $1,
1616             OP_STR_OFFSET);
1617 
1618         yr_free($1);
1619 
1620         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1621 
1622         compiler->current_rule_clflags |= RULE_OFFSETS;
1623 
1624         $$ = EXPRESSION_TYPE_INTEGER;
1625       }
1626     | _STRING_OFFSET_
1627       {
1628         compiler->last_result = yr_parser_emit_with_arg(
1629             yyscanner,
1630             OP_PUSH,
1631             1,
1632             NULL);
1633 
1634         if (compiler->last_result == ERROR_SUCCESS)
1635           compiler->last_result = yr_parser_reduce_string_identifier(
1636               yyscanner,
1637               $1,
1638               OP_STR_OFFSET);
1639 
1640         yr_free($1);
1641 
1642         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1643 
1644         compiler->current_rule_clflags |= RULE_OFFSETS;
1645 
1646         $$ = EXPRESSION_TYPE_INTEGER;
1647       }
1648     | identifier
1649       {
1650         if ($1 == (YR_OBJECT*) -1)  // loop identifier
1651         {
1652           $$ = EXPRESSION_TYPE_INTEGER;
1653         }
1654         else if ($1 == (YR_OBJECT*) -2)  // rule identifier
1655         {
1656           $$ = EXPRESSION_TYPE_BOOLEAN;
1657         }
1658         else if ($1 != NULL)
1659         {
1660           compiler->last_result = yr_parser_emit(
1661               yyscanner, OP_OBJ_VALUE, NULL);
1662 
1663           switch($1->type)
1664           {
1665             case OBJECT_TYPE_INTEGER:
1666               $$ = EXPRESSION_TYPE_INTEGER;
1667               break;
1668             case OBJECT_TYPE_STRING:
1669               $$ = EXPRESSION_TYPE_STRING;
1670               break;
1671             default:
1672               assert(FALSE);
1673           }
1674         }
1675         else
1676         {
1677           yr_compiler_set_error_extra_info(compiler, $1->identifier);
1678           compiler->last_result = ERROR_WRONG_TYPE;
1679         }
1680 
1681         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
1682       }
1683     | primary_expression '+' primary_expression
1684       {
1685         CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "+");
1686         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "+");
1687 
1688         yr_parser_emit(yyscanner, OP_ADD, NULL);
1689 
1690         $$ = EXPRESSION_TYPE_INTEGER;
1691       }
1692     | primary_expression '-' primary_expression
1693       {
1694         CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "-");
1695         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "-");
1696 
1697         yr_parser_emit(yyscanner, OP_SUB, NULL);
1698 
1699         $$ = EXPRESSION_TYPE_INTEGER;
1700       }
1701     | primary_expression '*' primary_expression
1702       {
1703         CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "*");
1704         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "*");
1705 
1706         yr_parser_emit(yyscanner, OP_MUL, NULL);
1707 
1708         $$ = EXPRESSION_TYPE_INTEGER;
1709       }
1710     | primary_expression '\\' primary_expression
1711       {
1712         CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "\\");
1713         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "\\");
1714 
1715         yr_parser_emit(yyscanner, OP_DIV, NULL);
1716 
1717         $$ = EXPRESSION_TYPE_INTEGER;
1718       }
1719     | primary_expression '%' primary_expression
1720       {
1721         CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "%");
1722         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "%");
1723 
1724         yr_parser_emit(yyscanner, OP_MOD, NULL);
1725 
1726         $$ = EXPRESSION_TYPE_INTEGER;
1727       }
1728     | primary_expression '^' primary_expression
1729       {
1730         CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "^");
1731         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "^");
1732 
1733         yr_parser_emit(yyscanner, OP_XOR, NULL);
1734 
1735         $$ = EXPRESSION_TYPE_INTEGER;
1736       }
1737     | primary_expression '&' primary_expression
1738       {
1739         CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "^");
1740         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "^");
1741 
1742         yr_parser_emit(yyscanner, OP_AND, NULL);
1743 
1744         $$ = EXPRESSION_TYPE_INTEGER;
1745       }
1746     | primary_expression '|' primary_expression
1747       {
1748         CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "|");
1749         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "|");
1750 
1751         yr_parser_emit(yyscanner, OP_OR, NULL);
1752 
1753         $$ = EXPRESSION_TYPE_INTEGER;
1754       }
1755     | '~' primary_expression
1756       {
1757         CHECK_TYPE($2, EXPRESSION_TYPE_INTEGER, "~");
1758 
1759         yr_parser_emit(yyscanner, OP_NEG, NULL);
1760 
1761         $$ = EXPRESSION_TYPE_INTEGER;
1762       }
1763     | primary_expression _SHIFT_LEFT_ primary_expression
1764       {
1765         CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, "<<");
1766         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, "<<");
1767 
1768         yr_parser_emit(yyscanner, OP_SHL, NULL);
1769 
1770         $$ = EXPRESSION_TYPE_INTEGER;
1771       }
1772     | primary_expression _SHIFT_RIGHT_ primary_expression
1773       {
1774         CHECK_TYPE($1, EXPRESSION_TYPE_INTEGER, ">>");
1775         CHECK_TYPE($3, EXPRESSION_TYPE_INTEGER, ">>");
1776 
1777         yr_parser_emit(yyscanner, OP_SHR, NULL);
1778 
1779         $$ = EXPRESSION_TYPE_INTEGER;
1780       }
1781     | regexp
1782       {
1783         $$ = $1;
1784       }
1785     ;
1786 
1787 %%
1788