@@ -108,7 +108,21 @@ private Grok(Map<String, String> patternBank, String grokPattern, boolean namedC
108108 * check for a circular reference.
109109 */
110110 private void forbidCircularReferences (String patternName , List <String > path , String pattern ) {
111- if (pattern .contains ("%{" + patternName + "}" ) || pattern .contains ("%{" + patternName + ":" )) {
111+ // first ensure that the pattern bank contains no simple circular references (i.e., any pattern
112+ // containing an immediate reference to itself) as those can cause the remainder of this algorithm
113+ // to recurse infinitely
114+ for (Map .Entry <String , String > entry : patternBank .entrySet ()) {
115+ if (patternReferencesItself (entry .getValue (), entry .getKey ())) {
116+ throw new IllegalArgumentException ("circular reference in pattern [" + entry .getKey () + "][" + entry .getValue () + "]" );
117+ }
118+ }
119+
120+ // next recursively check any other pattern names referenced in the pattern
121+ innerForbidCircularReferences (patternName , path , pattern );
122+ }
123+
124+ private void innerForbidCircularReferences (String patternName , List <String > path , String pattern ) {
125+ if (patternReferencesItself (pattern , patternName )) {
112126 String message ;
113127 if (path .isEmpty ()) {
114128 message = "circular reference in pattern [" + patternName + "][" + pattern + "]" ;
@@ -123,17 +137,18 @@ private void forbidCircularReferences(String patternName, List<String> path, Str
123137 throw new IllegalArgumentException (message );
124138 }
125139
140+ // next check any other pattern names found in the pattern
126141 for (int i = pattern .indexOf ("%{" ); i != -1 ; i = pattern .indexOf ("%{" , i + 1 )) {
127142 int begin = i + 2 ;
128- int brackedIndex = pattern .indexOf ('}' , begin );
143+ int bracketIndex = pattern .indexOf ('}' , begin );
129144 int columnIndex = pattern .indexOf (':' , begin );
130145 int end ;
131- if (brackedIndex != -1 && columnIndex == -1 ) {
132- end = brackedIndex ;
133- } else if (columnIndex != -1 && brackedIndex == -1 ) {
146+ if (bracketIndex != -1 && columnIndex == -1 ) {
147+ end = bracketIndex ;
148+ } else if (columnIndex != -1 && bracketIndex == -1 ) {
134149 end = columnIndex ;
135- } else if (brackedIndex != -1 && columnIndex != -1 ) {
136- end = Math .min (brackedIndex , columnIndex );
150+ } else if (bracketIndex != -1 && columnIndex != -1 ) {
151+ end = Math .min (bracketIndex , columnIndex );
137152 } else {
138153 throw new IllegalArgumentException ("pattern [" + pattern + "] has circular references to other pattern definitions" );
139154 }
@@ -143,6 +158,10 @@ private void forbidCircularReferences(String patternName, List<String> path, Str
143158 }
144159 }
145160
161+ private static boolean patternReferencesItself (String pattern , String patternName ) {
162+ return pattern .contains ("%{" + patternName + "}" ) || pattern .contains ("%{" + patternName + ":" );
163+ }
164+
146165 private String groupMatch (String name , Region region , String pattern ) {
147166 try {
148167 int number = GROK_PATTERN_REGEX .nameToBackrefNumber (name .getBytes (StandardCharsets .UTF_8 ), 0 ,
0 commit comments