[Forensics-changes] [yara] 05/135: Fix bug causing segmentation fault when using nested loops

Hilko Bengen bengen at moszumanska.debian.org
Sat Jul 1 10:27:27 UTC 2017


This is an automated email from the git hooks/post-receive script.

bengen pushed a commit to annotated tag v3.1.0
in repository yara.

commit c9d6d935f61ad8b5dd79ca40de0dfd6038228919
Author: Victor M. Alvarez <plusvic at gmail.com>
Date:   Thu Mar 13 08:52:02 2014 +0100

    Fix bug causing segmentation fault when using nested loops
---
 libyara/Makefile.am |   2 +-
 libyara/compiler.c  |   6 +++
 libyara/grammar.c   | 137 ++++++++++++++++++++++++++++++----------------------
 libyara/grammar.y   |  21 ++++++++
 libyara/parser.c    |   7 +--
 libyara/yara.h      |   3 +-
 6 files changed, 113 insertions(+), 63 deletions(-)

diff --git a/libyara/Makefile.am b/libyara/Makefile.am
index 89c4fae..ba0d882 100644
--- a/libyara/Makefile.am
+++ b/libyara/Makefile.am
@@ -1,6 +1,6 @@
 AM_YFLAGS=-d
 
-AM_CFLAGS=-O4 -Wall -std=gnu99
+AM_CFLAGS=-g -O0 -Wall -std=gnu99
 
 ACLOCAL_AMFLAGS=-I m4
 
diff --git a/libyara/compiler.c b/libyara/compiler.c
index bcfe781..76b216d 100644
--- a/libyara/compiler.c
+++ b/libyara/compiler.c
@@ -51,6 +51,7 @@ int yr_compiler_create(
   new_compiler->current_rule_flags = 0;
   new_compiler->allow_includes = 1;
   new_compiler->loop_depth = 0;
+  new_compiler->loop_for_of_mem_offset = -1;
   new_compiler->compiled_rules_arena = NULL;
   new_compiler->externals_count = 0;
   new_compiler->namespaces_count = 0;
@@ -758,6 +759,11 @@ char* yr_compiler_get_error_message(
           buffer_size,
           "loop nesting limit exceeded");
       break;
+    case ERROR_NESTED_FOR_OF_LOOP:
+      snprintf(buffer,
+          buffer_size,
+          "'for <quantifier> of <string set>' loops can't be nested");
+      break;
     case ERROR_INTERNAL_FATAL_ERROR:
       snprintf(
           buffer,
diff --git a/libyara/grammar.c b/libyara/grammar.c
index ec6009c..b4a06a1 100644
--- a/libyara/grammar.c
+++ b/libyara/grammar.c
@@ -624,13 +624,13 @@ static const yytype_uint16 yyrline[] =
      324,   325,   329,   345,   358,   371,   387,   388,   392,   406,
      405,   423,   439,   440,   444,   445,   446,   447,   451,   452,
      456,   460,   490,   531,   535,   546,   557,   561,   572,   578,
-     615,   577,   714,   713,   782,   786,   789,   793,   797,   801,
-     805,   809,   813,   817,   821,   825,   832,   851,   865,   866,
-     870,   874,   875,   879,   878,   883,   890,   891,   894,   899,
-     906,   907,   911,   918,   919,   923,   927,   931,   935,   939,
-     943,   947,   951,   955,   966,   977,   991,  1018,  1022,  1026,
-    1030,  1034,  1038,  1042,  1046,  1050,  1054,  1058,  1064,  1065,
-    1066
+     615,   577,   726,   725,   802,   806,   809,   813,   817,   821,
+     825,   829,   833,   837,   841,   845,   852,   871,   885,   886,
+     890,   894,   895,   899,   898,   904,   911,   912,   915,   920,
+     927,   928,   932,   939,   940,   944,   948,   952,   956,   960,
+     964,   968,   972,   976,   987,   998,  1012,  1039,  1043,  1047,
+    1051,  1055,  1059,  1063,  1067,  1071,  1075,  1079,  1085,  1086,
+    1087
 };
 #endif
 
@@ -2342,9 +2342,11 @@ yyreduce:
                         }
                         else // INTEGER_SET_RANGE
                         {
+                          // Pop higher bound of set range
                           yr_parser_emit_with_arg(
                               yyscanner, POP_M, mem_offset + 3, &addr);
 
+                          // Pop lower bound of set range
                           yr_parser_emit_with_arg(
                               yyscanner, POP_M, mem_offset, NULL);
                         }
@@ -2356,7 +2358,7 @@ yyreduce:
     break;
 
   case 51:
-#line 649 "grammar.y"
+#line 651 "grammar.y"
     {
                         YR_COMPILER* compiler = yyget_extra(yyscanner);
                         int mem_offset;
@@ -2364,9 +2366,14 @@ yyreduce:
                         compiler->loop_depth--;
                         mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
 
+                        // The value at the top of the stack is 1 if latest
+                        // expression was true or 0 otherwise. Add this value
+                        // to the counter for number of expressions evaluating
+                        // to true.
                         yr_parser_emit_with_arg(
                             yyscanner, ADD_M, mem_offset + 1, NULL);
 
+                        // Increment iterations counter
                         yr_parser_emit_with_arg(
                             yyscanner, INCR_M, mem_offset + 2, NULL);
 
@@ -2381,15 +2388,20 @@ yyreduce:
                         }
                         else // INTEGER_SET_RANGE
                         {
+                          // Increment lower bound of integer set
                           yr_parser_emit_with_arg(
                               yyscanner, INCR_M, mem_offset, NULL);
 
+                          // Push lower bound of integer set
                           yr_parser_emit_with_arg(
                               yyscanner, PUSH_M, mem_offset, NULL);
 
+                          // Push higher bound of integer set
                           yr_parser_emit_with_arg(
                               yyscanner, PUSH_M, mem_offset + 3, NULL);
 
+                          // Compare higher bound with lower bound, do loop again
+                          // if lower bound is still lower or equal than higher bound
                           yr_parser_emit_with_arg_reloc(
                               yyscanner,
                               JLE,
@@ -2424,7 +2436,7 @@ yyreduce:
     break;
 
   case 52:
-#line 714 "grammar.y"
+#line 726 "grammar.y"
     {
                         YR_COMPILER* compiler = yyget_extra(yyscanner);
                         int mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
@@ -2434,6 +2446,10 @@ yyreduce:
                           compiler->last_result = \
                             ERROR_LOOP_NESTING_LIMIT_EXCEEDED;
 
+                        if (compiler->loop_for_of_mem_offset != -1)
+                          compiler->last_result = \
+                            ERROR_NESTED_FOR_OF_LOOP;
+
                         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
 
                         yr_parser_emit_with_arg(
@@ -2446,18 +2462,22 @@ yyreduce:
                         yr_parser_emit_with_arg(
                             yyscanner, POP_M, mem_offset, &addr);
 
+                        compiler->loop_for_of_mem_offset = mem_offset;
                         compiler->loop_address[compiler->loop_depth] = addr;
+                        compiler->loop_identifier[compiler->loop_depth] = NULL;
                         compiler->loop_depth++;
                       }
     break;
 
   case 53:
-#line 739 "grammar.y"
+#line 757 "grammar.y"
     {
                         YR_COMPILER* compiler = yyget_extra(yyscanner);
                         int mem_offset;
 
                         compiler->loop_depth--;
+                        compiler->loop_for_of_mem_offset = -1;
+
                         mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
 
                         // Increment counter by the value returned by the
@@ -2499,90 +2519,90 @@ yyreduce:
     break;
 
   case 54:
-#line 783 "grammar.y"
+#line 803 "grammar.y"
     {
                         yr_parser_emit(yyscanner, OF, NULL);
                       }
     break;
 
   case 55:
-#line 787 "grammar.y"
+#line 807 "grammar.y"
     {
                       }
     break;
 
   case 56:
-#line 790 "grammar.y"
+#line 810 "grammar.y"
     {
                         yr_parser_emit(yyscanner, NOT, NULL);
                       }
     break;
 
   case 57:
-#line 794 "grammar.y"
+#line 814 "grammar.y"
     {
                         yr_parser_emit(yyscanner, AND, NULL);
                       }
     break;
 
   case 58:
-#line 798 "grammar.y"
+#line 818 "grammar.y"
     {
                         yr_parser_emit(yyscanner, OR, NULL);
                       }
     break;
 
   case 59:
-#line 802 "grammar.y"
+#line 822 "grammar.y"
     {
                         yr_parser_emit(yyscanner, LT, NULL);
                       }
     break;
 
   case 60:
-#line 806 "grammar.y"
+#line 826 "grammar.y"
     {
                         yr_parser_emit(yyscanner, GT, NULL);
                       }
     break;
 
   case 61:
-#line 810 "grammar.y"
+#line 830 "grammar.y"
     {
                         yr_parser_emit(yyscanner, LE, NULL);
                       }
     break;
 
   case 62:
-#line 814 "grammar.y"
+#line 834 "grammar.y"
     {
                         yr_parser_emit(yyscanner, GE, NULL);
                       }
     break;
 
   case 63:
-#line 818 "grammar.y"
+#line 838 "grammar.y"
     {
                         yr_parser_emit(yyscanner, EQ, NULL);
                       }
     break;
 
   case 64:
-#line 822 "grammar.y"
+#line 842 "grammar.y"
     {
                         yr_parser_emit(yyscanner, EQ, NULL);
                       }
     break;
 
   case 65:
-#line 826 "grammar.y"
+#line 846 "grammar.y"
     {
                         yr_parser_emit(yyscanner, NEQ, NULL);
                       }
     break;
 
   case 66:
-#line 833 "grammar.y"
+#line 853 "grammar.y"
     {
           YR_COMPILER* compiler = yyget_extra(yyscanner);
           SIZED_STRING* sized_string = (yyvsp[(1) - (1)].sized_string);
@@ -2604,7 +2624,7 @@ yyreduce:
     break;
 
   case 67:
-#line 852 "grammar.y"
+#line 872 "grammar.y"
     {
           int result = yr_parser_reduce_external(
               yyscanner,
@@ -2618,24 +2638,25 @@ yyreduce:
     break;
 
   case 68:
-#line 865 "grammar.y"
+#line 885 "grammar.y"
     { (yyval.integer) = INTEGER_SET_ENUMERATION; }
     break;
 
   case 69:
-#line 866 "grammar.y"
+#line 886 "grammar.y"
     { (yyval.integer) = INTEGER_SET_RANGE; }
     break;
 
   case 73:
-#line 879 "grammar.y"
+#line 899 "grammar.y"
     {
+                // Push end-of-list marker
                 yr_parser_emit_with_arg(yyscanner, PUSH, UNDEFINED, NULL);
               }
     break;
 
   case 75:
-#line 884 "grammar.y"
+#line 905 "grammar.y"
     {
                 yr_parser_emit_with_arg(yyscanner, PUSH, UNDEFINED, NULL);
                 yr_parser_emit_pushes_for_strings(yyscanner, "$*");
@@ -2643,7 +2664,7 @@ yyreduce:
     break;
 
   case 78:
-#line 895 "grammar.y"
+#line 916 "grammar.y"
     {
                             yr_parser_emit_pushes_for_strings(yyscanner, (yyvsp[(1) - (1)].c_string));
                             yr_free((yyvsp[(1) - (1)].c_string));
@@ -2651,7 +2672,7 @@ yyreduce:
     break;
 
   case 79:
-#line 900 "grammar.y"
+#line 921 "grammar.y"
     {
                             yr_parser_emit_pushes_for_strings(yyscanner, (yyvsp[(1) - (1)].c_string));
                             yr_free((yyvsp[(1) - (1)].c_string));
@@ -2659,84 +2680,84 @@ yyreduce:
     break;
 
   case 81:
-#line 908 "grammar.y"
+#line 929 "grammar.y"
     {
                     yr_parser_emit_with_arg(yyscanner, PUSH, UNDEFINED, NULL);
                   }
     break;
 
   case 82:
-#line 912 "grammar.y"
+#line 933 "grammar.y"
     {
                     yr_parser_emit_with_arg(yyscanner, PUSH, 1, NULL);
                   }
     break;
 
   case 84:
-#line 920 "grammar.y"
+#line 941 "grammar.y"
     {
                 yr_parser_emit(yyscanner, SIZE, NULL);
               }
     break;
 
   case 85:
-#line 924 "grammar.y"
+#line 945 "grammar.y"
     {
                 yr_parser_emit(yyscanner, ENTRYPOINT, NULL);
               }
     break;
 
   case 86:
-#line 928 "grammar.y"
+#line 949 "grammar.y"
     {
                 yr_parser_emit(yyscanner, INT8, NULL);
               }
     break;
 
   case 87:
-#line 932 "grammar.y"
+#line 953 "grammar.y"
     {
                 yr_parser_emit(yyscanner, INT16, NULL);
               }
     break;
 
   case 88:
-#line 936 "grammar.y"
+#line 957 "grammar.y"
     {
                 yr_parser_emit(yyscanner, INT32, NULL);
               }
     break;
 
   case 89:
-#line 940 "grammar.y"
+#line 961 "grammar.y"
     {
                 yr_parser_emit(yyscanner, UINT8, NULL);
               }
     break;
 
   case 90:
-#line 944 "grammar.y"
+#line 965 "grammar.y"
     {
                 yr_parser_emit(yyscanner, UINT16, NULL);
               }
     break;
 
   case 91:
-#line 948 "grammar.y"
+#line 969 "grammar.y"
     {
                 yr_parser_emit(yyscanner, UINT32, NULL);
               }
     break;
 
   case 92:
-#line 952 "grammar.y"
+#line 973 "grammar.y"
     {
                 yr_parser_emit_with_arg(yyscanner, PUSH, (yyvsp[(1) - (1)].integer), NULL);
               }
     break;
 
   case 93:
-#line 956 "grammar.y"
+#line 977 "grammar.y"
     {
                 int result = yr_parser_reduce_string_identifier(
                     yyscanner,
@@ -2750,7 +2771,7 @@ yyreduce:
     break;
 
   case 94:
-#line 967 "grammar.y"
+#line 988 "grammar.y"
     {
                 int result = yr_parser_reduce_string_identifier(
                     yyscanner,
@@ -2764,7 +2785,7 @@ yyreduce:
     break;
 
   case 95:
-#line 978 "grammar.y"
+#line 999 "grammar.y"
     {
                 int result = yr_parser_emit_with_arg(yyscanner, PUSH, 1, NULL);
 
@@ -2781,7 +2802,7 @@ yyreduce:
     break;
 
   case 96:
-#line 992 "grammar.y"
+#line 1013 "grammar.y"
     {
                 YR_COMPILER* compiler = yyget_extra(yyscanner);
                 int var_index;
@@ -2811,77 +2832,77 @@ yyreduce:
     break;
 
   case 97:
-#line 1019 "grammar.y"
+#line 1040 "grammar.y"
     {
                 yr_parser_emit(yyscanner, ADD, NULL);
               }
     break;
 
   case 98:
-#line 1023 "grammar.y"
+#line 1044 "grammar.y"
     {
                 yr_parser_emit(yyscanner, SUB, NULL);
               }
     break;
 
   case 99:
-#line 1027 "grammar.y"
+#line 1048 "grammar.y"
     {
                 yr_parser_emit(yyscanner, MUL, NULL);
               }
     break;
 
   case 100:
-#line 1031 "grammar.y"
+#line 1052 "grammar.y"
     {
                 yr_parser_emit(yyscanner, DIV, NULL);
               }
     break;
 
   case 101:
-#line 1035 "grammar.y"
+#line 1056 "grammar.y"
     {
                 yr_parser_emit(yyscanner, MOD, NULL);
               }
     break;
 
   case 102:
-#line 1039 "grammar.y"
+#line 1060 "grammar.y"
     {
                 yr_parser_emit(yyscanner, XOR, NULL);
               }
     break;
 
   case 103:
-#line 1043 "grammar.y"
+#line 1064 "grammar.y"
     {
                 yr_parser_emit(yyscanner, AND, NULL);
               }
     break;
 
   case 104:
-#line 1047 "grammar.y"
+#line 1068 "grammar.y"
     {
                 yr_parser_emit(yyscanner, OR, NULL);
               }
     break;
 
   case 105:
-#line 1051 "grammar.y"
+#line 1072 "grammar.y"
     {
                 yr_parser_emit(yyscanner, NEG, NULL);
               }
     break;
 
   case 106:
-#line 1055 "grammar.y"
+#line 1076 "grammar.y"
     {
                 yr_parser_emit(yyscanner, SHL, NULL);
               }
     break;
 
   case 107:
-#line 1059 "grammar.y"
+#line 1080 "grammar.y"
     {
                 yr_parser_emit(yyscanner, SHR, NULL);
               }
@@ -2889,7 +2910,7 @@ yyreduce:
 
 
 /* Line 1267 of yacc.c.  */
-#line 2893 "grammar.c"
+#line 2914 "grammar.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -3103,7 +3124,7 @@ yyreturn:
 }
 
 
-#line 1069 "grammar.y"
+#line 1090 "grammar.y"
 
 
 
diff --git a/libyara/grammar.y b/libyara/grammar.y
index 867ff6b..77e7dec 100644
--- a/libyara/grammar.y
+++ b/libyara/grammar.y
@@ -634,9 +634,11 @@ boolean_expression  : '(' boolean_expression ')'
                         }
                         else // INTEGER_SET_RANGE
                         {
+                          // Pop higher bound of set range
                           yr_parser_emit_with_arg(
                               yyscanner, POP_M, mem_offset + 3, &addr);
 
+                          // Pop lower bound of set range
                           yr_parser_emit_with_arg(
                               yyscanner, POP_M, mem_offset, NULL);
                         }
@@ -653,9 +655,14 @@ boolean_expression  : '(' boolean_expression ')'
                         compiler->loop_depth--;
                         mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
 
+                        // The value at the top of the stack is 1 if latest
+                        // expression was true or 0 otherwise. Add this value
+                        // to the counter for number of expressions evaluating
+                        // to true.
                         yr_parser_emit_with_arg(
                             yyscanner, ADD_M, mem_offset + 1, NULL);
 
+                        // Increment iterations counter
                         yr_parser_emit_with_arg(
                             yyscanner, INCR_M, mem_offset + 2, NULL);
 
@@ -670,15 +677,20 @@ boolean_expression  : '(' boolean_expression ')'
                         }
                         else // INTEGER_SET_RANGE
                         {
+                          // Increment lower bound of integer set
                           yr_parser_emit_with_arg(
                               yyscanner, INCR_M, mem_offset, NULL);
 
+                          // Push lower bound of integer set
                           yr_parser_emit_with_arg(
                               yyscanner, PUSH_M, mem_offset, NULL);
 
+                          // Push higher bound of integer set
                           yr_parser_emit_with_arg(
                               yyscanner, PUSH_M, mem_offset + 3, NULL);
 
+                          // Compare higher bound with lower bound, do loop again
+                          // if lower bound is still lower or equal than higher bound
                           yr_parser_emit_with_arg_reloc(
                               yyscanner,
                               JLE,
@@ -720,6 +732,10 @@ boolean_expression  : '(' boolean_expression ')'
                           compiler->last_result = \
                             ERROR_LOOP_NESTING_LIMIT_EXCEEDED;
 
+                        if (compiler->loop_for_of_mem_offset != -1)
+                          compiler->last_result = \
+                            ERROR_NESTED_FOR_OF_LOOP;
+
                         ERROR_IF(compiler->last_result != ERROR_SUCCESS);
 
                         yr_parser_emit_with_arg(
@@ -732,7 +748,9 @@ boolean_expression  : '(' boolean_expression ')'
                         yr_parser_emit_with_arg(
                             yyscanner, POP_M, mem_offset, &addr);
 
+                        compiler->loop_for_of_mem_offset = mem_offset;
                         compiler->loop_address[compiler->loop_depth] = addr;
+                        compiler->loop_identifier[compiler->loop_depth] = NULL;
                         compiler->loop_depth++;
                       }
                       '(' boolean_expression ')'
@@ -741,6 +759,8 @@ boolean_expression  : '(' boolean_expression ')'
                         int mem_offset;
 
                         compiler->loop_depth--;
+                        compiler->loop_for_of_mem_offset = -1;
+
                         mem_offset = LOOP_LOCAL_VARS * compiler->loop_depth;
 
                         // Increment counter by the value returned by the
@@ -877,6 +897,7 @@ integer_enumeration : expression
 
 string_set  : '('
               {
+                // Push end-of-list marker
                 yr_parser_emit_with_arg(yyscanner, PUSH, UNDEFINED, NULL);
               }
               string_enumeration ')'
diff --git a/libyara/parser.c b/libyara/parser.c
index 8fb635a..f639261 100644
--- a/libyara/parser.c
+++ b/libyara/parser.c
@@ -692,12 +692,12 @@ int yr_parser_reduce_string_identifier(
 
   if (strcmp(identifier, "$") == 0)
   {
-    if (compiler->loop_depth > 0)
+    if (compiler->loop_for_of_mem_offset >= 0)
     {
       yr_parser_emit_with_arg(
           yyscanner,
           PUSH_M,
-          LOOP_LOCAL_VARS * (compiler->loop_depth - 1),
+          compiler->loop_for_of_mem_offset,
           NULL);
 
       yr_parser_emit(yyscanner, instruction, NULL);
@@ -851,7 +851,8 @@ int yr_parser_lookup_loop_variable(
 
   for (i = 0; i < compiler->loop_depth; i++)
   {
-    if (strcmp(identifier, compiler->loop_identifier[i]) == 0)
+    if (compiler->loop_identifier[i] != NULL &&
+        strcmp(identifier, compiler->loop_identifier[i]) == 0)
       return i;
   }
 
diff --git a/libyara/yara.h b/libyara/yara.h
index d4a275e..ca10117 100644
--- a/libyara/yara.h
+++ b/libyara/yara.h
@@ -88,7 +88,7 @@ typedef int32_t tidx_mask_t;
 #define ERROR_INVALID_ARGUMENT                  29
 #define ERROR_TOO_MANY_MATCHES                  30
 #define ERROR_INTERNAL_FATAL_ERROR              31
-
+#define ERROR_NESTED_FOR_OF_LOOP                32
 
 #define CALLBACK_MSG_RULE_MATCHING              1
 #define CALLBACK_MSG_RULE_NOT_MATCHING          2
@@ -563,6 +563,7 @@ typedef struct _YR_COMPILER
   int8_t*             loop_address[MAX_LOOP_NESTING];
   char*               loop_identifier[MAX_LOOP_NESTING];
   int                 loop_depth;
+  int                 loop_for_of_mem_offset;
 
   int                 allow_includes;
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/forensics/yara.git



More information about the forensics-changes mailing list