Uploaded image for project: 'Commons Lang'
  1. Commons Lang
  2. LANG-15

Infinite loop in StringUtils.replace(text, repl, with) + FIX

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 2.0
    • 2.0
    • lang.*
    • None
    • Operating System: Linux
      Platform: PC

    • 16204

    Description

      Hopefully I can give back a little after having had so much
      benefit of your work.

      I will refer to the sources from commons-lang-1.0.1-src.zip, downloaded
      the 17 January 2003.

      Detail:
      =======
      In org.apache.commons.lang.StringUtils: If you invoke
      public static String replace(String text, String repl, String with)
      with arguments:
      text != null
      repl.equals("")
      with anything

      you get an infinite loop as "FOO".indexOf("") == 0.

      Demo:
      =====
      To demonstrate the bug, please add the following lines in
      org.apache.commons.lang.StringUtilsTest in the body of
      testReplaceFunctions(), line 194:

      public void testReplaceFunctions()

      { //... existing code //-- bug demonstration, added by HoKr assertEquals("replace(String, String, String) failed", "FOO", StringUtils.replace("FOO", "", "any")); }

      I got an OutOfMemoryException then.

      Fix:
      ====
      My suggestion to fix this in StringUtils.replace(String, String, String),
      line 593:

      public static String replace(String text, String repl, String with,
      int max) {
      if (text == null)

      { return null; }

      //-- FIX SUGGESTION START >>>
      //-- added by HoKr for infinite loop avoidance
      //-- keeps on throwing NullPointerException if repl == null
      //-- -->> this is faster than "".equals(repl); NPE allowed.
      if (repl.length() == 0) { return text; }
      //-- <<< FIX SUGGESTION END

      StringBuffer buf = new StringBuffer(text.length());
      int start = 0, end = 0;
      while ((end = text.indexOf(repl, start)) != -1) {
      buf.append(text.substring(start, end)).append(with);
      start = end + repl.length();

      if (--max == 0) { break; }
      }
      buf.append(text.substring(start));
      return buf.toString();
      }

      Further:
      ========
      Further I suggest instead of throwing NullPointerExceptions
      if (repl == null || with == null) to return the parameter text then.

      It would meet closer the expectation of what the method should perform from
      my point of view in these cases.

      This behaviour would be payed with 2 extra comparisons to null
      (before the while-loop) in 'normal' operation mode though.

      The Code would be:

      public static String replace(String text, String repl, String with,
      int max) {
      if (text == null) { return null; }

      //-- START >>>
      //-- suggestion by HoKr, BUT would CHANGE outside behaviour:
      //-- not throwing NPE any more!
      if (repl == null || with == null)

      { return text; }
      //-- added by HoKr for infinite loop avoidance
      //-- keeps on throwing NullPointerException if repl == null
      if (repl.length() == 0) { return text; }

      //-- <<< END

      StringBuffer buf = new StringBuffer(text.length());
      int start = 0, end = 0;
      while ((end = text.indexOf(repl, start)) != -1) {
      buf.append(text.substring(start, end)).append(with);
      start = end + repl.length();

      if (--max == 0)

      { break; }

      }
      buf.append(text.substring(start));
      return buf.toString();
      }

      Regards,
      Holger Krauth

      Attachments

        Activity

          People

            Unassigned Unassigned
            holger.krauth@danet.de Holger Krauth
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: