summaryrefslogtreecommitdiff
path: root/icu4j/main/core/src/main/java/com/ibm/icu/text/CanonicalIterator.java
diff options
context:
space:
mode:
Diffstat (limited to 'icu4j/main/core/src/main/java/com/ibm/icu/text/CanonicalIterator.java')
-rw-r--r--icu4j/main/core/src/main/java/com/ibm/icu/text/CanonicalIterator.java26
1 files changed, 24 insertions, 2 deletions
diff --git a/icu4j/main/core/src/main/java/com/ibm/icu/text/CanonicalIterator.java b/icu4j/main/core/src/main/java/com/ibm/icu/text/CanonicalIterator.java
index 56b36d90c..39baae1b6 100644
--- a/icu4j/main/core/src/main/java/com/ibm/icu/text/CanonicalIterator.java
+++ b/icu4j/main/core/src/main/java/com/ibm/icu/text/CanonicalIterator.java
@@ -154,6 +154,10 @@ public final class CanonicalIterator {
}
}
+ // To avoid infinity loop caused by permute, we limit the depth of recursive
+ // call to permute and throw exception.
+ // We know in some unit test we need at least 4. Set to 8 just in case some
+ // unforseen use cases.
/**
* Simple implementation of permutation.
* <br><b>Warning: The strings are not guaranteed to be in any particular order.</b>
@@ -165,9 +169,27 @@ public final class CanonicalIterator {
*/
@Deprecated
public static void permute(String source, boolean skipZeros, Set<String> output) {
+ permute(source, skipZeros, output, 0);
+ }
+
+ private static int PERMUTE_DEPTH_LIMIT = 8;
+ /**
+ * Simple implementation of permutation.
+ * <br><b>Warning: The strings are not guaranteed to be in any particular order.</b>
+ * @param source the string to find permutations for
+ * @param skipZeros set to true to skip characters with canonical combining class zero
+ * @param output the set to add the results to
+ * @param depth the depth of the recursive call.
+ * @internal
+ * @deprecated This API is ICU internal only.
+ */
+ @Deprecated
+ private static void permute(String source, boolean skipZeros, Set<String> output, int depth) {
// TODO: optimize
//if (PROGRESS) System.out.println("Permute: " + source);
-
+ if (depth > PERMUTE_DEPTH_LIMIT) {
+ throw new UnsupportedOperationException("Stack too deep:" + depth);
+ }
// optimization:
// if zero or one character, just return a set with it
// we check for length < 2 to keep from counting code points all the time
@@ -193,7 +215,7 @@ public final class CanonicalIterator {
// see what the permutations of the characters before and after this one are
subpermute.clear();
permute(source.substring(0,i)
- + source.substring(i + UTF16.getCharCount(cp)), skipZeros, subpermute);
+ + source.substring(i + UTF16.getCharCount(cp)), skipZeros, subpermute, depth+1);
// prefix this character to all of them
String chStr = UTF16.valueOf(source, i);