Restrict GraphTokenStreamFiniteStrings#articulationPointsRecurse recursion depth (#12249)

This commit is contained in:
Chris Fournier 2023-06-12 12:20:10 -04:00 committed by GitHub
parent ef35e6edf4
commit 41baf23ad9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 1 deletions

View File

@ -190,6 +190,8 @@ Bug Fixes
* GITHUB#12352: [Tessellator] Improve the checks that validate the diagonal between two polygon nodes so
the resulting polygons are valid counter clockwise polygons. (Ignacio Vera)
* LUCENE-10181: Restrict GraphTokenStreamFiniteStrings#articulationPointsRecurse recursion depth. (Chris Fournier)
Other
---------------------
(No changes)

View File

@ -45,6 +45,8 @@ import org.apache.lucene.util.automaton.Transition;
* different paths of the {@link Automaton}.
*/
public final class GraphTokenStreamFiniteStrings {
/** Maximum level of recursion allowed in recursive operations. */
private static final int MAX_RECURSION_LEVEL = 1000;
private AttributeSource[] tokens = new AttributeSource[4];
private final Automaton det;
@ -271,7 +273,12 @@ public final class GraphTokenStreamFiniteStrings {
a.getNextTransition(t);
if (visited.get(t.dest) == false) {
parent[t.dest] = state;
articulationPointsRecurse(a, t.dest, d + 1, depth, low, parent, visited, points);
if (d < MAX_RECURSION_LEVEL) {
articulationPointsRecurse(a, t.dest, d + 1, depth, low, parent, visited, points);
} else {
throw new IllegalArgumentException(
"Exceeded maximum recursion level during graph analysis");
}
childCount++;
if (low[t.dest] >= depth[state]) {
isArticulation = true;

View File

@ -16,6 +16,7 @@
*/
package org.apache.lucene.util.graph;
import java.util.ArrayList;
import java.util.Iterator;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
@ -660,4 +661,27 @@ public class TestGraphTokenStreamFiniteStrings extends LuceneTestCase {
it.next(), new String[] {"king", "alfred", "saxons", "ruled"}, new int[] {1, 1, 3, 1});
assertFalse(it.hasNext());
}
public void testLongTokenStreamStackOverflowError() throws Exception {
ArrayList<Token> tokens =
new ArrayList<Token>() {
{
add(token("fast", 1, 1));
add(token("wi", 1, 1));
add(token("wifi", 0, 2));
add(token("fi", 1, 1));
}
};
// Add in too many tokens to get a high depth graph
for (int i = 0; i < 1024 + 1; i++) {
tokens.add(token("network", 1, 1));
}
TokenStream ts = new CannedTokenStream(tokens.toArray(new Token[0]));
GraphTokenStreamFiniteStrings graph = new GraphTokenStreamFiniteStrings(ts);
assertThrows(IllegalArgumentException.class, graph::articulationPoints);
}
}