浏览代码

Fix potential NPE in FuzzyTermsEnum (#53231)

Under certain circumstances SpanMultiTermQueryWrapper uses
SpanBooleanQueryRewriteWithMaxClause as its rewrite method, which in turn tries
to get a TermsEnum from the wrapped MultiTermQuery currently using a `null`
AttributeSource. While queries TermsQuery or subclasses of AutomatonQuery ignore
this argument, FuzzyQuery uses it to create a FuzzyTermsEnum which triggers an
NPE when the AttributeSource is not provided. This PR fixes this by supplying an
empty AttributeSource instead of a `null` value.

Closes #52894
Christoph Büscher 5 年之前
父节点
当前提交
649a22803d

+ 4 - 2
server/src/main/java/org/elasticsearch/common/lucene/search/SpanBooleanQueryRewriteWithMaxClause.java

@@ -33,6 +33,7 @@ import org.apache.lucene.search.spans.SpanMultiTermQueryWrapper;
 import org.apache.lucene.search.spans.SpanOrQuery;
 import org.apache.lucene.search.spans.SpanQuery;
 import org.apache.lucene.search.spans.SpanTermQuery;
+import org.apache.lucene.util.AttributeSource;
 import org.apache.lucene.util.BytesRef;
 
 import java.io.IOException;
@@ -92,11 +93,12 @@ public class SpanBooleanQueryRewriteWithMaxClause extends SpanMultiTermQueryWrap
                         continue;
                     }
 
-                    final TermsEnum termsEnum = getTermsEnum(query, terms, null);
+                    final TermsEnum termsEnum = getTermsEnum(query, terms, new AttributeSource());
                     assert termsEnum != null;
 
-                    if (termsEnum == TermsEnum.EMPTY)
+                    if (termsEnum == TermsEnum.EMPTY) {
                         continue;
+                    }
 
                     BytesRef bytes;
                     while ((bytes = termsEnum.next()) != null) {

+ 20 - 0
server/src/test/java/org/elasticsearch/search/query/SearchQueryIT.java

@@ -19,7 +19,10 @@
 
 package org.elasticsearch.search.query;
 
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.MultiTermQuery;
 import org.apache.lucene.search.join.ScoreMode;
+import org.apache.lucene.util.AttributeSource;
 import org.apache.lucene.util.English;
 import org.elasticsearch.action.index.IndexRequestBuilder;
 import org.elasticsearch.action.search.SearchPhaseExecutionException;
@@ -28,6 +31,7 @@ import org.elasticsearch.action.search.SearchType;
 import org.elasticsearch.action.search.ShardSearchFailure;
 import org.elasticsearch.bootstrap.JavaVersion;
 import org.elasticsearch.common.document.DocumentField;
+import org.elasticsearch.common.lucene.search.SpanBooleanQueryRewriteWithMaxClause;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.time.DateFormatter;
 import org.elasticsearch.common.unit.Fuzziness;
@@ -1758,4 +1762,20 @@ public class SearchQueryIT extends ESIntegTestCase {
        }
 
    }
+
+    /**
+     * Test correct handling {@link SpanBooleanQueryRewriteWithMaxClause#rewrite(IndexReader, MultiTermQuery)}. That rewrite method is e.g.
+     * set for fuzzy queries with "constant_score" rewrite nested inside a `span_multi` query and would cause NPEs due to an unset
+     * {@link AttributeSource}.
+     */
+    public void testIssueFuzzyInsideSpanMulti() {
+        createIndex("test");
+        client().prepareIndex("test").setId("1").setSource("field", "foobarbaz").get();
+        ensureGreen();
+        refresh();
+
+        BoolQueryBuilder query = boolQuery().filter(spanMultiTermQueryBuilder(fuzzyQuery("field", "foobarbiz").rewrite("constant_score")));
+        SearchResponse response = client().prepareSearch("test").setQuery(query).get();
+        assertHitCount(response, 1);
+    }
 }