Skip to content

Commit 00bb78b

Browse files
cwperksnibix
andauthored
Introduced new setting search.query.max_query_string_length (#19491) (#19814)
Co-authored-by: Nils Bandener <33570290+nibix@users.noreply.github.com>
1 parent d69262e commit 00bb78b

File tree

5 files changed

+66
-0
lines changed

5 files changed

+66
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
## [Unreleased 2.x]
77
### Added
88
- Reject close index requests, while remote store migration is in progress.([#18327](https://github.com/opensearch-project/OpenSearch/pull/18327))
9+
- New cluster setting search.query.max_query_string_length ([#19491](https://github.com/opensearch-project/OpenSearch/pull/19491))
910

1011
### Dependencies
1112
- Bump `netty` from 4.1.118.Final to 4.1.125.Final ([#18192](https://github.com/opensearch-project/OpenSearch/pull/18192)) ([#19270](https://github.com/opensearch-project/OpenSearch/pull/19270))

server/src/internalClusterTest/java/org/opensearch/search/query/SimpleQueryStringIT.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
import static org.opensearch.index.query.QueryBuilders.termQuery;
8181
import static org.opensearch.search.SearchService.CLUSTER_CONCURRENT_SEGMENT_SEARCH_SETTING;
8282
import static org.opensearch.search.SearchService.INDICES_MAX_CLAUSE_COUNT_SETTING;
83+
import static org.opensearch.search.SearchService.SEARCH_MAX_QUERY_STRING_LENGTH;
8384
import static org.opensearch.test.StreamsUtils.copyToStringFromClasspath;
8485
import static org.opensearch.test.hamcrest.OpenSearchAssertions.assertAcked;
8586
import static org.opensearch.test.hamcrest.OpenSearchAssertions.assertFailures;
@@ -767,6 +768,34 @@ public void testDynamicClauseCountUpdate() throws Exception {
767768
);
768769
}
769770

771+
public void testMaxQueryStringLength() throws Exception {
772+
try {
773+
String indexBody = copyToStringFromClasspath("/org/opensearch/search/query/all-query-index.json");
774+
assertAcked(prepareCreate("test").setSource(indexBody, MediaTypeRegistry.JSON));
775+
ensureGreen("test");
776+
777+
assertAcked(
778+
client().admin()
779+
.cluster()
780+
.prepareUpdateSettings()
781+
.setTransientSettings(Settings.builder().put(SEARCH_MAX_QUERY_STRING_LENGTH.getKey(), 10))
782+
);
783+
784+
SearchPhaseExecutionException e = expectThrows(SearchPhaseExecutionException.class, () -> {
785+
client().prepareSearch("test").setQuery(queryStringQuery("foo OR foo OR foo OR foo")).get();
786+
});
787+
788+
assertThat(e.getDetailedMessage(), containsString("Query string length exceeds max allowed length 10"));
789+
} finally {
790+
assertAcked(
791+
client().admin()
792+
.cluster()
793+
.prepareUpdateSettings()
794+
.setTransientSettings(Settings.builder().putNull(SEARCH_MAX_QUERY_STRING_LENGTH.getKey()))
795+
);
796+
}
797+
}
798+
770799
private void assertHits(SearchHits hits, String... ids) {
771800
assertThat(hits.getTotalHits().value, equalTo((long) ids.length));
772801
Set<String> hitIds = new HashSet<>();

server/src/main/java/org/opensearch/common/settings/ClusterSettings.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,7 @@ public void apply(Settings value, Settings current, Settings previous) {
556556
SearchService.MAX_PIT_KEEPALIVE_SETTING,
557557
SearchService.MAX_AGGREGATION_REWRITE_FILTERS,
558558
SearchService.INDICES_MAX_CLAUSE_COUNT_SETTING,
559+
SearchService.SEARCH_MAX_QUERY_STRING_LENGTH,
559560
SearchService.CARDINALITY_AGGREGATION_PRUNING_THRESHOLD,
560561
SearchService.KEYWORD_INDEX_OR_DOC_VALUES_ENABLED,
561562
CreatePitController.PIT_INIT_KEEP_ALIVE,

server/src/main/java/org/opensearch/index/search/QueryStringQueryParser.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import org.apache.lucene.util.BytesRef;
5959
import org.opensearch.common.lucene.search.Queries;
6060
import org.opensearch.common.regex.Regex;
61+
import org.opensearch.common.settings.Settings;
6162
import org.opensearch.common.unit.Fuzziness;
6263
import org.opensearch.common.util.io.IOUtils;
6364
import org.opensearch.index.IndexSettings;
@@ -69,6 +70,7 @@
6970
import org.opensearch.index.query.ExistsQueryBuilder;
7071
import org.opensearch.index.query.MultiMatchQueryBuilder;
7172
import org.opensearch.index.query.QueryShardContext;
73+
import org.opensearch.search.SearchService;
7274

7375
import java.io.IOException;
7476
import java.time.ZoneId;
@@ -94,6 +96,8 @@
9496
*/
9597
public class QueryStringQueryParser extends XQueryParser {
9698
private static final String EXISTS_FIELD = "_exists_";
99+
@SuppressWarnings("NonFinalStaticField")
100+
private static int maxQueryStringLength = SearchService.SEARCH_MAX_QUERY_STRING_LENGTH.get(Settings.EMPTY);
97101

98102
private final QueryShardContext context;
99103
private final Map<String, Float> fieldsAndWeights;
@@ -860,6 +864,23 @@ public Query parse(String query) throws ParseException {
860864
if (query.trim().isEmpty()) {
861865
return Queries.newMatchNoDocsQuery("Matching no documents because no terms present");
862866
}
867+
if (query.length() > maxQueryStringLength) {
868+
throw new ParseException(
869+
"Query string length exceeds max allowed length "
870+
+ maxQueryStringLength
871+
+ " ("
872+
+ SearchService.SEARCH_MAX_QUERY_STRING_LENGTH.getKey()
873+
+ "); actual length: "
874+
+ query.length()
875+
);
876+
}
863877
return super.parse(query);
864878
}
879+
880+
/**
881+
* Sets the maximum allowed length for query strings. This should be only called from SearchService on settings updates.
882+
*/
883+
public static void setMaxQueryStringLength(int maxQueryStringLength) {
884+
QueryStringQueryParser.maxQueryStringLength = maxQueryStringLength;
885+
}
865886
}

server/src/main/java/org/opensearch/search/SearchService.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
import org.opensearch.index.query.QueryRewriteContext;
9090
import org.opensearch.index.query.QueryShardContext;
9191
import org.opensearch.index.query.Rewriteable;
92+
import org.opensearch.index.search.QueryStringQueryParser;
9293
import org.opensearch.index.shard.IndexEventListener;
9394
import org.opensearch.index.shard.IndexShard;
9495
import org.opensearch.index.shard.SearchOperationListener;
@@ -327,6 +328,15 @@ public class SearchService extends AbstractLifecycleComponent implements IndexEv
327328
Setting.Property.Dynamic
328329
);
329330

331+
public static final Setting<Integer> SEARCH_MAX_QUERY_STRING_LENGTH = Setting.intSetting(
332+
"search.query.max_query_string_length",
333+
32_000,
334+
1,
335+
Integer.MAX_VALUE,
336+
Setting.Property.NodeScope,
337+
Setting.Property.Dynamic
338+
);
339+
330340
public static final Setting<Boolean> CLUSTER_ALLOW_DERIVED_FIELD_SETTING = Setting.boolSetting(
331341
"search.derived_field.enabled",
332342
true,
@@ -469,6 +479,10 @@ public SearchService(
469479
IndexSearcher.setMaxClauseCount(INDICES_MAX_CLAUSE_COUNT_SETTING.get(settings));
470480
clusterService.getClusterSettings().addSettingsUpdateConsumer(INDICES_MAX_CLAUSE_COUNT_SETTING, IndexSearcher::setMaxClauseCount);
471481

482+
QueryStringQueryParser.setMaxQueryStringLength(SEARCH_MAX_QUERY_STRING_LENGTH.get(settings));
483+
clusterService.getClusterSettings()
484+
.addSettingsUpdateConsumer(SEARCH_MAX_QUERY_STRING_LENGTH, QueryStringQueryParser::setMaxQueryStringLength);
485+
472486
allowDerivedField = CLUSTER_ALLOW_DERIVED_FIELD_SETTING.get(settings);
473487
clusterService.getClusterSettings().addSettingsUpdateConsumer(CLUSTER_ALLOW_DERIVED_FIELD_SETTING, this::setAllowDerivedField);
474488

0 commit comments

Comments
 (0)