@@ -1182,6 +1182,8 @@ if (isForwardRange!R && is(ElementType!R : dchar))
11821182 state = State.Start;
11831183 break ;
11841184 default :
1185+ if (current >= privateUseStart && current <= privateUseEnd)
1186+ enforce(false , " no matching ']' found while parsing character class" );
11851187 enforce(false , " invalid escape sequence" );
11861188 }
11871189 break ;
@@ -1256,8 +1258,17 @@ if (isForwardRange!R && is(ElementType!R : dchar))
12561258 end = parseUniHex(pat, 8 );
12571259 break ;
12581260 default :
1261+ if (current >= privateUseStart && current <= privateUseEnd)
1262+ enforce(false , " no matching ']' found while parsing character class" );
12591263 error(" invalid escape sequence" );
12601264 }
1265+ // Lookahead to check if it's a \T
1266+ // where T is sub-pattern terminator in multi-pattern scheme
1267+ if (end == ' \\ ' && ! pat.empty)
1268+ {
1269+ if (pat.front >= privateUseStart && pat.front <= privateUseEnd)
1270+ enforce(false , " invalid escape sequence" );
1271+ }
12611272 enforce(last <= end," inverted range" );
12621273 set.add(last, end + 1 );
12631274 state = State.Start;
@@ -1293,6 +1304,7 @@ if (isForwardRange!R && is(ElementType!R : dchar))
12931304 switch (op)
12941305 {
12951306 case Operator.Negate:
1307+ enforce(! stack.empty, " no operand for '^'" );
12961308 stack.top = stack.top.inverted;
12971309 break ;
12981310 case Operator.Union:
@@ -1364,8 +1376,7 @@ if (isForwardRange!R && is(ElementType!R : dchar))
13641376 " character class syntax error" );
13651377 enforce(! opstack.empty, " unmatched ']'" );
13661378 opstack.pop();
1367- next();
1368- if (opstack.empty)
1379+ if (! next() || opstack.empty)
13691380 break L_CharsetLoop;
13701381 auto pair = parseCharTerm();
13711382 if (! pair[0 ].empty)// not only operator e.g. -- or ~~
@@ -1390,10 +1401,13 @@ if (isForwardRange!R && is(ElementType!R : dchar))
13901401 }
13911402 vstack.push(pair[0 ]);
13921403 }
1393-
13941404 }while (! empty || ! opstack.empty);
13951405 while (! opstack.empty)
1396- apply(opstack.pop(),vstack);
1406+ {
1407+ enforce(opstack.top != Operator.Open,
1408+ " no matching ']' found while parsing character class" );
1409+ apply(opstack.pop(), vstack);
1410+ }
13971411 assert (vstack.length == 1 );
13981412 g.charsetToIr(vstack.top);
13991413 }
@@ -1483,6 +1497,13 @@ if (isForwardRange!R && is(ElementType!R : dchar))
14831497 g.markBackref(nref);
14841498 break ;
14851499 default :
1500+ // Lookahead to check if it's a \T
1501+ // where T is sub-pattern terminator in multi-pattern scheme
1502+ if (current == ' \\ ' && ! pat.empty)
1503+ {
1504+ if (pat.front >= privateUseStart && current <= privateUseEnd)
1505+ enforce(false , " invalid escape sequence" );
1506+ }
14861507 if (current >= privateUseStart && current <= privateUseEnd)
14871508 {
14881509 g.endPattern(current - privateUseStart + 1 );
0 commit comments