From 65e7aba780c058649064627163a45f1c90065f1f Mon Sep 17 00:00:00 2001 From: Martijn van Groningen Date: Wed, 9 Sep 2015 12:07:16 +0200 Subject: [PATCH] inner hits: Protected against specifying a size larger than the total amount of documents in an index. Closes #13394 --- .../fetch/innerhits/InnerHitsContext.java | 4 +-- .../search/innerhits/InnerHitsIT.java | 35 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/elasticsearch/search/fetch/innerhits/InnerHitsContext.java b/core/src/main/java/org/elasticsearch/search/fetch/innerhits/InnerHitsContext.java index a0df6388812..2887a83ad8f 100644 --- a/core/src/main/java/org/elasticsearch/search/fetch/innerhits/InnerHitsContext.java +++ b/core/src/main/java/org/elasticsearch/search/fetch/innerhits/InnerHitsContext.java @@ -123,7 +123,7 @@ public final class InnerHitsContext { if (size() == 0) { return new TopDocs(context.searcher().count(q), Lucene.EMPTY_SCORE_DOCS, 0); } else { - int topN = from() + size(); + int topN = Math.min(from() + size(), context.searcher().getIndexReader().maxDoc()); TopDocsCollector topDocsCollector; if (sort() != null) { try { @@ -303,7 +303,7 @@ public final class InnerHitsContext { final int count = context.searcher().count(q); return new TopDocs(count, Lucene.EMPTY_SCORE_DOCS, 0); } else { - int topN = from() + size(); + int topN = Math.min(from() + size(), context.searcher().getIndexReader().maxDoc()); TopDocsCollector topDocsCollector; if (sort() != null) { topDocsCollector = TopFieldCollector.create(sort(), topN, true, trackScores(), trackScores()); diff --git a/core/src/test/java/org/elasticsearch/search/innerhits/InnerHitsIT.java b/core/src/test/java/org/elasticsearch/search/innerhits/InnerHitsIT.java index 8b4ef4ed5e5..ba432864c29 100644 --- a/core/src/test/java/org/elasticsearch/search/innerhits/InnerHitsIT.java +++ b/core/src/test/java/org/elasticsearch/search/innerhits/InnerHitsIT.java @@ -19,6 +19,7 @@ package org.elasticsearch.search.innerhits; +import org.apache.lucene.util.ArrayUtil; import org.elasticsearch.Version; import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus; import org.elasticsearch.action.index.IndexRequestBuilder; @@ -1131,4 +1132,38 @@ public class InnerHitsIT extends ESIntegTestCase { assertThat(response.getHits().getAt(0).getInnerHits().get("child").getAt(0).getMatchedQueries()[0], equalTo("_name2")); } + @Test + public void testDontExplode() throws Exception { + assertAcked(prepareCreate("index1").addMapping("child", "_parent", "type=parent")); + List requests = new ArrayList<>(); + requests.add(client().prepareIndex("index1", "parent", "1").setSource("{}")); + requests.add(client().prepareIndex("index1", "child", "1").setParent("1").setSource("field", "value1")); + indexRandom(true, requests); + + SearchResponse response = client().prepareSearch("index1") + .setQuery(hasChildQuery("child", matchQuery("field", "value1")).innerHit(new QueryInnerHitBuilder().setSize(ArrayUtil.MAX_ARRAY_LENGTH - 1))) + .addSort("_uid", SortOrder.ASC) + .get(); + assertNoFailures(response); + assertHitCount(response, 1); + + assertAcked(prepareCreate("index2").addMapping("type", "nested", "type=nested")); + client().prepareIndex("index2", "type", "1").setSource(jsonBuilder().startObject() + .startArray("nested") + .startObject() + .field("field", "value1") + .endObject() + .endArray() + .endObject()) + .setRefresh(true) + .get(); + + response = client().prepareSearch("index2") + .setQuery(nestedQuery("nested", matchQuery("nested.field", "value1")).innerHit(new QueryInnerHitBuilder().setSize(ArrayUtil.MAX_ARRAY_LENGTH - 1))) + .addSort("_uid", SortOrder.ASC) + .get(); + assertNoFailures(response); + assertHitCount(response, 1); + } + }