@@ -3264,6 +3264,14 @@ setup_subexp_call(Node* node, ScanEnv* env)
3264
3264
}
3265
3265
#endif
3266
3266
3267
+ #define IN_ALT (1<<0)
3268
+ #define IN_NOT (1<<1)
3269
+ #define IN_REPEAT (1<<2)
3270
+ #define IN_VAR_REPEAT (1<<3)
3271
+ #define IN_CALL (1<<4)
3272
+ #define IN_RECCALL (1<<5)
3273
+ #define IN_LOOK_BEHIND (1<<6)
3274
+
3267
3275
/* divide different length alternatives in look-behind.
3268
3276
(?<=A|B) ==> (?<=A)|(?<=B)
3269
3277
(?<!A|B) ==> (?<!A)(?<!B)
@@ -3560,24 +3568,29 @@ expand_case_fold_string_alt(int item_num, OnigCaseFoldCodeItem items[],
3560
3568
return ONIGERR_MEMORY ;
3561
3569
}
3562
3570
3563
- static int
3564
- expand_case_fold_string (Node * node , regex_t * reg )
3565
- {
3566
3571
#define THRESHOLD_CASE_FOLD_ALT_FOR_EXPANSION 8
3567
3572
3573
+ static int
3574
+ expand_case_fold_string (Node * node , regex_t * reg , int state )
3575
+ {
3568
3576
int r , n , len , alt_num ;
3569
3577
int varlen = 0 ;
3578
+ int is_in_look_behind ;
3570
3579
UChar * start , * end , * p ;
3571
3580
Node * top_root , * root , * snode , * prev_node ;
3572
3581
OnigCaseFoldCodeItem items [ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM ];
3573
- StrNode * sn = NSTR ( node ) ;
3582
+ StrNode * sn ;
3574
3583
3575
3584
if (NSTRING_IS_AMBIG (node )) return 0 ;
3576
3585
3586
+ sn = NSTR (node );
3587
+
3577
3588
start = sn -> s ;
3578
3589
end = sn -> end ;
3579
3590
if (start >= end ) return 0 ;
3580
3591
3592
+ is_in_look_behind = (state & IN_LOOK_BEHIND ) != 0 ;
3593
+
3581
3594
r = 0 ;
3582
3595
top_root = root = prev_node = snode = NULL_NODE ;
3583
3596
alt_num = 1 ;
@@ -3593,7 +3606,7 @@ expand_case_fold_string(Node* node, regex_t* reg)
3593
3606
len = enclen (reg -> enc , p , end );
3594
3607
3595
3608
varlen = is_case_fold_variable_len (n , items , len );
3596
- if (n == 0 || varlen == 0 ) {
3609
+ if (n == 0 || varlen == 0 || is_in_look_behind ) {
3597
3610
if (IS_NULL (snode )) {
3598
3611
if (IS_NULL (root ) && IS_NOT_NULL (prev_node )) {
3599
3612
onig_node_free (top_root );
@@ -3854,13 +3867,6 @@ setup_comb_exp_check(Node* node, int state, ScanEnv* env)
3854
3867
}
3855
3868
#endif
3856
3869
3857
- #define IN_ALT (1<<0)
3858
- #define IN_NOT (1<<1)
3859
- #define IN_REPEAT (1<<2)
3860
- #define IN_VAR_REPEAT (1<<3)
3861
- #define IN_CALL (1<<4)
3862
- #define IN_RECCALL (1<<5)
3863
-
3864
3870
/* setup_tree does the following work.
3865
3871
1. check empty loop. (set qn->target_empty_info)
3866
3872
2. expand ignore-case in char class.
@@ -3902,7 +3908,7 @@ setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env)
3902
3908
3903
3909
case NT_STR :
3904
3910
if (IS_IGNORECASE (reg -> options ) && !NSTRING_IS_RAW (node )) {
3905
- r = expand_case_fold_string (node , reg );
3911
+ r = expand_case_fold_string (node , reg , state );
3906
3912
}
3907
3913
break ;
3908
3914
@@ -4145,7 +4151,7 @@ setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env)
4145
4151
if (r < 0 ) return r ;
4146
4152
if (r > 0 ) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN ;
4147
4153
if (NTYPE (node ) != NT_ANCHOR ) goto restart ;
4148
- r = setup_tree (an -> target , reg , state , env );
4154
+ r = setup_tree (an -> target , reg , ( state | IN_LOOK_BEHIND ) , env );
4149
4155
if (r != 0 ) return r ;
4150
4156
r = setup_look_behind (node , reg , env );
4151
4157
}
@@ -4158,7 +4164,8 @@ setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env)
4158
4164
if (r < 0 ) return r ;
4159
4165
if (r > 0 ) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN ;
4160
4166
if (NTYPE (node ) != NT_ANCHOR ) goto restart ;
4161
- r = setup_tree (an -> target , reg , (state | IN_NOT ), env );
4167
+ r = setup_tree (an -> target , reg , (state | IN_NOT | IN_LOOK_BEHIND ),
4168
+ env );
4162
4169
if (r != 0 ) return r ;
4163
4170
r = setup_look_behind (node , reg , env );
4164
4171
}
0 commit comments