diff --git a/libyara/include/yara/limits.h b/libyara/include/yara/limits.h index af30d55e9a..ae4d1ac1d5 100644 --- a/libyara/include/yara/limits.h +++ b/libyara/include/yara/limits.h @@ -65,4 +65,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define LEX_BUF_SIZE 8192 +// Maximum allowed split ID, also limiting the number of split instructions +// allowed in a regular expression. This number can't be increased +// over 255 without changing RE_SPLIT_ID_TYPE. +#define RE_MAX_SPLIT_ID 128 + +// Maximum stack size for regexp evaluation +#define RE_MAX_STACK 1024 + +// Maximum code size for a compiled regexp +#define RE_MAX_CODE_SIZE 32768 + +// Maximum input size scanned by yr_re_exec +#define RE_SCAN_LIMIT 4096 + +// Maximum number of fibers +#define RE_MAX_FIBERS 1024 + +// Maximum number of levels in regexp's AST +#define RE_MAX_AST_LEVELS 2000 + #endif diff --git a/libyara/include/yara/re.h b/libyara/include/yara/re.h index b421e9bc1e..ebdb1fd8e8 100644 --- a/libyara/include/yara/re.h +++ b/libyara/include/yara/re.h @@ -136,6 +136,7 @@ struct RE_NODE struct RE_AST { uint32_t flags; + uint16_t levels; RE_NODE* root_node; }; diff --git a/libyara/re.c b/libyara/re.c index de20324ba7..959979ba28 100644 --- a/libyara/re.c +++ b/libyara/re.c @@ -52,23 +52,6 @@ order to avoid confusion with operating system threads. #include #include -// Maximum allowed split ID, also limiting the number of split instructions -// allowed in a regular expression. This number can't be increased -// over 255 without changing RE_SPLIT_ID_TYPE. -#define RE_MAX_SPLIT_ID 128 - -// Maximum stack size for regexp evaluation -#define RE_MAX_STACK 1024 - -// Maximum code size for a compiled regexp -#define RE_MAX_CODE_SIZE 32768 - -// Maximum input size scanned by yr_re_exec -#define RE_SCAN_LIMIT 4096 - -// Maximum number of fibers -#define RE_MAX_FIBERS 1024 - #define EMIT_BACKWARDS 0x01 #define EMIT_DONT_SET_FORWARDS_CODE 0x02 @@ -268,6 +251,7 @@ int yr_re_ast_create( return ERROR_INSUFFICIENT_MEMORY; (*re_ast)->flags = 0; + (*re_ast)->levels = 0; (*re_ast)->root_node = NULL; return ERROR_SUCCESS; diff --git a/libyara/re_grammar.c b/libyara/re_grammar.c index 4122c7d48a..51839f6f00 100644 --- a/libyara/re_grammar.c +++ b/libyara/re_grammar.c @@ -88,6 +88,14 @@ #define mark_as_not_fast_regexp() \ ((RE_AST*) yyget_extra(yyscanner))->flags &= ~RE_FLAGS_FAST_REGEXP +#define incr_ast_levels() \ + if (((RE_AST*) yyget_extra(yyscanner))->levels++ > RE_MAX_AST_LEVELS) \ + { \ + lex_env->last_error_code = ERROR_INVALID_REGULAR_EXPRESSION; \ + YYABORT; \ + } + + #define ERROR_IF(x, error) \ if (x) \ { \ @@ -102,7 +110,7 @@ } \ -#line 106 "re_grammar.c" /* yacc.c:339 */ +#line 114 "re_grammar.c" /* yacc.c:339 */ # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus @@ -170,14 +178,14 @@ extern int re_yydebug; union YYSTYPE { -#line 73 "re_grammar.y" /* yacc.c:355 */ +#line 81 "re_grammar.y" /* yacc.c:355 */ int integer; uint32_t range; RE_NODE* re_node; uint8_t* class_vector; -#line 181 "re_grammar.c" /* yacc.c:355 */ +#line 189 "re_grammar.c" /* yacc.c:355 */ }; typedef union YYSTYPE YYSTYPE; @@ -193,7 +201,7 @@ int re_yyparse (void *yyscanner, RE_LEX_ENVIRONMENT *lex_env); /* Copy the second part of user declarations. */ -#line 197 "re_grammar.c" /* yacc.c:358 */ +#line 205 "re_grammar.c" /* yacc.c:358 */ #ifdef short # undef short @@ -491,10 +499,10 @@ static const yytype_uint8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 104, 104, 109, 113, 117, 128, 146, 150, 161, - 175, 191, 205, 221, 244, 268, 290, 313, 317, 323, - 329, 335, 344, 348, 354, 362, 368, 374, 380, 386, - 392, 398 + 0, 112, 112, 117, 121, 125, 137, 156, 160, 173, + 187, 203, 217, 233, 256, 280, 302, 325, 329, 335, + 341, 347, 356, 362, 368, 376, 382, 388, 394, 400, + 406, 412 }; #endif @@ -1039,33 +1047,33 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, void *yyscanner, R switch (yytype) { case 6: /* _CLASS_ */ -#line 96 "re_grammar.y" /* yacc.c:1257 */ +#line 104 "re_grammar.y" /* yacc.c:1257 */ { yr_free(((*yyvaluep).class_vector)); } -#line 1045 "re_grammar.c" /* yacc.c:1257 */ +#line 1053 "re_grammar.c" /* yacc.c:1257 */ break; case 26: /* alternative */ -#line 97 "re_grammar.y" /* yacc.c:1257 */ +#line 105 "re_grammar.y" /* yacc.c:1257 */ { yr_re_node_destroy(((*yyvaluep).re_node)); } -#line 1051 "re_grammar.c" /* yacc.c:1257 */ +#line 1059 "re_grammar.c" /* yacc.c:1257 */ break; case 27: /* concatenation */ -#line 98 "re_grammar.y" /* yacc.c:1257 */ +#line 106 "re_grammar.y" /* yacc.c:1257 */ { yr_re_node_destroy(((*yyvaluep).re_node)); } -#line 1057 "re_grammar.c" /* yacc.c:1257 */ +#line 1065 "re_grammar.c" /* yacc.c:1257 */ break; case 28: /* repeat */ -#line 99 "re_grammar.y" /* yacc.c:1257 */ +#line 107 "re_grammar.y" /* yacc.c:1257 */ { yr_re_node_destroy(((*yyvaluep).re_node)); } -#line 1063 "re_grammar.c" /* yacc.c:1257 */ +#line 1071 "re_grammar.c" /* yacc.c:1257 */ break; case 29: /* single */ -#line 100 "re_grammar.y" /* yacc.c:1257 */ +#line 108 "re_grammar.y" /* yacc.c:1257 */ { yr_re_node_destroy(((*yyvaluep).re_node)); } -#line 1069 "re_grammar.c" /* yacc.c:1257 */ +#line 1077 "re_grammar.c" /* yacc.c:1257 */ break; @@ -1331,26 +1339,27 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); switch (yyn) { case 2: -#line 105 "re_grammar.y" /* yacc.c:1646 */ +#line 113 "re_grammar.y" /* yacc.c:1646 */ { RE_AST* re_ast = yyget_extra(yyscanner); re_ast->root_node = (yyvsp[0].re_node); } -#line 1340 "re_grammar.c" /* yacc.c:1646 */ +#line 1348 "re_grammar.c" /* yacc.c:1646 */ break; case 4: -#line 114 "re_grammar.y" /* yacc.c:1646 */ +#line 122 "re_grammar.y" /* yacc.c:1646 */ { (yyval.re_node) = (yyvsp[0].re_node); } -#line 1348 "re_grammar.c" /* yacc.c:1646 */ +#line 1356 "re_grammar.c" /* yacc.c:1646 */ break; case 5: -#line 118 "re_grammar.y" /* yacc.c:1646 */ +#line 126 "re_grammar.y" /* yacc.c:1646 */ { mark_as_not_fast_regexp(); + incr_ast_levels(); (yyval.re_node) = yr_re_node_create(RE_NODE_ALT, (yyvsp[-2].re_node), (yyvsp[0].re_node)); @@ -1359,15 +1368,16 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); ERROR_IF((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY); } -#line 1363 "re_grammar.c" /* yacc.c:1646 */ +#line 1372 "re_grammar.c" /* yacc.c:1646 */ break; case 6: -#line 129 "re_grammar.y" /* yacc.c:1646 */ +#line 138 "re_grammar.y" /* yacc.c:1646 */ { RE_NODE* node; mark_as_not_fast_regexp(); + incr_ast_levels(); node = yr_re_node_create(RE_NODE_EMPTY, NULL, NULL); @@ -1378,31 +1388,33 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); ERROR_IF((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY); } -#line 1382 "re_grammar.c" /* yacc.c:1646 */ +#line 1392 "re_grammar.c" /* yacc.c:1646 */ break; case 7: -#line 147 "re_grammar.y" /* yacc.c:1646 */ +#line 157 "re_grammar.y" /* yacc.c:1646 */ { (yyval.re_node) = (yyvsp[0].re_node); } -#line 1390 "re_grammar.c" /* yacc.c:1646 */ +#line 1400 "re_grammar.c" /* yacc.c:1646 */ break; case 8: -#line 151 "re_grammar.y" /* yacc.c:1646 */ +#line 161 "re_grammar.y" /* yacc.c:1646 */ { + incr_ast_levels(); + (yyval.re_node) = yr_re_node_create(RE_NODE_CONCAT, (yyvsp[-1].re_node), (yyvsp[0].re_node)); DESTROY_NODE_IF((yyval.re_node) == NULL, (yyvsp[-1].re_node)); DESTROY_NODE_IF((yyval.re_node) == NULL, (yyvsp[0].re_node)); ERROR_IF((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY); } -#line 1402 "re_grammar.c" /* yacc.c:1646 */ +#line 1414 "re_grammar.c" /* yacc.c:1646 */ break; case 9: -#line 162 "re_grammar.y" /* yacc.c:1646 */ +#line 174 "re_grammar.y" /* yacc.c:1646 */ { RE_AST* re_ast; @@ -1416,11 +1428,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); DESTROY_NODE_IF((yyval.re_node) == NULL, (yyvsp[-1].re_node)); ERROR_IF((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY); } -#line 1420 "re_grammar.c" /* yacc.c:1646 */ +#line 1432 "re_grammar.c" /* yacc.c:1646 */ break; case 10: -#line 176 "re_grammar.y" /* yacc.c:1646 */ +#line 188 "re_grammar.y" /* yacc.c:1646 */ { RE_AST* re_ast; @@ -1436,11 +1448,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.re_node)->greedy = FALSE; } -#line 1440 "re_grammar.c" /* yacc.c:1646 */ +#line 1452 "re_grammar.c" /* yacc.c:1646 */ break; case 11: -#line 192 "re_grammar.y" /* yacc.c:1646 */ +#line 204 "re_grammar.y" /* yacc.c:1646 */ { RE_AST* re_ast; @@ -1454,11 +1466,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); DESTROY_NODE_IF((yyval.re_node) == NULL, (yyvsp[-1].re_node)); ERROR_IF((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY); } -#line 1458 "re_grammar.c" /* yacc.c:1646 */ +#line 1470 "re_grammar.c" /* yacc.c:1646 */ break; case 12: -#line 206 "re_grammar.y" /* yacc.c:1646 */ +#line 218 "re_grammar.y" /* yacc.c:1646 */ { RE_AST* re_ast; @@ -1474,11 +1486,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.re_node)->greedy = FALSE; } -#line 1478 "re_grammar.c" /* yacc.c:1646 */ +#line 1490 "re_grammar.c" /* yacc.c:1646 */ break; case 13: -#line 222 "re_grammar.y" /* yacc.c:1646 */ +#line 234 "re_grammar.y" /* yacc.c:1646 */ { RE_AST* re_ast = yyget_extra(yyscanner); re_ast->flags |= RE_FLAGS_GREEDY; @@ -1501,11 +1513,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.re_node)->start = 0; (yyval.re_node)->end = 1; } -#line 1505 "re_grammar.c" /* yacc.c:1646 */ +#line 1517 "re_grammar.c" /* yacc.c:1646 */ break; case 14: -#line 245 "re_grammar.y" /* yacc.c:1646 */ +#line 257 "re_grammar.y" /* yacc.c:1646 */ { RE_AST* re_ast = yyget_extra(yyscanner); re_ast->flags |= RE_FLAGS_UNGREEDY; @@ -1529,11 +1541,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.re_node)->end = 1; (yyval.re_node)->greedy = FALSE; } -#line 1533 "re_grammar.c" /* yacc.c:1646 */ +#line 1545 "re_grammar.c" /* yacc.c:1646 */ break; case 15: -#line 269 "re_grammar.y" /* yacc.c:1646 */ +#line 281 "re_grammar.y" /* yacc.c:1646 */ { RE_AST* re_ast = yyget_extra(yyscanner); re_ast->flags |= RE_FLAGS_GREEDY; @@ -1555,11 +1567,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.re_node)->start = (yyvsp[0].range) & 0xFFFF;; (yyval.re_node)->end = (yyvsp[0].range) >> 16;; } -#line 1559 "re_grammar.c" /* yacc.c:1646 */ +#line 1571 "re_grammar.c" /* yacc.c:1646 */ break; case 16: -#line 291 "re_grammar.y" /* yacc.c:1646 */ +#line 303 "re_grammar.y" /* yacc.c:1646 */ { RE_AST* re_ast = yyget_extra(yyscanner); re_ast->flags |= RE_FLAGS_UNGREEDY; @@ -1582,77 +1594,79 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.re_node)->end = (yyvsp[-1].range) >> 16;; (yyval.re_node)->greedy = FALSE; } -#line 1586 "re_grammar.c" /* yacc.c:1646 */ +#line 1598 "re_grammar.c" /* yacc.c:1646 */ break; case 17: -#line 314 "re_grammar.y" /* yacc.c:1646 */ +#line 326 "re_grammar.y" /* yacc.c:1646 */ { (yyval.re_node) = (yyvsp[0].re_node); } -#line 1594 "re_grammar.c" /* yacc.c:1646 */ +#line 1606 "re_grammar.c" /* yacc.c:1646 */ break; case 18: -#line 318 "re_grammar.y" /* yacc.c:1646 */ +#line 330 "re_grammar.y" /* yacc.c:1646 */ { (yyval.re_node) = yr_re_node_create(RE_NODE_WORD_BOUNDARY, NULL, NULL); ERROR_IF((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY); } -#line 1604 "re_grammar.c" /* yacc.c:1646 */ +#line 1616 "re_grammar.c" /* yacc.c:1646 */ break; case 19: -#line 324 "re_grammar.y" /* yacc.c:1646 */ +#line 336 "re_grammar.y" /* yacc.c:1646 */ { (yyval.re_node) = yr_re_node_create(RE_NODE_NON_WORD_BOUNDARY, NULL, NULL); ERROR_IF((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY); } -#line 1614 "re_grammar.c" /* yacc.c:1646 */ +#line 1626 "re_grammar.c" /* yacc.c:1646 */ break; case 20: -#line 330 "re_grammar.y" /* yacc.c:1646 */ +#line 342 "re_grammar.y" /* yacc.c:1646 */ { (yyval.re_node) = yr_re_node_create(RE_NODE_ANCHOR_START, NULL, NULL); ERROR_IF((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY); } -#line 1624 "re_grammar.c" /* yacc.c:1646 */ +#line 1636 "re_grammar.c" /* yacc.c:1646 */ break; case 21: -#line 336 "re_grammar.y" /* yacc.c:1646 */ +#line 348 "re_grammar.y" /* yacc.c:1646 */ { (yyval.re_node) = yr_re_node_create(RE_NODE_ANCHOR_END, NULL, NULL); ERROR_IF((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY); } -#line 1634 "re_grammar.c" /* yacc.c:1646 */ +#line 1646 "re_grammar.c" /* yacc.c:1646 */ break; case 22: -#line 345 "re_grammar.y" /* yacc.c:1646 */ +#line 357 "re_grammar.y" /* yacc.c:1646 */ { + incr_ast_levels(); + (yyval.re_node) = (yyvsp[-1].re_node); } -#line 1642 "re_grammar.c" /* yacc.c:1646 */ +#line 1656 "re_grammar.c" /* yacc.c:1646 */ break; case 23: -#line 349 "re_grammar.y" /* yacc.c:1646 */ +#line 363 "re_grammar.y" /* yacc.c:1646 */ { (yyval.re_node) = yr_re_node_create(RE_NODE_ANY, NULL, NULL); ERROR_IF((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY); } -#line 1652 "re_grammar.c" /* yacc.c:1646 */ +#line 1666 "re_grammar.c" /* yacc.c:1646 */ break; case 24: -#line 355 "re_grammar.y" /* yacc.c:1646 */ +#line 369 "re_grammar.y" /* yacc.c:1646 */ { (yyval.re_node) = yr_re_node_create(RE_NODE_LITERAL, NULL, NULL); @@ -1660,71 +1674,71 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.re_node)->value = (yyvsp[0].integer); } -#line 1664 "re_grammar.c" /* yacc.c:1646 */ +#line 1678 "re_grammar.c" /* yacc.c:1646 */ break; case 25: -#line 363 "re_grammar.y" /* yacc.c:1646 */ +#line 377 "re_grammar.y" /* yacc.c:1646 */ { (yyval.re_node) = yr_re_node_create(RE_NODE_WORD_CHAR, NULL, NULL); ERROR_IF((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY); } -#line 1674 "re_grammar.c" /* yacc.c:1646 */ +#line 1688 "re_grammar.c" /* yacc.c:1646 */ break; case 26: -#line 369 "re_grammar.y" /* yacc.c:1646 */ +#line 383 "re_grammar.y" /* yacc.c:1646 */ { (yyval.re_node) = yr_re_node_create(RE_NODE_NON_WORD_CHAR, NULL, NULL); ERROR_IF((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY); } -#line 1684 "re_grammar.c" /* yacc.c:1646 */ +#line 1698 "re_grammar.c" /* yacc.c:1646 */ break; case 27: -#line 375 "re_grammar.y" /* yacc.c:1646 */ +#line 389 "re_grammar.y" /* yacc.c:1646 */ { (yyval.re_node) = yr_re_node_create(RE_NODE_SPACE, NULL, NULL); ERROR_IF((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY); } -#line 1694 "re_grammar.c" /* yacc.c:1646 */ +#line 1708 "re_grammar.c" /* yacc.c:1646 */ break; case 28: -#line 381 "re_grammar.y" /* yacc.c:1646 */ +#line 395 "re_grammar.y" /* yacc.c:1646 */ { (yyval.re_node) = yr_re_node_create(RE_NODE_NON_SPACE, NULL, NULL); ERROR_IF((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY); } -#line 1704 "re_grammar.c" /* yacc.c:1646 */ +#line 1718 "re_grammar.c" /* yacc.c:1646 */ break; case 29: -#line 387 "re_grammar.y" /* yacc.c:1646 */ +#line 401 "re_grammar.y" /* yacc.c:1646 */ { (yyval.re_node) = yr_re_node_create(RE_NODE_DIGIT, NULL, NULL); ERROR_IF((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY); } -#line 1714 "re_grammar.c" /* yacc.c:1646 */ +#line 1728 "re_grammar.c" /* yacc.c:1646 */ break; case 30: -#line 393 "re_grammar.y" /* yacc.c:1646 */ +#line 407 "re_grammar.y" /* yacc.c:1646 */ { (yyval.re_node) = yr_re_node_create(RE_NODE_NON_DIGIT, NULL, NULL); ERROR_IF((yyval.re_node) == NULL, ERROR_INSUFFICIENT_MEMORY); } -#line 1724 "re_grammar.c" /* yacc.c:1646 */ +#line 1738 "re_grammar.c" /* yacc.c:1646 */ break; case 31: -#line 399 "re_grammar.y" /* yacc.c:1646 */ +#line 413 "re_grammar.y" /* yacc.c:1646 */ { (yyval.re_node) = yr_re_node_create(RE_NODE_CLASS, NULL, NULL); @@ -1732,11 +1746,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); (yyval.re_node)->class_vector = (yyvsp[0].class_vector); } -#line 1736 "re_grammar.c" /* yacc.c:1646 */ +#line 1750 "re_grammar.c" /* yacc.c:1646 */ break; -#line 1740 "re_grammar.c" /* yacc.c:1646 */ +#line 1754 "re_grammar.c" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1964,5 +1978,5 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); #endif return yyresult; } -#line 407 "re_grammar.y" /* yacc.c:1906 */ +#line 421 "re_grammar.y" /* yacc.c:1906 */ diff --git a/libyara/re_grammar.h b/libyara/re_grammar.h index c673bd131b..8ba1c56dec 100644 --- a/libyara/re_grammar.h +++ b/libyara/re_grammar.h @@ -78,7 +78,7 @@ extern int re_yydebug; union YYSTYPE { -#line 73 "re_grammar.y" /* yacc.c:1909 */ +#line 81 "re_grammar.y" /* yacc.c:1909 */ int integer; uint32_t range; diff --git a/libyara/re_grammar.y b/libyara/re_grammar.y index 9a22b44cfb..9e88d24e85 100644 --- a/libyara/re_grammar.y +++ b/libyara/re_grammar.y @@ -46,6 +46,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define mark_as_not_fast_regexp() \ ((RE_AST*) yyget_extra(yyscanner))->flags &= ~RE_FLAGS_FAST_REGEXP +#define incr_ast_levels() \ + if (((RE_AST*) yyget_extra(yyscanner))->levels++ > RE_MAX_AST_LEVELS) \ + { \ + lex_env->last_error_code = ERROR_INVALID_REGULAR_EXPRESSION; \ + YYABORT; \ + } + + #define ERROR_IF(x, error) \ if (x) \ { \ @@ -117,6 +125,7 @@ alternative | alternative '|' concatenation { mark_as_not_fast_regexp(); + incr_ast_levels(); $$ = yr_re_node_create(RE_NODE_ALT, $1, $3); @@ -130,6 +139,7 @@ alternative RE_NODE* node; mark_as_not_fast_regexp(); + incr_ast_levels(); node = yr_re_node_create(RE_NODE_EMPTY, NULL, NULL); @@ -149,6 +159,8 @@ concatenation } | concatenation repeat { + incr_ast_levels(); + $$ = yr_re_node_create(RE_NODE_CONCAT, $1, $2); DESTROY_NODE_IF($$ == NULL, $1); @@ -343,6 +355,8 @@ repeat single : '(' alternative ')' { + incr_ast_levels(); + $$ = $2; } | '.'