@@ -114,7 +114,21 @@ private Grok(Map<String, String> patternBank, String grokPattern, boolean namedC
114114 * check for a circular reference.
115115 */
116116 private void forbidCircularReferences (String patternName , List <String > path , String pattern ) {
117- if (pattern .contains ("%{" + patternName + "}" ) || pattern .contains ("%{" + patternName + ":" )) {
117+ // first ensure that the pattern bank contains no simple circular references (i.e., any pattern
118+ // containing an immediate reference to itself) as those can cause the remainder of this algorithm
119+ // to recurse infinitely
120+ for (Map .Entry <String , String > entry : patternBank .entrySet ()) {
121+ if (patternReferencesItself (entry .getValue (), entry .getKey ())) {
122+ throw new IllegalArgumentException ("circular reference in pattern [" + entry .getKey () + "][" + entry .getValue () + "]" );
123+ }
124+ }
125+
126+ // next recursively check any other pattern names referenced in the pattern
127+ innerForbidCircularReferences (patternName , path , pattern );
128+ }
129+
130+ private void innerForbidCircularReferences (String patternName , List <String > path , String pattern ) {
131+ if (patternReferencesItself (pattern , patternName )) {
118132 String message ;
119133 if (path .isEmpty ()) {
120134 message = "circular reference in pattern [" + patternName + "][" + pattern + "]" ;
@@ -129,17 +143,18 @@ private void forbidCircularReferences(String patternName, List<String> path, Str
129143 throw new IllegalArgumentException (message );
130144 }
131145
146+ // next check any other pattern names found in the pattern
132147 for (int i = pattern .indexOf ("%{" ); i != -1 ; i = pattern .indexOf ("%{" , i + 1 )) {
133148 int begin = i + 2 ;
134- int brackedIndex = pattern .indexOf ('}' , begin );
149+ int bracketIndex = pattern .indexOf ('}' , begin );
135150 int columnIndex = pattern .indexOf (':' , begin );
136151 int end ;
137- if (brackedIndex != -1 && columnIndex == -1 ) {
138- end = brackedIndex ;
139- } else if (columnIndex != -1 && brackedIndex == -1 ) {
152+ if (bracketIndex != -1 && columnIndex == -1 ) {
153+ end = bracketIndex ;
154+ } else if (columnIndex != -1 && bracketIndex == -1 ) {
140155 end = columnIndex ;
141- } else if (brackedIndex != -1 && columnIndex != -1 ) {
142- end = Math .min (brackedIndex , columnIndex );
156+ } else if (bracketIndex != -1 && columnIndex != -1 ) {
157+ end = Math .min (bracketIndex , columnIndex );
143158 } else {
144159 throw new IllegalArgumentException ("pattern [" + pattern + "] has circular references to other pattern definitions" );
145160 }
@@ -149,6 +164,10 @@ private void forbidCircularReferences(String patternName, List<String> path, Str
149164 }
150165 }
151166
167+ private static boolean patternReferencesItself (String pattern , String patternName ) {
168+ return pattern .contains ("%{" + patternName + "}" ) || pattern .contains ("%{" + patternName + ":" );
169+ }
170+
152171 public String groupMatch (String name , Region region , String pattern ) {
153172 try {
154173 int number = GROK_PATTERN_REGEX .nameToBackrefNumber (name .getBytes (StandardCharsets .UTF_8 ), 0 ,
0 commit comments