You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ce...@apache.org on 2019/12/31 16:52:55 UTC

svn commit: r1872145 - in /poi/trunk: src/java/org/apache/poi/ss/formula/functions/ src/testcases/org/apache/poi/hssf/usermodel/ src/testcases/org/apache/poi/ss/formula/functions/ test-data/spreadsheet/

Author: centic
Date: Tue Dec 31 16:52:55 2019
New Revision: 1872145

URL: http://svn.apache.org/viewvc?rev=1872145&view=rev
Log:
Bug 63940: Avoid endless loop/out of memory on string-replace with empty search string

Added:
    poi/trunk/src/testcases/org/apache/poi/ss/formula/functions/TestSubstitute.java
    poi/trunk/test-data/spreadsheet/SUBSTITUTE.xls
Modified:
    poi/trunk/src/java/org/apache/poi/ss/formula/functions/Substitute.java
    poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java

Modified: poi/trunk/src/java/org/apache/poi/ss/formula/functions/Substitute.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/formula/functions/Substitute.java?rev=1872145&r1=1872144&r2=1872145&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/formula/functions/Substitute.java (original)
+++ poi/trunk/src/java/org/apache/poi/ss/formula/functions/Substitute.java Tue Dec 31 16:52:55 2019
@@ -64,11 +64,15 @@ public final class Substitute extends Va
 	}
 
 	private static String replaceAllOccurrences(String oldStr, String searchStr, String newStr) {
+		// avoid endless loop when searching for nothing
+		if (searchStr.length() < 1) {
+			return oldStr;
+		}
+
 		StringBuilder sb = new StringBuilder();
 		int startIndex = 0;
-		int nextMatch;
 		while (true) {
-			nextMatch = oldStr.indexOf(searchStr, startIndex);
+			int nextMatch = oldStr.indexOf(searchStr, startIndex);
 			if (nextMatch < 0) {
 				// store everything from end of last match to end of string
 				sb.append(oldStr.substring(startIndex));
@@ -82,25 +86,23 @@ public final class Substitute extends Va
 	}
 
 	private static String replaceOneOccurrence(String oldStr, String searchStr, String newStr, int instanceNumber) {
+		// avoid endless loop when searching for nothing
 		if (searchStr.length() < 1) {
 			return oldStr;
 		}
 		int startIndex = 0;
-		int nextMatch = -1;
 		int count=0;
 		while (true) {
-			nextMatch = oldStr.indexOf(searchStr, startIndex);
+			int nextMatch = oldStr.indexOf(searchStr, startIndex);
 			if (nextMatch < 0) {
 				// not enough occurrences found - leave unchanged
 				return oldStr;
 			}
 			count++;
 			if (count == instanceNumber) {
-				StringBuilder sb = new StringBuilder(oldStr.length() + newStr.length());
-				sb.append(oldStr, 0, nextMatch);
-				sb.append(newStr);
-				sb.append(oldStr.substring(nextMatch + searchStr.length()));
-				return sb.toString();
+				return oldStr.substring(0, nextMatch) +
+						newStr +
+						oldStr.substring(nextMatch + searchStr.length());
 			}
 			startIndex = nextMatch + searchStr.length();
 		}

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java?rev=1872145&r1=1872144&r2=1872145&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java Tue Dec 31 16:52:55 2019
@@ -2879,7 +2879,7 @@ public final class TestBugs extends Base
         FormulaEvaluator eval = wb.getCreationHelper().createFormulaEvaluator();
 
         eval.evaluateAll();
-        
+
         /*OutputStream out = new FileOutputStream("C:\\temp\\48043.xls");
         try {
           wb.write(out);
@@ -3119,20 +3119,25 @@ public final class TestBugs extends Base
 
     @Test
     public void test60460() throws IOException {
-        final Workbook wb = HSSFTestDataSamples.openSampleWorkbook("60460.xls");
-
-        assertEquals(2, wb.getAllNames().size());
+        try (final Workbook wb = HSSFTestDataSamples.openSampleWorkbook("60460.xls")) {
+            assertEquals(2, wb.getAllNames().size());
 
-        Name rangedName = wb.getAllNames().get(0);
-        assertFalse(rangedName.isFunctionName());
-        assertEquals("'[\\\\HEPPC3\\gt$\\Teaching\\Syn\\physyn.xls]#REF'!$AK$70:$AL$70",
-                // replace '/' to make test work equally on Windows and Linux
-                rangedName.getRefersToFormula().replace("/", "\\"));
-
-        rangedName = wb.getAllNames().get(1);
-        assertFalse(rangedName.isFunctionName());
-        assertEquals("Questionnaire!$A$1:$L$65", rangedName.getRefersToFormula());
+            Name rangedName = wb.getAllNames().get(0);
+            assertFalse(rangedName.isFunctionName());
+            assertEquals("'[\\\\HEPPC3\\gt$\\Teaching\\Syn\\physyn.xls]#REF'!$AK$70:$AL$70",
+                    // replace '/' to make test work equally on Windows and Linux
+                    rangedName.getRefersToFormula().replace("/", "\\"));
+
+            rangedName = wb.getAllNames().get(1);
+            assertFalse(rangedName.isFunctionName());
+            assertEquals("Questionnaire!$A$1:$L$65", rangedName.getRefersToFormula());
+        }
+    }
 
-        wb.close();
+    @Test
+    public void test63940() throws IOException {
+        try (final Workbook wb = HSSFTestDataSamples.openSampleWorkbook("SUBSTITUTE.xls")) {
+            wb.getCreationHelper().createFormulaEvaluator().evaluateAll();
+        }
     }
 }

Added: poi/trunk/src/testcases/org/apache/poi/ss/formula/functions/TestSubstitute.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/ss/formula/functions/TestSubstitute.java?rev=1872145&view=auto
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/ss/formula/functions/TestSubstitute.java (added)
+++ poi/trunk/src/testcases/org/apache/poi/ss/formula/functions/TestSubstitute.java Tue Dec 31 16:52:55 2019
@@ -0,0 +1,89 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.ss.formula.functions;
+
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.StringEval;
+import org.apache.poi.ss.formula.eval.StringValueEval;
+import org.apache.poi.ss.usermodel.FormulaError;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestSubstitute {
+    @Test
+    public void testSubstitute() {
+        Substitute fun = new Substitute();
+        assertEquals("ADEFC", ((StringValueEval)fun.evaluate(0, 1,
+                new StringEval("ABC"), new StringEval("B"), new StringEval("DEF"))).getStringValue());
+
+        assertEquals("ACDEC", ((StringValueEval)fun.evaluate(0, 1,
+                new StringEval("ABC"), new StringEval("B"), new StringEval("CDE"))).getStringValue());
+
+        assertEquals("ACDECCDEA", ((StringValueEval)fun.evaluate(0, 1,
+                new StringEval("ABCBA"), new StringEval("B"), new StringEval("CDE"))).getStringValue());
+    }
+
+    @Test
+    public void testSubstituteInvalidArg() {
+        Substitute fun = new Substitute();
+        assertEquals(ErrorEval.valueOf(FormulaError.VALUE.getLongCode()),
+                fun.evaluate(0, 1,
+                ErrorEval.valueOf(FormulaError.VALUE.getLongCode()), new StringEval("B"), new StringEval("DEF")));
+
+        assertEquals(ErrorEval.valueOf(FormulaError.VALUE.getLongCode()),
+                fun.evaluate(0, 1,
+                ErrorEval.valueOf(FormulaError.VALUE.getLongCode()), new StringEval("B"), new StringEval("DEF"),
+                        new NumberEval(1)));
+
+        // fails on occurrence below 1
+        assertEquals(ErrorEval.valueOf(FormulaError.VALUE.getLongCode()),
+                fun.evaluate(0, 1,
+                new StringEval("ABC"), new StringEval("B"), new StringEval("CDE"), new NumberEval(0)));
+    }
+
+    @Test
+    public void testSubstituteOne() {
+        Substitute fun = new Substitute();
+        assertEquals("ADEFC", ((StringValueEval)fun.evaluate(0, 1,
+                new StringEval("ABC"), new StringEval("B"), new StringEval("DEF"), new NumberEval(1))).getStringValue());
+
+        assertEquals("ACDEC", ((StringValueEval)fun.evaluate(0, 1,
+                new StringEval("ABC"), new StringEval("B"), new StringEval("CDE"), new NumberEval(1))).getStringValue());
+    }
+
+    @Test
+    public void testSubstituteNotFound() {
+        Substitute fun = new Substitute();
+        assertEquals("ABC", ((StringValueEval)fun.evaluate(0, 1,
+                new StringEval("ABC"), new StringEval("B"), new StringEval("DEF"), new NumberEval(12))).getStringValue());
+
+        assertEquals("ABC", ((StringValueEval)fun.evaluate(0, 1,
+                new StringEval("ABC"), new StringEval("B"), new StringEval("CDE"), new NumberEval(2))).getStringValue());
+    }
+
+    @Test
+    public void testSearchEmpty() {
+        Substitute fun = new Substitute();
+        assertEquals("ABC", ((StringValueEval)fun.evaluate(0, 1,
+                new StringEval("ABC"), new StringEval(""), new StringEval("CDE"))).getStringValue());
+        assertEquals("ABC", ((StringValueEval)fun.evaluate(0, 1,
+                new StringEval("ABC"), new StringEval(""), new StringEval("CDE"), new NumberEval(1))).getStringValue());
+    }
+}
\ No newline at end of file

Added: poi/trunk/test-data/spreadsheet/SUBSTITUTE.xls
URL: http://svn.apache.org/viewvc/poi/trunk/test-data/spreadsheet/SUBSTITUTE.xls?rev=1872145&view=auto
==============================================================================
Binary files poi/trunk/test-data/spreadsheet/SUBSTITUTE.xls (added) and poi/trunk/test-data/spreadsheet/SUBSTITUTE.xls Tue Dec 31 16:52:55 2019 differ



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org