Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4509697

java.regex.Matcher.appendReplacement improperly parses $n if n>9

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 1.4.0
    • 1.4.0
    • core-libs
    • beta3
    • generic
    • generic
    • Verified



      Name: nt126004 Date: 10/02/2001


      java version "1.4.0-beta2"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta2-b77)
      Java HotSpot(TM) Client VM (build 1.4.0-beta2-b77, mixed mode)

      The method appendReplacement(StringBuffer sb, String replacement) doesn't parse
      group references properly. Although most calls to this method won't be affected
      by the bug, it becomes obvious in two situations:

      1. The regex contains more than 9 groups and the replacement string contains a
      reference to group 10 or higher ($10, $11...)

      2. When the last character of the replacement string comes right after a group
      reference it will be ignored. E.g. replace if the regex is "(.)" and we attempt
      to replace "X" by "($1)", the actual replacement will be "(X".


      This bug is very easy to fix.
      Make changes to the code in the inner while loop of appendReplacement()'s
      parsing routine:

          while (!done) {
              cursor++;
              ^^^^^^^^^ <-- remove
              groupEnd = cursor;
              if (cursor >= replacement.length())
                  break;
              int nextDigit = replacement.charAt(cursor) - '0';
              if ((nextDigit < 0)||(nextDigit > 9)) { // not a number
                  cursor--;
                  ^^^^^^^^^ <-- remove
                  break;
              }
              int newRefNum = (refNum * 10) + nextDigit;
              if (groupCount() < newRefNum)
                  done = true;
              else
                  refNum = newRefNum;
              cursor++;
              ^^^^^^^^^ <-- add
          }


      import java.util.regex.*;

      class TestRegexReplacement
      {

          public void testMoreThanNineMatchGroups() {
              String haystack = "Here is dozenletters!";
              // following pattern has twelve groups, each maches one character
              // of the word dozenletters
              String pattern =
                  ".*(\\w)(\\w)(\\w)(\\w)(\\w)(\\w)(\\w)(\\w)(\\w)(\\w)(\\w)(\\w)";
              String replacement = "You are $12$10$9";
              String expected = "You are set!";

              Pattern p = Pattern.compile( pattern );
              Matcher m = p.matcher( haystack );

              // execute the regex search n' replace
              StringBuffer sb = new StringBuffer();
              m.find();
              m.appendReplacement( sb, replacement );
              m.appendTail( sb );

              System.out.println( "\ntestMoreThanNineMatchGroups()\n" +
                                  "-------------------------------" );
              System.out.println(
                          "Should change \"" + haystack + "\"" +
                          " into: \"" + expected + "\"" );
              System.out.println( "But actually changes it into: \"" + sb + "\"\n" );
          }

          public void testLastCharacterIgnored() {
              String haystack = "__-x-__";
              String pattern = "-(.)-"; // find this needle in haystack
              String replacement = "|$1|"; // replace it with this one
              String expected = "__|x|__"; // expected outcome

              Pattern p = Pattern.compile( pattern );
              Matcher m = p.matcher( haystack );

              // execute the regex search n' replace
              StringBuffer sb = new StringBuffer();
              m.find();
              m.appendReplacement( sb, replacement );
              m.appendTail( sb );

              System.out.println( "\ntestLastCharacterIgnored()\n" +
                                  "-------------------------------" );
              System.out.println(
                          "Should change \"" + haystack + "\"" +
                          " into: \"" + expected + "\"" );
              System.out.println( "But actually changes it into: \"" + sb + "\"\n" );
          }

          public static void main(String[] args) {
              TestRegexReplacement test = new TestRegexReplacement();
              test.testLastCharacterIgnored();
              test.testMoreThanNineMatchGroups();
          }
      }
      (Review ID: 132875)
      ======================================================================

            mmcclosksunw Michael Mccloskey (Inactive)
            nthompsosunw Nathanael Thompson (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: