Skip to content

Commit 3bde396

Browse files
committed
Fix a race condition in Derived Field parsing from search request
Signed-off-by: Rishabh Maurya <[email protected]>
1 parent f5dbbb0 commit 3bde396

File tree

5 files changed

+72
-42
lines changed

5 files changed

+72
-42
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
99
- [Remote Store] Rate limiter for remote store low priority uploads ([#14374](https://github.com/opensearch-project/OpenSearch/pull/14374/))
1010
- Apply the date histogram rewrite optimization to range aggregation ([#13865](https://github.com/opensearch-project/OpenSearch/pull/13865))
1111
- [Writable Warm] Add composite directory implementation and integrate it with FileCache ([12782](https://github.com/opensearch-project/OpenSearch/pull/12782))
12+
- Fix a race condition in derived field defined in search request ([14445](https://github.com/opensearch-project/OpenSearch/pull/14445))
1213

1314
### Dependencies
1415
- Bump `org.gradle.test-retry` from 1.5.8 to 1.5.9 ([#13442](https://github.com/opensearch-project/OpenSearch/pull/13442))

modules/ingest-common/src/main/java/org/opensearch/ingest/common/CopyProcessor.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
package org.opensearch.ingest.common;
1010

11+
import org.opensearch.common.util.CopyUtil;
1112
import org.opensearch.core.common.Strings;
1213
import org.opensearch.ingest.AbstractProcessor;
1314
import org.opensearch.ingest.ConfigurationUtils;
@@ -95,7 +96,7 @@ public IngestDocument execute(IngestDocument document) {
9596

9697
if (overrideTarget || document.hasField(target, true) == false || document.getFieldValue(target, Object.class) == null) {
9798
Object sourceValue = document.getFieldValue(source, Object.class);
98-
document.setFieldValue(target, IngestDocument.deepCopy(sourceValue));
99+
document.setFieldValue(target, CopyUtil.deepCopy(sourceValue));
99100
} else {
100101
throw new IllegalArgumentException("target field [" + target + "] already exists");
101102
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.common.util;
10+
11+
import java.time.ZonedDateTime;
12+
import java.util.ArrayList;
13+
import java.util.Arrays;
14+
import java.util.Date;
15+
import java.util.HashMap;
16+
import java.util.List;
17+
import java.util.Map;
18+
19+
/**
20+
* Utility class for deep copying Object of different types.
21+
*/
22+
public class CopyUtil {
23+
24+
/**
25+
* Deep copies the provided object
26+
* @return cloned object after deep copy. Throws {@link IllegalArgumentException} for unsupported object type.
27+
*/
28+
public static Object deepCopy(Object value) {
29+
if (value instanceof Map) {
30+
Map<?, ?> mapValue = (Map<?, ?>) value;
31+
Map<Object, Object> copy = new HashMap<>(mapValue.size());
32+
for (Map.Entry<?, ?> entry : mapValue.entrySet()) {
33+
copy.put(entry.getKey(), deepCopy(entry.getValue()));
34+
}
35+
return copy;
36+
} else if (value instanceof List) {
37+
List<?> listValue = (List<?>) value;
38+
List<Object> copy = new ArrayList<>(listValue.size());
39+
for (Object itemValue : listValue) {
40+
copy.add(deepCopy(itemValue));
41+
}
42+
return copy;
43+
} else if (value instanceof byte[]) {
44+
byte[] bytes = (byte[]) value;
45+
return Arrays.copyOf(bytes, bytes.length);
46+
} else if (value == null
47+
|| value instanceof Byte
48+
|| value instanceof Character
49+
|| value instanceof Short
50+
|| value instanceof String
51+
|| value instanceof Integer
52+
|| value instanceof Long
53+
|| value instanceof Float
54+
|| value instanceof Double
55+
|| value instanceof Boolean
56+
|| value instanceof ZonedDateTime) {
57+
return value;
58+
} else if (value instanceof Date) {
59+
return ((Date) value).clone();
60+
} else {
61+
throw new IllegalArgumentException("unexpected value type [" + value.getClass() + "]");
62+
}
63+
}
64+
}

server/src/main/java/org/opensearch/index/mapper/DefaultDerivedFieldResolver.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.apache.logging.log4j.Logger;
1313
import org.opensearch.common.regex.Regex;
1414
import org.opensearch.index.query.QueryShardContext;
15+
import org.opensearch.ingest.IngestDocument;
1516
import org.opensearch.script.Script;
1617

1718
import java.io.IOException;
@@ -189,9 +190,10 @@ private void initDerivedFieldTypes(Map<String, Object> derivedFieldsObject, List
189190

190191
private Map<String, DerivedFieldType> getAllDerivedFieldTypeFromObject(Map<String, Object> derivedFieldObject) {
191192
Map<String, DerivedFieldType> derivedFieldTypes = new HashMap<>();
193+
// deep copy of derivedFieldObject is required as DocumentMapperParser modifies the map
192194
DocumentMapper documentMapper = queryShardContext.getMapperService()
193195
.documentMapperParser()
194-
.parse(DerivedFieldMapper.CONTENT_TYPE, derivedFieldObject);
196+
.parse(DerivedFieldMapper.CONTENT_TYPE, IngestDocument.deepCopyMap(derivedFieldObject));
195197
if (documentMapper != null && documentMapper.mappers() != null) {
196198
for (Mapper mapper : documentMapper.mappers()) {
197199
if (mapper instanceof DerivedFieldMapper) {

server/src/main/java/org/opensearch/ingest/IngestDocument.java

Lines changed: 2 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
package org.opensearch.ingest;
3434

35+
import org.opensearch.common.util.CopyUtil;
3536
import org.opensearch.core.common.Strings;
3637
import org.opensearch.core.common.util.CollectionUtils;
3738
import org.opensearch.index.VersionType;
@@ -45,10 +46,8 @@
4546
import java.time.ZoneOffset;
4647
import java.time.ZonedDateTime;
4748
import java.util.ArrayList;
48-
import java.util.Arrays;
4949
import java.util.Base64;
5050
import java.util.Collections;
51-
import java.util.Date;
5251
import java.util.EnumMap;
5352
import java.util.HashMap;
5453
import java.util.LinkedHashSet;
@@ -754,44 +753,7 @@ public Map<String, Object> getSourceAndMetadata() {
754753
@SuppressWarnings("unchecked")
755754
public static <K, V> Map<K, V> deepCopyMap(Map<K, V> source) {
756755
CollectionUtils.ensureNoSelfReferences(source, "IngestDocument: Self reference present in object.");
757-
return (Map<K, V>) deepCopy(source);
758-
}
759-
760-
public static Object deepCopy(Object value) {
761-
if (value instanceof Map) {
762-
Map<?, ?> mapValue = (Map<?, ?>) value;
763-
Map<Object, Object> copy = new HashMap<>(mapValue.size());
764-
for (Map.Entry<?, ?> entry : mapValue.entrySet()) {
765-
copy.put(entry.getKey(), deepCopy(entry.getValue()));
766-
}
767-
return copy;
768-
} else if (value instanceof List) {
769-
List<?> listValue = (List<?>) value;
770-
List<Object> copy = new ArrayList<>(listValue.size());
771-
for (Object itemValue : listValue) {
772-
copy.add(deepCopy(itemValue));
773-
}
774-
return copy;
775-
} else if (value instanceof byte[]) {
776-
byte[] bytes = (byte[]) value;
777-
return Arrays.copyOf(bytes, bytes.length);
778-
} else if (value == null
779-
|| value instanceof Byte
780-
|| value instanceof Character
781-
|| value instanceof Short
782-
|| value instanceof String
783-
|| value instanceof Integer
784-
|| value instanceof Long
785-
|| value instanceof Float
786-
|| value instanceof Double
787-
|| value instanceof Boolean
788-
|| value instanceof ZonedDateTime) {
789-
return value;
790-
} else if (value instanceof Date) {
791-
return ((Date) value).clone();
792-
} else {
793-
throw new IllegalArgumentException("unexpected value type [" + value.getClass() + "]");
794-
}
756+
return (Map<K, V>) CopyUtil.deepCopy(source);
795757
}
796758

797759
/**

0 commit comments

Comments
 (0)