diff --git a/src/main/java/org/elasticsearch/search/internal/DefaultSearchContext.java b/src/main/java/org/elasticsearch/search/internal/DefaultSearchContext.java index 433222b281a..3d6244e11b4 100644 --- a/src/main/java/org/elasticsearch/search/internal/DefaultSearchContext.java +++ b/src/main/java/org/elasticsearch/search/internal/DefaultSearchContext.java @@ -63,6 +63,7 @@ import org.elasticsearch.search.fetch.script.ScriptFieldsContext; import org.elasticsearch.search.fetch.source.FetchSourceContext; import org.elasticsearch.search.highlight.SearchContextHighlight; import org.elasticsearch.search.lookup.SearchLookup; +import org.elasticsearch.search.query.QueryPhaseExecutionException; import org.elasticsearch.search.query.QuerySearchResult; import org.elasticsearch.search.rescore.RescoreSearchContext; import org.elasticsearch.search.scan.ScanContext; @@ -213,6 +214,15 @@ public class DefaultSearchContext extends SearchContext { * Should be called before executing the main query and after all other parameters have been set. */ public void preProcess() { + if (!(from() == -1 && size() == -1)) { + // from and size have been set. + int numHits = from() + size(); + if (numHits < 0) { + String msg = "Result window is too large, from + size must be less than or equal to: [" + Integer.MAX_VALUE + "] but was [" + (((long) from()) + ((long) size())) + "]"; + throw new QueryPhaseExecutionException(this, msg); + } + } + if (query() == null) { parsedQuery(ParsedQuery.parsedMatchAllQuery()); } diff --git a/src/main/java/org/elasticsearch/search/query/QueryPhaseExecutionException.java b/src/main/java/org/elasticsearch/search/query/QueryPhaseExecutionException.java index 233f73340e3..6d968fce6bb 100644 --- a/src/main/java/org/elasticsearch/search/query/QueryPhaseExecutionException.java +++ b/src/main/java/org/elasticsearch/search/query/QueryPhaseExecutionException.java @@ -30,4 +30,8 @@ public class QueryPhaseExecutionException extends SearchContextException { public QueryPhaseExecutionException(SearchContext context, String msg, Throwable cause) { super(context, "Query Failed [" + msg + "]", cause); } + + public QueryPhaseExecutionException(SearchContext context, String msg) { + super(context, msg); + } } diff --git a/src/test/java/org/elasticsearch/search/simple/SimpleSearchTests.java b/src/test/java/org/elasticsearch/search/simple/SimpleSearchTests.java index 02e4354227c..1063175f22b 100644 --- a/src/test/java/org/elasticsearch/search/simple/SimpleSearchTests.java +++ b/src/test/java/org/elasticsearch/search/simple/SimpleSearchTests.java @@ -21,6 +21,7 @@ package org.elasticsearch.search.simple; import org.elasticsearch.ElasticsearchIllegalArgumentException; import org.elasticsearch.action.index.IndexRequestBuilder; +import org.elasticsearch.action.search.SearchPhaseExecutionException; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.xcontent.XContentFactory; @@ -39,6 +40,7 @@ import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.index.query.QueryBuilders.boolQuery; import static org.elasticsearch.index.query.QueryBuilders.rangeQuery; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.*; +import static org.hamcrest.Matchers.containsString; public class SimpleSearchTests extends ElasticsearchIntegrationTest { @@ -244,4 +246,17 @@ public class SimpleSearchTests extends ElasticsearchIntegrationTest { assertHitCount(searchResponse, max); assertFalse(searchResponse.isTerminatedEarly()); } + + @Test + public void testInsaneFrom() throws Exception { + createIndex("idx"); + indexRandom(true, client().prepareIndex("idx", "type").setSource("{}")); + + try { + client().prepareSearch("idx").setFrom(Integer.MAX_VALUE).get(); + fail(); + } catch (SearchPhaseExecutionException e) { + assertThat(e.getMessage(), containsString("Result window is too large, from + size must be less than or equal to:")); + } + } }