@@ -107,6 +107,51 @@ abstract class RegexString extends StringLiteral {
107
107
end = start + 3
108
108
}
109
109
110
+ private predicate namedBackreference ( int start , int end , string name ) {
111
+ this .escapingChar ( start ) and
112
+ this .getChar ( start + 1 ) = "k" and
113
+ this .getChar ( start + 2 ) = "<" and
114
+ end = min ( int i | i > start + 2 and this .getChar ( i ) = ">" ) + 1 and
115
+ name = this .getText ( ) .substring ( start + 3 , end - 2 )
116
+ }
117
+
118
+ private predicate numberedBackreference ( int start , int end , int value ) {
119
+ this .escapingChar ( start ) and
120
+ // starting with 0 makes it an octal escape
121
+ not this .getChar ( start + 1 ) = "0" and
122
+ exists ( string text , string svalue , int len |
123
+ end = start + len and
124
+ text = this .getText ( ) and
125
+ len in [ 2 .. 3 ]
126
+ |
127
+ svalue = text .substring ( start + 1 , start + len ) and
128
+ value = svalue .toInt ( ) and
129
+ // value is composed of digits
130
+ forall ( int i | i in [ start + 1 .. start + len - 1 ] | this .getChar ( i ) = [ 0 .. 9 ] .toString ( ) ) and
131
+ // a longer reference is not possible
132
+ not (
133
+ len = 2 and
134
+ exists ( text .substring ( start + 1 , start + len + 1 ) .toInt ( ) )
135
+ ) and
136
+ // 3 octal digits makes it an octal escape
137
+ not forall ( int i | i in [ start + 1 .. start + 4 ] | this .isOctal ( i ) )
138
+ // TODO: Inside a character set, all numeric escapes are treated as characters.
139
+ )
140
+ }
141
+
142
+ /** Holds if the text in the range start,end is a back reference */
143
+ predicate backreference ( int start , int end ) {
144
+ this .numberedBackreference ( start , end , _)
145
+ or
146
+ this .namedBackreference ( start , end , _)
147
+ }
148
+
149
+ /** Gets the number of the back reference in start,end */
150
+ int getBackrefNumber ( int start , int end ) { this .numberedBackreference ( start , end , result ) }
151
+
152
+ /** Gets the name, if it has one, of the back reference in start,end */
153
+ string getBackrefName ( int start , int end ) { this .namedBackreference ( start , end , result ) }
154
+
110
155
pragma [ inline]
111
156
private predicate isOctal ( int index ) { this .getChar ( index ) = [ 0 .. 7 ] .toString ( ) }
112
157
@@ -592,51 +637,6 @@ abstract class RegexString extends StringLiteral {
592
637
this .positiveLookbehindAssertionGroup ( start , end )
593
638
}
594
639
595
- private predicate namedBackreference ( int start , int end , string name ) {
596
- this .escapingChar ( start ) and
597
- this .getChar ( start + 1 ) = "k" and
598
- this .getChar ( start + 2 ) = "<" and
599
- end = min ( int i | i > start + 2 and this .getChar ( i ) = ">" ) + 1 and
600
- name = this .getText ( ) .substring ( start + 3 , end - 2 )
601
- }
602
-
603
- private predicate numberedBackreference ( int start , int end , int value ) {
604
- this .escapingChar ( start ) and
605
- // starting with 0 makes it an octal escape
606
- not this .getChar ( start + 1 ) = "0" and
607
- exists ( string text , string svalue , int len |
608
- end = start + len and
609
- text = this .getText ( ) and
610
- len in [ 2 .. 3 ]
611
- |
612
- svalue = text .substring ( start + 1 , start + len ) and
613
- value = svalue .toInt ( ) and
614
- // value is composed of digits
615
- forall ( int i | i in [ start + 1 .. start + len - 1 ] | this .getChar ( i ) = [ 0 .. 9 ] .toString ( ) ) and
616
- // a longer reference is not possible
617
- not (
618
- len = 2 and
619
- exists ( text .substring ( start + 1 , start + len + 1 ) .toInt ( ) )
620
- ) and
621
- // 3 octal digits makes it an octal escape
622
- not forall ( int i | i in [ start + 1 .. start + 4 ] | this .isOctal ( i ) )
623
- // TODO: Inside a character set, all numeric escapes are treated as characters.
624
- )
625
- }
626
-
627
- /** Holds if the text in the range start,end is a back reference */
628
- predicate backreference ( int start , int end ) {
629
- this .numberedBackreference ( start , end , _)
630
- or
631
- this .namedBackreference ( start , end , _)
632
- }
633
-
634
- /** Gets the number of the back reference in start,end */
635
- int getBackrefNumber ( int start , int end ) { this .numberedBackreference ( start , end , result ) }
636
-
637
- /** Gets the name, if it has one, of the back reference in start,end */
638
- string getBackrefName ( int start , int end ) { this .namedBackreference ( start , end , result ) }
639
-
640
640
private predicate baseItem ( int start , int end ) {
641
641
this .character ( start , end ) and
642
642
not exists ( int x , int y | this .charSet ( x , y ) and x <= start and y >= end )
0 commit comments