Skip to content

Commit cfb04bd

Browse files
committed
Fixes NPE in bool filter, when an empty should filter clause returns a DocIdSet, but null as iterator.
Closes elastic#4685
1 parent 9734a79 commit cfb04bd

File tree

2 files changed

+39
-7
lines changed

2 files changed

+39
-7
lines changed

src/main/java/org/elasticsearch/common/lucene/search/XBooleanFilter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ public DocIdSet getDocIdSet(AtomicReaderContext context, Bits acceptDocs) throws
282282
for (int setDoc = it.nextDoc(); setDoc != DocIdSetIterator.NO_MORE_DOCS; setDoc = it.nextDoc()) {
283283
for (ResultClause fastOrClause : fastOrClauses) {
284284
DocIdSetIterator clauseIterator = fastOrClause.iterator();
285-
if (it == null) {
285+
if (clauseIterator == null) {
286286
continue;
287287
}
288288
if (iteratorMatch(clauseIterator, setDoc)) {

src/test/java/org/elasticsearch/common/lucene/search/XBooleanFilterTests.java

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import org.apache.lucene.queries.TermFilter;
1010
import org.apache.lucene.search.*;
1111
import org.apache.lucene.store.Directory;
12+
import org.apache.lucene.util.Bits;
1213
import org.apache.lucene.util.FixedBitSet;
1314
import org.elasticsearch.common.lucene.Lucene;
1415
import org.elasticsearch.test.ElasticsearchLuceneTestCase;
@@ -433,21 +434,36 @@ public void testRandom() throws IOException {
433434
case 6:
434435
case 5:
435436
hasMust = true;
436-
clauses[i] = newFilterClause(field, value, MUST, random().nextBoolean());
437-
topLevel.add(new BooleanClause(new TermQuery(new Term(String.valueOf(field), String.valueOf(value))), MUST));
437+
if (rarely()) {
438+
clauses[i] = new FilterClause(new EmptyFilter(), MUST);
439+
topLevel.add(new BooleanClause(new MatchNoDocsQuery(), MUST));
440+
} else {
441+
clauses[i] = newFilterClause(field, value, MUST, random().nextBoolean());
442+
topLevel.add(new BooleanClause(new TermQuery(new Term(String.valueOf(field), String.valueOf(value))), MUST));
443+
}
438444
break;
439445
case 4:
440446
case 3:
441447
case 2:
442448
case 1:
443449
hasShould = true;
444-
clauses[i] = newFilterClause(field, value, SHOULD, random().nextBoolean());
445-
orQuery.add(new BooleanClause(new TermQuery(new Term(String.valueOf(field), String.valueOf(value))), SHOULD));
450+
if (rarely()) {
451+
clauses[i] = new FilterClause(new EmptyFilter(), SHOULD);
452+
orQuery.add(new BooleanClause(new MatchNoDocsQuery(), SHOULD));
453+
} else {
454+
clauses[i] = newFilterClause(field, value, SHOULD, random().nextBoolean());
455+
orQuery.add(new BooleanClause(new TermQuery(new Term(String.valueOf(field), String.valueOf(value))), SHOULD));
456+
}
446457
break;
447458
case 0:
448459
hasMustNot = true;
449-
clauses[i] = newFilterClause(field, value, MUST_NOT, random().nextBoolean());
450-
topLevel.add(new BooleanClause(new TermQuery(new Term(String.valueOf(field), String.valueOf(value))), MUST_NOT));
460+
if (rarely()) {
461+
clauses[i] = new FilterClause(new EmptyFilter(), MUST_NOT);
462+
topLevel.add(new BooleanClause(new MatchNoDocsQuery(), MUST_NOT));
463+
} else {
464+
clauses[i] = newFilterClause(field, value, MUST_NOT, random().nextBoolean());
465+
topLevel.add(new BooleanClause(new TermQuery(new Term(String.valueOf(field), String.valueOf(value))), MUST_NOT));
466+
}
451467
break;
452468

453469
}
@@ -512,5 +528,21 @@ public String toString() {
512528
}
513529
}
514530

531+
public final class EmptyFilter extends Filter {
532+
533+
@Override
534+
public DocIdSet getDocIdSet(AtomicReaderContext context, Bits acceptDocs) throws IOException {
535+
return random().nextBoolean() ? new Empty() : null;
536+
}
537+
538+
private class Empty extends DocIdSet {
539+
540+
@Override
541+
public DocIdSetIterator iterator() throws IOException {
542+
return null;
543+
}
544+
}
545+
}
546+
515547
}
516548

0 commit comments

Comments
 (0)