@@ -2859,6 +2859,7 @@ uint32_t delimiter;
2859
2859
uint32_t namelen ;
2860
2860
uint32_t class_range_state ;
2861
2861
uint32_t class_op_state ;
2862
+ uint32_t * class_start ;
2862
2863
uint32_t * verblengthptr = NULL ; /* Value avoids compiler warning */
2863
2864
uint32_t * verbstartptr = NULL ;
2864
2865
uint32_t * previous_callout = NULL ;
@@ -2869,9 +2870,8 @@ uint32_t *prev_parsed_item = NULL;
2869
2870
uint32_t meta_quantifier = 0 ;
2870
2871
uint32_t add_after_mark = 0 ;
2871
2872
uint16_t nest_depth = 0 ;
2872
- uint16_t class_depth = 0 ;
2873
- uint16_t class_maxdepth = 0 ;
2874
- uint8_t class_op_used [ECLASS_NEST_LIMIT ];
2873
+ int16_t class_depth_m1 = -1 ; /* The m1 means minus 1. */
2874
+ int16_t class_maxdepth_m1 = -1 ;
2875
2875
int after_manual_callout = 0 ;
2876
2876
int expect_cond_assert = 0 ;
2877
2877
int errorcode = 0 ;
@@ -3650,10 +3650,11 @@ while (ptr < ptrend)
3650
3650
3651
3651
/* c is still set to '[' so the loop will handle the start of the class. */
3652
3652
3653
- class_depth = 0 ;
3654
- class_maxdepth = 0 ;
3653
+ class_depth_m1 = -1 ;
3654
+ class_maxdepth_m1 = -1 ;
3655
3655
class_range_state = RANGE_NO ;
3656
3656
class_op_state = CLASS_OP_NONE ;
3657
+ class_start = NULL ;
3657
3658
3658
3659
for (;;)
3659
3660
{
@@ -3684,7 +3685,7 @@ while (ptr < ptrend)
3684
3685
[.ch.] and [=ch=] ("collating elements") and fault them, as Perl
3685
3686
5.6 and 5.8 do. */
3686
3687
3687
- if (class_depth > 0 &&
3688
+ if (class_depth_m1 >= 0 &&
3688
3689
c == CHAR_LEFT_SQUARE_BRACKET &&
3689
3690
ptrend - ptr >= 3 &&
3690
3691
(* ptr == CHAR_COLON || * ptr == CHAR_DOT ||
@@ -3792,7 +3793,7 @@ while (ptr < ptrend)
3792
3793
/* Check for the start of the outermost class, or the start of a nested class. */
3793
3794
3794
3795
else if (c == CHAR_LEFT_SQUARE_BRACKET &&
3795
- (class_depth == 0 || (options & PCRE2_ALT_EXTENDED_CLASS ) != 0 ))
3796
+ (class_depth_m1 < 0 || (options & PCRE2_ALT_EXTENDED_CLASS ) != 0 ))
3796
3797
{
3797
3798
/* Tidy up the other class before starting the nested class. */
3798
3799
/* -[ beginning a nested class is a literal '-' */
@@ -3801,7 +3802,7 @@ while (ptr < ptrend)
3801
3802
parsed_pattern [-1 ] = CHAR_MINUS ;
3802
3803
3803
3804
/* Validate nesting depth */
3804
- if (class_depth >= ECLASS_NEST_LIMIT )
3805
+ if (class_depth_m1 >= ECLASS_NEST_LIMIT - 1 )
3805
3806
{
3806
3807
errorcode = ERR107 ;
3807
3808
goto FAILED ; /* Classes too deeply nested */
@@ -3845,11 +3846,19 @@ while (ptr < ptrend)
3845
3846
if (c == CHAR_RIGHT_SQUARE_BRACKET &&
3846
3847
(cb -> external_options & PCRE2_ALLOW_EMPTY_CLASS ) != 0 )
3847
3848
{
3849
+ if (class_start != NULL )
3850
+ {
3851
+ PCRE2_ASSERT (class_depth_m1 >= 0 );
3852
+ /* Represents that the class is an extended class. */
3853
+ * class_start |= CLASS_IS_ECLASS ;
3854
+ class_start = NULL ;
3855
+ }
3856
+
3848
3857
* parsed_pattern ++ = negate_class ? META_CLASS_EMPTY_NOT : META_CLASS_EMPTY ;
3849
3858
3850
3859
/* Leave nesting depth unchanged; but check for zero depth to handle the
3851
3860
very first (top-level) class being empty. */
3852
- if (class_depth == 0 ) break ;
3861
+ if (class_depth_m1 < 0 ) break ;
3853
3862
3854
3863
class_range_state = RANGE_NO ; /* for processing the containing class */
3855
3864
class_op_state = CLASS_OP_OPERAND ;
@@ -3858,12 +3867,23 @@ while (ptr < ptrend)
3858
3867
3859
3868
/* Enter a non-empty class. */
3860
3869
3870
+ if (class_start != NULL )
3871
+ {
3872
+ PCRE2_ASSERT (class_depth_m1 >= 0 );
3873
+ /* Represents that the class is an extended class. */
3874
+ * class_start |= CLASS_IS_ECLASS ;
3875
+ class_start = NULL ;
3876
+ }
3877
+
3878
+ class_start = parsed_pattern ;
3861
3879
* parsed_pattern ++ = negate_class ? META_CLASS_NOT : META_CLASS ;
3862
3880
class_range_state = RANGE_NO ;
3863
3881
class_op_state = CLASS_OP_NONE ;
3864
- ++ class_depth ;
3865
- class_maxdepth = class_depth > class_maxdepth ?class_depth :class_maxdepth ;
3866
- class_op_used [class_depth - 1 ] = 0 ; /* reset; no op seen yet at new depth */
3882
+ ++ class_depth_m1 ;
3883
+ if (class_maxdepth_m1 < class_depth_m1 )
3884
+ class_maxdepth_m1 = class_depth_m1 ;
3885
+ /* Reset; no op seen yet at new depth. */
3886
+ cb -> class_op_used [class_depth_m1 ] = 0 ;
3867
3887
3868
3888
/* Implement the special start-of-class literal meaning of ']'. */
3869
3889
if (c == CHAR_RIGHT_SQUARE_BRACKET )
@@ -3894,10 +3914,13 @@ while (ptr < ptrend)
3894
3914
3895
3915
* parsed_pattern ++ = META_CLASS_END ;
3896
3916
3897
- if (-- class_depth == 0 ) break ;
3917
+ if (-- class_depth_m1 < 0 ) break ;
3898
3918
3899
3919
class_range_state = RANGE_NO ; /* for processing the containing class */
3900
3920
class_op_state = CLASS_OP_OPERAND ;
3921
+ /* The extended class flag has already
3922
+ been set for the parent class. */
3923
+ class_start = NULL ;
3901
3924
}
3902
3925
3903
3926
/* Handle a set operator */
@@ -3924,13 +3947,21 @@ while (ptr < ptrend)
3924
3947
}
3925
3948
3926
3949
/* Check for mixed precedence. Forbid [A--B&&C]. */
3927
- if (class_op_used [class_depth - 1 ] != 0 &&
3928
- class_op_used [class_depth - 1 ] != (uint8_t )c )
3950
+ if (cb -> class_op_used [class_depth_m1 ] != 0 &&
3951
+ cb -> class_op_used [class_depth_m1 ] != (uint8_t )c )
3929
3952
{
3930
3953
errorcode = ERR111 ;
3931
3954
goto FAILED ;
3932
3955
}
3933
3956
3957
+ if (class_start != NULL )
3958
+ {
3959
+ PCRE2_ASSERT (class_depth_m1 >= 0 );
3960
+ /* Represents that the class is an extended class. */
3961
+ * class_start |= CLASS_IS_ECLASS ;
3962
+ class_start = NULL ;
3963
+ }
3964
+
3934
3965
/* Dangling '-' before an operator is a literal */
3935
3966
if (class_range_state == RANGE_STARTED )
3936
3967
parsed_pattern [-1 ] = CHAR_MINUS ;
@@ -3940,7 +3971,7 @@ while (ptr < ptrend)
3940
3971
META_ECLASS_AND ;
3941
3972
class_range_state = RANGE_NO ;
3942
3973
class_op_state = CLASS_OP_OPERATOR ;
3943
- class_op_used [class_depth - 1 ] = (uint8_t )c ;
3974
+ cb -> class_op_used [class_depth_m1 ] = (uint8_t )c ;
3944
3975
}
3945
3976
3946
3977
/* Handle potential start of range */
@@ -4133,7 +4164,7 @@ while (ptr < ptrend)
4133
4164
if (ptr >= ptrend )
4134
4165
{
4135
4166
if ((options & PCRE2_ALT_EXTENDED_CLASS ) != 0 &&
4136
- class_depth == 1 && class_maxdepth == 2 )
4167
+ class_depth_m1 == 0 && class_maxdepth_m1 == 1 )
4137
4168
errorcode = ERR112 ; /* Missing terminating ']', but we saw '[ [ ]...' */
4138
4169
else
4139
4170
errorcode = ERR6 ; /* Missing terminating ']' */
@@ -5614,7 +5645,6 @@ for (;; pptr++)
5614
5645
uint32_t groupnumber ;
5615
5646
uint32_t verbarglen , verbculen ;
5616
5647
uint32_t subreqcuflags , subfirstcuflags ;
5617
- uint32_t * end_ptr ;
5618
5648
open_capitem * oc ;
5619
5649
PCRE2_UCHAR mcbuffer [8 ];
5620
5650
@@ -5781,7 +5811,7 @@ for (;; pptr++)
5781
5811
5782
5812
/* Check for complex extended classes and handle them separately. */
5783
5813
5784
- if (! PRIV ( check_class_not_nested )( pptr + 1 , & end_ptr ) )
5814
+ if (( * pptr & CLASS_IS_ECLASS ) != 0 )
5785
5815
{
5786
5816
previous = code ;
5787
5817
* code ++ = OP_ECLASS ;
@@ -5920,13 +5950,11 @@ for (;; pptr++)
5920
5950
5921
5951
/* Now emit the OP_CLASS/OP_NCLASS/OP_XCLASS/OP_ALLANY opcode. */
5922
5952
5923
- if (!PRIV (compile_class_not_nested )(options , xoptions , pptr + 1 , end_ptr ,
5924
- & code , meta == META_CLASS_NOT ,
5925
- errorcodeptr , cb , lengthptr ))
5926
- return 0 ;
5927
-
5928
- PCRE2_ASSERT (* end_ptr == META_CLASS_END );
5929
- pptr = end_ptr ;
5953
+ pptr = PRIV (compile_class_not_nested )(options , xoptions , pptr + 1 ,
5954
+ & code , meta == META_CLASS_NOT ,
5955
+ errorcodeptr , cb , lengthptr );
5956
+ if (pptr == NULL ) return 0 ;
5957
+ PCRE2_ASSERT (* pptr == META_CLASS_END );
5930
5958
5931
5959
/* If this class is the first thing in the branch, there can be no first
5932
5960
char setting, whatever the repeat count. Any reqcu setting must remain
0 commit comments