63
63
*/
64
64
#define RE_IS_CAPTURE_GROUP (x ) (((x) < RE_OP_NON_CAPTURE_GROUP_START) ? 1 : 0)
65
65
66
+ /**
67
+ * Check RegExp recursion depth limit
68
+ */
69
+ #ifdef REGEXP_RECURSION_LIMIT
70
+ JERRY_STATIC_ASSERT (REGEXP_RECURSION_LIMIT > 0 , regexp_recursion_limit_must_be_greater_than_zero );
71
+ #endif /* REGEXP_RECURSION_LIMIT */
72
+
66
73
/**
67
74
* Parse RegExp flags (global, ignoreCase, multiline)
68
75
*
@@ -364,6 +371,12 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
364
371
const lit_utf8_byte_t * str_p , /**< input string pointer */
365
372
const lit_utf8_byte_t * * out_str_p ) /**< [out] matching substring iterator */
366
373
{
374
+ #ifdef REGEXP_RECURSION_LIMIT
375
+ if (-- re_ctx_p -> recursion_counter == 0 )
376
+ {
377
+ return ecma_raise_range_error ("RegExp executor recursion limit is exceeded." );
378
+ }
379
+ #endif /* REGEXP_RECURSION_LIMIT */
367
380
const lit_utf8_byte_t * str_curr_p = str_p ;
368
381
369
382
while (true)
@@ -376,12 +389,14 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
376
389
{
377
390
JERRY_TRACE_MSG ("Execute RE_OP_MATCH: match\n" );
378
391
* out_str_p = str_curr_p ;
392
+ REGEXP_INCREASE_RECURSION_COUNTER ();
379
393
return ECMA_VALUE_TRUE ; /* match */
380
394
}
381
395
case RE_OP_CHAR :
382
396
{
383
397
if (str_curr_p >= re_ctx_p -> input_end_p )
384
398
{
399
+ REGEXP_INCREASE_RECURSION_COUNTER ();
385
400
return ECMA_VALUE_FALSE ; /* fail */
386
401
}
387
402
@@ -393,6 +408,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
393
408
if (ch1 != ch2 )
394
409
{
395
410
JERRY_TRACE_MSG ("fail\n" );
411
+ REGEXP_INCREASE_RECURSION_COUNTER ();
396
412
return ECMA_VALUE_FALSE ; /* fail */
397
413
}
398
414
@@ -404,6 +420,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
404
420
{
405
421
if (str_curr_p >= re_ctx_p -> input_end_p )
406
422
{
423
+ REGEXP_INCREASE_RECURSION_COUNTER ();
407
424
return ECMA_VALUE_FALSE ; /* fail */
408
425
}
409
426
@@ -413,6 +430,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
413
430
if (lit_char_is_line_terminator (ch ))
414
431
{
415
432
JERRY_TRACE_MSG ("fail\n" );
433
+ REGEXP_INCREASE_RECURSION_COUNTER ();
416
434
return ECMA_VALUE_FALSE ; /* fail */
417
435
}
418
436
@@ -432,6 +450,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
432
450
if (!(re_ctx_p -> flags & RE_FLAG_MULTILINE ))
433
451
{
434
452
JERRY_TRACE_MSG ("fail\n" );
453
+ REGEXP_INCREASE_RECURSION_COUNTER ();
435
454
return ECMA_VALUE_FALSE ; /* fail */
436
455
}
437
456
@@ -442,6 +461,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
442
461
}
443
462
444
463
JERRY_TRACE_MSG ("fail\n" );
464
+ REGEXP_INCREASE_RECURSION_COUNTER ();
445
465
return ECMA_VALUE_FALSE ; /* fail */
446
466
}
447
467
case RE_OP_ASSERT_END :
@@ -457,6 +477,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
457
477
if (!(re_ctx_p -> flags & RE_FLAG_MULTILINE ))
458
478
{
459
479
JERRY_TRACE_MSG ("fail\n" );
480
+ REGEXP_INCREASE_RECURSION_COUNTER ();
460
481
return ECMA_VALUE_FALSE ; /* fail */
461
482
}
462
483
@@ -467,6 +488,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
467
488
}
468
489
469
490
JERRY_TRACE_MSG ("fail\n" );
491
+ REGEXP_INCREASE_RECURSION_COUNTER ();
470
492
return ECMA_VALUE_FALSE ; /* fail */
471
493
}
472
494
case RE_OP_ASSERT_WORD_BOUNDARY :
@@ -498,6 +520,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
498
520
if (is_wordchar_left == is_wordchar_right )
499
521
{
500
522
JERRY_TRACE_MSG ("fail\n" );
523
+ REGEXP_INCREASE_RECURSION_COUNTER ();
501
524
return ECMA_VALUE_FALSE ; /* fail */
502
525
}
503
526
}
@@ -509,6 +532,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
509
532
if (is_wordchar_left != is_wordchar_right )
510
533
{
511
534
JERRY_TRACE_MSG ("fail\n" );
535
+ REGEXP_INCREASE_RECURSION_COUNTER ();
512
536
return ECMA_VALUE_FALSE ; /* fail */
513
537
}
514
538
}
@@ -563,6 +587,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
563
587
564
588
if (!ECMA_IS_VALUE_ERROR (match_value ))
565
589
{
590
+ REGEXP_INCREASE_RECURSION_COUNTER ();
566
591
if (ecma_is_value_true (match_value ))
567
592
{
568
593
* out_str_p = sub_str_p ;
@@ -588,6 +613,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
588
613
if (str_curr_p >= re_ctx_p -> input_end_p )
589
614
{
590
615
JERRY_TRACE_MSG ("fail\n" );
616
+ REGEXP_INCREASE_RECURSION_COUNTER ();
591
617
return ECMA_VALUE_FALSE ; /* fail */
592
618
}
593
619
@@ -618,6 +644,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
618
644
if (!is_match )
619
645
{
620
646
JERRY_TRACE_MSG ("fail\n" );
647
+ REGEXP_INCREASE_RECURSION_COUNTER ();
621
648
return ECMA_VALUE_FALSE ; /* fail */
622
649
}
623
650
}
@@ -627,6 +654,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
627
654
if (is_match )
628
655
{
629
656
JERRY_TRACE_MSG ("fail\n" );
657
+ REGEXP_INCREASE_RECURSION_COUNTER ();
630
658
return ECMA_VALUE_FALSE ; /* fail */
631
659
}
632
660
}
@@ -657,6 +685,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
657
685
if (str_curr_p >= re_ctx_p -> input_end_p )
658
686
{
659
687
JERRY_TRACE_MSG ("fail\n" );
688
+ REGEXP_INCREASE_RECURSION_COUNTER ();
660
689
return ECMA_VALUE_FALSE ; /* fail */
661
690
}
662
691
@@ -666,6 +695,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
666
695
if (ch1 != ch2 )
667
696
{
668
697
JERRY_TRACE_MSG ("fail\n" );
698
+ REGEXP_INCREASE_RECURSION_COUNTER ();
669
699
return ECMA_VALUE_FALSE ; /* fail */
670
700
}
671
701
}
@@ -689,6 +719,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
689
719
if (ecma_is_value_true (match_value ))
690
720
{
691
721
* out_str_p = sub_str_p ;
722
+ REGEXP_INCREASE_RECURSION_COUNTER ();
692
723
return match_value ; /* match */
693
724
}
694
725
else if (ECMA_IS_VALUE_ERROR (match_value ))
@@ -703,13 +734,15 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
703
734
bc_p = old_bc_p ;
704
735
705
736
re_ctx_p -> saved_p [RE_GLOBAL_START_IDX ] = old_start_p ;
737
+ REGEXP_INCREASE_RECURSION_COUNTER ();
706
738
return ECMA_VALUE_FALSE ; /* fail */
707
739
}
708
740
case RE_OP_SAVE_AND_MATCH :
709
741
{
710
742
JERRY_TRACE_MSG ("End of pattern is reached: match\n" );
711
743
re_ctx_p -> saved_p [RE_GLOBAL_END_IDX ] = str_curr_p ;
712
744
* out_str_p = str_curr_p ;
745
+ REGEXP_INCREASE_RECURSION_COUNTER ();
713
746
return ECMA_VALUE_TRUE ; /* match */
714
747
}
715
748
case RE_OP_ALTERNATIVE :
@@ -774,6 +807,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
774
807
if (ecma_is_value_true (match_value ))
775
808
{
776
809
* out_str_p = sub_str_p ;
810
+ REGEXP_INCREASE_RECURSION_COUNTER ();
777
811
return match_value ; /* match */
778
812
}
779
813
else if (ECMA_IS_VALUE_ERROR (match_value ))
@@ -832,6 +866,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
832
866
if (ecma_is_value_true (match_value ))
833
867
{
834
868
* out_str_p = sub_str_p ;
869
+ REGEXP_INCREASE_RECURSION_COUNTER ();
835
870
return match_value ; /* match */
836
871
}
837
872
else if (ECMA_IS_VALUE_ERROR (match_value ))
@@ -856,6 +891,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
856
891
if (ecma_is_value_true (match_value ))
857
892
{
858
893
* out_str_p = sub_str_p ;
894
+ REGEXP_INCREASE_RECURSION_COUNTER ();
859
895
return match_value ; /* match */
860
896
}
861
897
else if (ECMA_IS_VALUE_ERROR (match_value ))
@@ -865,6 +901,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
865
901
}
866
902
867
903
re_ctx_p -> saved_p [start_idx ] = old_start_p ;
904
+ REGEXP_INCREASE_RECURSION_COUNTER ();
868
905
return ECMA_VALUE_FALSE ; /* fail */
869
906
}
870
907
case RE_OP_CAPTURE_NON_GREEDY_GROUP_END :
@@ -910,6 +947,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
910
947
if (ecma_is_value_true (match_value ))
911
948
{
912
949
* out_str_p = sub_str_p ;
950
+ REGEXP_INCREASE_RECURSION_COUNTER ();
913
951
return match_value ; /* match */
914
952
}
915
953
else if (ECMA_IS_VALUE_ERROR (match_value ))
@@ -958,6 +996,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
958
996
if (re_ctx_p -> num_of_iterations_p [iter_idx ] >= min
959
997
&& str_curr_p == re_ctx_p -> saved_p [start_idx ])
960
998
{
999
+ REGEXP_INCREASE_RECURSION_COUNTER ();
961
1000
return ECMA_VALUE_FALSE ; /* fail */
962
1001
}
963
1002
@@ -979,6 +1018,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
979
1018
if (ecma_is_value_true (match_value ))
980
1019
{
981
1020
* out_str_p = sub_str_p ;
1021
+ REGEXP_INCREASE_RECURSION_COUNTER ();
982
1022
return match_value ; /* match */
983
1023
}
984
1024
else if (ECMA_IS_VALUE_ERROR (match_value ))
@@ -1003,6 +1043,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
1003
1043
if (ecma_is_value_true (match_value ))
1004
1044
{
1005
1045
* out_str_p = sub_str_p ;
1046
+ REGEXP_INCREASE_RECURSION_COUNTER ();
1006
1047
return match_value ; /* match */
1007
1048
}
1008
1049
else if (ECMA_IS_VALUE_ERROR (match_value ))
@@ -1024,6 +1065,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
1024
1065
if (ecma_is_value_true (match_value ))
1025
1066
{
1026
1067
* out_str_p = sub_str_p ;
1068
+ REGEXP_INCREASE_RECURSION_COUNTER ();
1027
1069
return match_value ; /* match */
1028
1070
}
1029
1071
else if (ECMA_IS_VALUE_ERROR (match_value ))
@@ -1035,6 +1077,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
1035
1077
/* restore if fails */
1036
1078
re_ctx_p -> saved_p [end_idx ] = old_end_p ;
1037
1079
re_ctx_p -> num_of_iterations_p [iter_idx ]-- ;
1080
+ REGEXP_INCREASE_RECURSION_COUNTER ();
1038
1081
return ECMA_VALUE_FALSE ; /* fail */
1039
1082
}
1040
1083
case RE_OP_NON_GREEDY_ITERATOR :
@@ -1059,6 +1102,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
1059
1102
if (ecma_is_value_true (match_value ))
1060
1103
{
1061
1104
* out_str_p = sub_str_p ;
1105
+ REGEXP_INCREASE_RECURSION_COUNTER ();
1062
1106
return match_value ; /* match */
1063
1107
}
1064
1108
else if (ECMA_IS_VALUE_ERROR (match_value ))
@@ -1082,6 +1126,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
1082
1126
str_curr_p = sub_str_p ;
1083
1127
num_of_iter ++ ;
1084
1128
}
1129
+ REGEXP_INCREASE_RECURSION_COUNTER ();
1085
1130
return ECMA_VALUE_FALSE ; /* fail */
1086
1131
}
1087
1132
default :
@@ -1125,6 +1170,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
1125
1170
if (ecma_is_value_true (match_value ))
1126
1171
{
1127
1172
* out_str_p = sub_str_p ;
1173
+ REGEXP_INCREASE_RECURSION_COUNTER ();
1128
1174
return match_value ; /* match */
1129
1175
}
1130
1176
else if (ECMA_IS_VALUE_ERROR (match_value ))
@@ -1140,6 +1186,7 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */
1140
1186
lit_utf8_read_prev (& str_curr_p );
1141
1187
num_of_iter -- ;
1142
1188
}
1189
+ REGEXP_INCREASE_RECURSION_COUNTER ();
1143
1190
return ECMA_VALUE_FALSE ; /* fail */
1144
1191
}
1145
1192
}
@@ -1232,6 +1279,9 @@ ecma_regexp_exec_helper (ecma_value_t regexp_value, /**< RegExp object */
1232
1279
re_ctx .input_start_p = input_curr_p ;
1233
1280
const lit_utf8_byte_t * input_end_p = re_ctx .input_start_p + input_buffer_size ;
1234
1281
re_ctx .input_end_p = input_end_p ;
1282
+ #ifdef REGEXP_RECURSION_LIMIT
1283
+ re_ctx .recursion_counter = REGEXP_RECURSION_LIMIT ;
1284
+ #endif /* REGEXP_RECURSION_LIMIT */
1235
1285
1236
1286
/* 1. Read bytecode header and init regexp matcher context. */
1237
1287
re_ctx .flags = bc_p -> header .status_flags ;
0 commit comments