@@ -105,7 +105,21 @@ private Grok(Map<String, String> patternBank, String grokPattern, boolean namedC
105105 * check for a circular reference.
106106 */
107107 private void forbidCircularReferences (String patternName , List <String > path , String pattern ) {
108- if (pattern .contains ("%{" + patternName + "}" ) || pattern .contains ("%{" + patternName + ":" )) {
108+ // first ensure that the pattern bank contains no simple circular references (i.e., any pattern
109+ // containing an immediate reference to itself) as those can cause the remainder of this algorithm
110+ // to recurse infinitely
111+ for (Map .Entry <String , String > entry : patternBank .entrySet ()) {
112+ if (patternReferencesItself (entry .getValue (), entry .getKey ())) {
113+ throw new IllegalArgumentException ("circular reference in pattern [" + entry .getKey () + "][" + entry .getValue () + "]" );
114+ }
115+ }
116+
117+ // next recursively check any other pattern names referenced in the pattern
118+ innerForbidCircularReferences (patternName , path , pattern );
119+ }
120+
121+ private void innerForbidCircularReferences (String patternName , List <String > path , String pattern ) {
122+ if (patternReferencesItself (pattern , patternName )) {
109123 String message ;
110124 if (path .isEmpty ()) {
111125 message = "circular reference in pattern [" + patternName + "][" + pattern + "]" ;
@@ -120,17 +134,18 @@ private void forbidCircularReferences(String patternName, List<String> path, Str
120134 throw new IllegalArgumentException (message );
121135 }
122136
137+ // next check any other pattern names found in the pattern
123138 for (int i = pattern .indexOf ("%{" ); i != -1 ; i = pattern .indexOf ("%{" , i + 1 )) {
124139 int begin = i + 2 ;
125- int brackedIndex = pattern .indexOf ('}' , begin );
140+ int bracketIndex = pattern .indexOf ('}' , begin );
126141 int columnIndex = pattern .indexOf (':' , begin );
127142 int end ;
128- if (brackedIndex != -1 && columnIndex == -1 ) {
129- end = brackedIndex ;
130- } else if (columnIndex != -1 && brackedIndex == -1 ) {
143+ if (bracketIndex != -1 && columnIndex == -1 ) {
144+ end = bracketIndex ;
145+ } else if (columnIndex != -1 && bracketIndex == -1 ) {
131146 end = columnIndex ;
132- } else if (brackedIndex != -1 && columnIndex != -1 ) {
133- end = Math .min (brackedIndex , columnIndex );
147+ } else if (bracketIndex != -1 && columnIndex != -1 ) {
148+ end = Math .min (bracketIndex , columnIndex );
134149 } else {
135150 throw new IllegalArgumentException ("pattern [" + pattern + "] has circular references to other pattern definitions" );
136151 }
@@ -140,6 +155,10 @@ private void forbidCircularReferences(String patternName, List<String> path, Str
140155 }
141156 }
142157
158+ private static boolean patternReferencesItself (String pattern , String patternName ) {
159+ return pattern .contains ("%{" + patternName + "}" ) || pattern .contains ("%{" + patternName + ":" );
160+ }
161+
143162 private String groupMatch (String name , Region region , String pattern ) {
144163 int number = GROK_PATTERN_REGEX .nameToBackrefNumber (name .getBytes (StandardCharsets .UTF_8 ), 0 ,
145164 name .getBytes (StandardCharsets .UTF_8 ).length , region );
0 commit comments