Skip to content

Commit 078b05a

Browse files
Fix SnapshotInfo.fromXContentInternal not Fully Consuming Parser (#73268) (#73274)
The parsing here was causing trouble with the new streaming deserialization because it did not fully consume the parser so if the internal buffer of the parser was just enough to finish reading the `"snapshot"` field but missed the closing bracket, then the stream behind the parser would not have been consumed fully. Also it was strangely lenient and would just read a broken in-progress `SnapshotInfo` if it ran into SMILE that contained any object field under any key that isn't "snapshot". I made it a little stricter now to enforce that we have a "snapshot" field and not just an object field by any name.
1 parent ae48ae1 commit 078b05a

File tree

1 file changed

+62
-62
lines changed

1 file changed

+62
-62
lines changed

server/src/main/java/org/elasticsearch/snapshots/SnapshotInfo.java

Lines changed: 62 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -829,76 +829,76 @@ public static SnapshotInfo fromXContentInternal(final XContentParser parser) thr
829829
parser.nextToken();
830830
}
831831
XContentParser.Token token;
832+
XContentParserUtils.ensureFieldName(parser, parser.currentToken(), SNAPSHOT);
832833
XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser);
833-
String currentFieldName = parser.currentName();
834-
if (SNAPSHOT.equals(currentFieldName)) {
835-
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
836-
if (token == XContentParser.Token.FIELD_NAME) {
837-
currentFieldName = parser.currentName();
838-
token = parser.nextToken();
839-
if (token.isValue()) {
840-
if (NAME.equals(currentFieldName)) {
841-
name = parser.text();
842-
} else if (UUID.equals(currentFieldName)) {
843-
uuid = parser.text();
844-
} else if (STATE.equals(currentFieldName)) {
845-
state = SnapshotState.valueOf(parser.text());
846-
} else if (REASON.equals(currentFieldName)) {
847-
reason = parser.text();
848-
} else if (START_TIME.equals(currentFieldName)) {
849-
startTime = parser.longValue();
850-
} else if (END_TIME.equals(currentFieldName)) {
851-
endTime = parser.longValue();
852-
} else if (TOTAL_SHARDS.equals(currentFieldName)) {
853-
totalShards = parser.intValue();
854-
} else if (SUCCESSFUL_SHARDS.equals(currentFieldName)) {
855-
successfulShards = parser.intValue();
856-
} else if (VERSION_ID.equals(currentFieldName)) {
857-
version = Version.fromId(parser.intValue());
858-
} else if (INCLUDE_GLOBAL_STATE.equals(currentFieldName)) {
859-
includeGlobalState = parser.booleanValue();
834+
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
835+
if (token == XContentParser.Token.FIELD_NAME) {
836+
final String currentFieldName = parser.currentName();
837+
token = parser.nextToken();
838+
if (token.isValue()) {
839+
if (NAME.equals(currentFieldName)) {
840+
name = parser.text();
841+
} else if (UUID.equals(currentFieldName)) {
842+
uuid = parser.text();
843+
} else if (STATE.equals(currentFieldName)) {
844+
state = SnapshotState.valueOf(parser.text());
845+
} else if (REASON.equals(currentFieldName)) {
846+
reason = parser.text();
847+
} else if (START_TIME.equals(currentFieldName)) {
848+
startTime = parser.longValue();
849+
} else if (END_TIME.equals(currentFieldName)) {
850+
endTime = parser.longValue();
851+
} else if (TOTAL_SHARDS.equals(currentFieldName)) {
852+
totalShards = parser.intValue();
853+
} else if (SUCCESSFUL_SHARDS.equals(currentFieldName)) {
854+
successfulShards = parser.intValue();
855+
} else if (VERSION_ID.equals(currentFieldName)) {
856+
version = Version.fromId(parser.intValue());
857+
} else if (INCLUDE_GLOBAL_STATE.equals(currentFieldName)) {
858+
includeGlobalState = parser.booleanValue();
859+
}
860+
} else if (token == XContentParser.Token.START_ARRAY) {
861+
if (DATA_STREAMS.equals(currentFieldName)) {
862+
dataStreams = new ArrayList<>();
863+
while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
864+
dataStreams.add(parser.text());
865+
}
866+
} else if (INDICES.equals(currentFieldName)) {
867+
ArrayList<String> indicesArray = new ArrayList<>();
868+
while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
869+
indicesArray.add(parser.text());
860870
}
861-
} else if (token == XContentParser.Token.START_ARRAY) {
862-
if (DATA_STREAMS.equals(currentFieldName)){
863-
dataStreams = new ArrayList<>();
864-
while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
865-
dataStreams.add(parser.text());
866-
}
867-
} else if (INDICES.equals(currentFieldName)) {
868-
ArrayList<String> indicesArray = new ArrayList<>();
869-
while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
870-
indicesArray.add(parser.text());
871-
}
872-
indices = Collections.unmodifiableList(indicesArray);
873-
} else if (FAILURES.equals(currentFieldName)) {
874-
ArrayList<SnapshotShardFailure> shardFailureArrayList = new ArrayList<>();
875-
while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
876-
shardFailureArrayList.add(SnapshotShardFailure.fromXContent(parser));
877-
}
878-
shardFailures = Collections.unmodifiableList(shardFailureArrayList);
879-
} else if (FEATURE_STATES.equals(currentFieldName)) {
880-
ArrayList<SnapshotFeatureInfo> snapshotFeatureInfoArrayList = new ArrayList<>();
881-
while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
882-
snapshotFeatureInfoArrayList.add(SnapshotFeatureInfo.fromXContent(parser));
883-
}
884-
featureStates = Collections.unmodifiableList(snapshotFeatureInfoArrayList);
885-
} else {
886-
// It was probably created by newer version - ignoring
887-
parser.skipChildren();
871+
indices = Collections.unmodifiableList(indicesArray);
872+
} else if (FAILURES.equals(currentFieldName)) {
873+
ArrayList<SnapshotShardFailure> shardFailureArrayList = new ArrayList<>();
874+
while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
875+
shardFailureArrayList.add(SnapshotShardFailure.fromXContent(parser));
888876
}
889-
} else if (token == XContentParser.Token.START_OBJECT) {
890-
if (USER_METADATA.equals(currentFieldName)) {
891-
userMetadata = parser.map();
892-
} else if (INDEX_DETAILS.equals(currentFieldName)) {
893-
indexSnapshotDetails = parser.map(HashMap::new, p -> IndexSnapshotDetails.PARSER.parse(p, null));
894-
} else {
895-
// It was probably created by newer version - ignoring
896-
parser.skipChildren();
877+
shardFailures = Collections.unmodifiableList(shardFailureArrayList);
878+
} else if (FEATURE_STATES.equals(currentFieldName)) {
879+
ArrayList<SnapshotFeatureInfo> snapshotFeatureInfoArrayList = new ArrayList<>();
880+
while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
881+
snapshotFeatureInfoArrayList.add(SnapshotFeatureInfo.fromXContent(parser));
897882
}
883+
featureStates = Collections.unmodifiableList(snapshotFeatureInfoArrayList);
884+
} else {
885+
// It was probably created by newer version - ignoring
886+
parser.skipChildren();
887+
}
888+
} else if (token == XContentParser.Token.START_OBJECT) {
889+
if (USER_METADATA.equals(currentFieldName)) {
890+
userMetadata = parser.map();
891+
} else if (INDEX_DETAILS.equals(currentFieldName)) {
892+
indexSnapshotDetails = parser.map(HashMap::new, p -> IndexSnapshotDetails.PARSER.parse(p, null));
893+
} else {
894+
// It was probably created by newer version - ignoring
895+
parser.skipChildren();
898896
}
899897
}
900898
}
901899
}
900+
// closing bracket of the object containing the "snapshot" field should be there
901+
XContentParserUtils.ensureExpectedToken(XContentParser.Token.END_OBJECT, parser.nextToken(), parser);
902902
if (uuid == null) {
903903
// the old format where there wasn't a UUID
904904
uuid = name;

0 commit comments

Comments
 (0)