You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by dw...@apache.org on 2021/02/08 21:44:36 UTC
[lucene-solr] branch branch_8x updated: LUCENE-9744: NPE on a
degenerate query in
MinimumShouldMatchIntervalsSource$MinimumMatchesIterator.getSubMatches()
(#2323) (#2324)
This is an automated email from the ASF dual-hosted git repository.
dweiss pushed a commit to branch branch_8x
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git
The following commit(s) were added to refs/heads/branch_8x by this push:
new 190c172 LUCENE-9744: NPE on a degenerate query in MinimumShouldMatchIntervalsSource$MinimumMatchesIterator.getSubMatches() (#2323) (#2324)
190c172 is described below
commit 190c1728989f1e51924bd7e633e3489278fc7480
Author: Dawid Weiss <da...@carrotsearch.com>
AuthorDate: Mon Feb 8 22:43:08 2021 +0100
LUCENE-9744: NPE on a degenerate query in MinimumShouldMatchIntervalsSource$MinimumMatchesIterator.getSubMatches() (#2323) (#2324)
---
lucene/CHANGES.txt | 4 +-
.../apache/lucene/queries/intervals/Intervals.java | 10 +++
.../MinimumShouldMatchIntervalsSource.java | 1 +
.../queries/intervals/NoMatchIntervalsSource.java | 75 ++++++++++++++++++++++
.../lucene/queries/intervals/TestIntervals.java | 21 ++++++
.../queries/intervals/TestSimplifications.java | 8 +++
6 files changed, 118 insertions(+), 1 deletion(-)
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index 535528b..155270f 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -39,7 +39,9 @@ Optimizations
Bug Fixes
---------------------
-(No changes)
+
+* LUCENE-9744: NPE on a degenerate query in MinimumShouldMatchIntervalsSource
+ $MinimumMatchesIterator.getSubMatches(). (Alan Woodward)
Other
---------------------
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/intervals/Intervals.java b/lucene/queries/src/java/org/apache/lucene/queries/intervals/Intervals.java
index 5d835bd..fcdcf4f 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/intervals/Intervals.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/intervals/Intervals.java
@@ -442,6 +442,16 @@ public final class Intervals {
* Return intervals that span combinations of intervals from {@code minShouldMatch} of the sources
*/
public static IntervalsSource atLeast(int minShouldMatch, IntervalsSource... sources) {
+ if (minShouldMatch == sources.length) {
+ return unordered(sources);
+ }
+ if (minShouldMatch > sources.length) {
+ return new NoMatchIntervalsSource(
+ "Too few sources to match minimum of ["
+ + minShouldMatch
+ + "]: "
+ + Arrays.toString(sources));
+ }
return new MinimumShouldMatchIntervalsSource(sources, minShouldMatch);
}
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/intervals/MinimumShouldMatchIntervalsSource.java b/lucene/queries/src/java/org/apache/lucene/queries/intervals/MinimumShouldMatchIntervalsSource.java
index ce3a6de..4cc2cfb 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/intervals/MinimumShouldMatchIntervalsSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/intervals/MinimumShouldMatchIntervalsSource.java
@@ -43,6 +43,7 @@ class MinimumShouldMatchIntervalsSource extends IntervalsSource {
private final int minShouldMatch;
MinimumShouldMatchIntervalsSource(IntervalsSource[] sources, int minShouldMatch) {
+ assert minShouldMatch < sources.length;
this.sources = sources;
this.minShouldMatch = minShouldMatch;
}
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/intervals/NoMatchIntervalsSource.java b/lucene/queries/src/java/org/apache/lucene/queries/intervals/NoMatchIntervalsSource.java
new file mode 100644
index 0000000..cfa7364
--- /dev/null
+++ b/lucene/queries/src/java/org/apache/lucene/queries/intervals/NoMatchIntervalsSource.java
@@ -0,0 +1,75 @@
+/*
+ * 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.lucene.queries.intervals;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Objects;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.search.QueryVisitor;
+
+/** A source returning no matches */
+class NoMatchIntervalsSource extends IntervalsSource {
+ final String reason;
+
+ NoMatchIntervalsSource(String reason) {
+ this.reason = reason;
+ }
+
+ @Override
+ public IntervalIterator intervals(String field, LeafReaderContext ctx) throws IOException {
+ return null;
+ }
+
+ @Override
+ public IntervalMatchesIterator matches(String field, LeafReaderContext ctx, int doc)
+ throws IOException {
+ return null;
+ }
+
+ @Override
+ public void visit(String field, QueryVisitor visitor) {}
+
+ @Override
+ public int minExtent() {
+ return 0;
+ }
+
+ @Override
+ public Collection<IntervalsSource> pullUpDisjunctions() {
+ return Collections.singleton(this);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ NoMatchIntervalsSource that = (NoMatchIntervalsSource) o;
+ return Objects.equals(reason, that.reason);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(reason);
+ }
+
+ @Override
+ public String toString() {
+ return "NOMATCH(" + reason + ")";
+ }
+}
diff --git a/lucene/queries/src/test/org/apache/lucene/queries/intervals/TestIntervals.java b/lucene/queries/src/test/org/apache/lucene/queries/intervals/TestIntervals.java
index 5444b66..2329ea8 100644
--- a/lucene/queries/src/test/org/apache/lucene/queries/intervals/TestIntervals.java
+++ b/lucene/queries/src/test/org/apache/lucene/queries/intervals/TestIntervals.java
@@ -761,6 +761,27 @@ public class TestIntervals extends LuceneTestCase {
}
+ public void testDegenerateMinShouldMatch() throws IOException {
+ IntervalsSource source =
+ Intervals.ordered(
+ Intervals.atLeast(1, Intervals.term("interest")),
+ Intervals.atLeast(1, Intervals.term("anyone")));
+
+ MatchesIterator mi = getMatches(source, 0, "field1");
+ assertMatch(mi, 2, 4, 11, 29);
+ MatchesIterator subs = mi.getSubMatches();
+ assertNotNull(subs);
+ assertMatch(subs, 2, 2, 11, 19);
+ assertMatch(subs, 4, 4, 23, 29);
+ assertFalse(subs.next());
+ assertFalse(mi.next());
+ }
+
+ public void testNoMatchMinShouldMatch() throws IOException {
+ IntervalsSource source = Intervals.atLeast(4, Intervals.term("a"), Intervals.term("b"));
+ checkIntervals(source, "field", 0, new int[][] {});
+ }
+
public void testDefinedGaps() throws IOException {
IntervalsSource source = Intervals.phrase(
Intervals.term("pease"),
diff --git a/lucene/queries/src/test/org/apache/lucene/queries/intervals/TestSimplifications.java b/lucene/queries/src/test/org/apache/lucene/queries/intervals/TestSimplifications.java
index 76a4857..8706c12 100644
--- a/lucene/queries/src/test/org/apache/lucene/queries/intervals/TestSimplifications.java
+++ b/lucene/queries/src/test/org/apache/lucene/queries/intervals/TestSimplifications.java
@@ -93,4 +93,12 @@ public class TestSimplifications extends LuceneTestCase {
assertEquals(Intervals.or(Intervals.term("a"), Intervals.term("b"), Intervals.term("c"), Intervals.term("d")), actual);
}
+ public void testMinShouldMatchSimplifications() {
+ IntervalsSource expected = Intervals.unordered(Intervals.term("a"), Intervals.term("b"));
+ assertEquals(expected, Intervals.atLeast(2, Intervals.term("a"), Intervals.term("b")));
+
+ assertEquals(
+ "NOMATCH(Too few sources to match minimum of [3]: [a, b])",
+ Intervals.atLeast(3, Intervals.term("a"), Intervals.term("b")).toString());
+ }
}