Skip to content

Commit 03abcb4

Browse files
authored
Ensure meta and document field maps are never null in GetResult (#50112)
This commit ensures deseriable a GetResult from StreamInput does not leave metaFields and documentFields null. This could cause an NPE in situations where upsert response for a document that did not exist is passed back to a node that forwarded the upsert request. closes #48215
1 parent 9a781c6 commit 03abcb4

File tree

2 files changed

+20
-10
lines changed

2 files changed

+20
-10
lines changed

server/src/main/java/org/elasticsearch/index/get/GetResult.java

+7-10
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ public class GetResult implements Writeable, Iterable<DocumentField>, ToXContent
6565
private long seqNo;
6666
private long primaryTerm;
6767
private boolean exists;
68-
private Map<String, DocumentField> documentFields;
69-
private Map<String, DocumentField> metaFields;
68+
private final Map<String, DocumentField> documentFields;
69+
private final Map<String, DocumentField> metaFields;
7070
private Map<String, Object> sourceAsMap;
7171
private BytesReference source;
7272
private byte[] sourceAsBytes;
@@ -95,6 +95,9 @@ public GetResult(StreamInput in) throws IOException {
9595
metaFields = new HashMap<>();
9696
splitFieldsByMetadata(fields, documentFields, metaFields);
9797
}
98+
} else {
99+
metaFields = Collections.emptyMap();
100+
documentFields = Collections.emptyMap();
98101
}
99102
}
100103

@@ -111,14 +114,8 @@ public GetResult(String index, String id, long seqNo, long primaryTerm, long ver
111114
this.version = version;
112115
this.exists = exists;
113116
this.source = source;
114-
this.documentFields = documentFields;
115-
if (this.documentFields == null) {
116-
this.documentFields = emptyMap();
117-
}
118-
this.metaFields = metaFields;
119-
if (this.metaFields == null) {
120-
this.metaFields = emptyMap();
121-
}
117+
this.documentFields = documentFields == null ? emptyMap() : documentFields;
118+
this.metaFields = metaFields == null ? emptyMap() : metaFields;
122119
}
123120

124121
/**

server/src/test/java/org/elasticsearch/index/get/GetResultTests.java

+13
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.elasticsearch.common.bytes.BytesReference;
2525
import org.elasticsearch.common.collect.Tuple;
2626
import org.elasticsearch.common.document.DocumentField;
27+
import org.elasticsearch.common.io.stream.BytesStreamOutput;
2728
import org.elasticsearch.common.xcontent.ToXContent;
2829
import org.elasticsearch.common.xcontent.XContentHelper;
2930
import org.elasticsearch.common.xcontent.XContentParser;
@@ -138,6 +139,18 @@ public void testToXContentEmbeddedNotFound() throws IOException {
138139
assertEquals("{\"found\":false}", originalBytes.utf8ToString());
139140
}
140141

142+
public void testSerializationNotFound() throws IOException {
143+
// serializes and deserializes with streamable, then prints back to xcontent
144+
GetResult getResult = new GetResult("index", "id", UNASSIGNED_SEQ_NO, 0, 1, false, null, null, null);
145+
146+
BytesStreamOutput out = new BytesStreamOutput();
147+
getResult.writeTo(out);
148+
getResult = new GetResult(out.bytes().streamInput());
149+
150+
BytesReference originalBytes = toXContentEmbedded(getResult, XContentType.JSON, false);
151+
assertEquals("{\"found\":false}", originalBytes.utf8ToString());
152+
}
153+
141154
public void testGetSourceAsBytes() {
142155
XContentType xContentType = randomFrom(XContentType.values());
143156
Tuple<GetResult, GetResult> tuple = randomGetResult(xContentType);

0 commit comments

Comments
 (0)