From 5c2b67a091eb97d1a80dafbb3e3a27123ca97877 Mon Sep 17 00:00:00 2001 From: Albert Meltzer <7529386+kitbellew@users.noreply.github.com> Date: Thu, 20 Nov 2025 11:35:49 -0800 Subject: [PATCH] Matcher: no useless backtracking in group replace When encountering `${`, we do not move the read index forward to the `}` and continue iterating on it again. The reason it "worked" is two-fold: - a group name contains alphanumeric or underscore, which won't trigger special handling in the loop (only `\\` and `$` would) - we had already moved `last` index past the closing `}` --- java/com/google/re2j/Matcher.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/java/com/google/re2j/Matcher.java b/java/com/google/re2j/Matcher.java index 678186d0..66fc0a69 100644 --- a/java/com/google/re2j/Matcher.java +++ b/java/com/google/re2j/Matcher.java @@ -523,19 +523,19 @@ private void appendReplacementInternal(StringBuilder sb, String replacement) { if (last < i) { sb.append(replacement.substring(last, i)); } - i++; // skip { - int j = i + 1; - while (j < replacement.length() - && replacement.charAt(j) != '}' - && replacement.charAt(j) != ' ') { - j++; + i += 2; // after { + int off = i; + while (i < replacement.length() + && replacement.charAt(i) != '}' + && replacement.charAt(i) != ' ') { + i++; } - if (j == replacement.length() || replacement.charAt(j) != '}') { + if (i == replacement.length() || replacement.charAt(i) != '}') { throw new IllegalArgumentException("named capture group is missing trailing '}'"); } - String groupName = replacement.substring(i + 1, j); + String groupName = replacement.substring(off, i); sb.append(group(groupName)); - last = j + 1; + last = i + 1; } } }