diff --git a/core/src/main/java/hudson/util/RobustMapConverter.java b/core/src/main/java/hudson/util/RobustMapConverter.java index 896138ace0e9..f845e38771cc 100644 --- a/core/src/main/java/hudson/util/RobustMapConverter.java +++ b/core/src/main/java/hudson/util/RobustMapConverter.java @@ -25,6 +25,7 @@ package hudson.util; import com.thoughtworks.xstream.XStreamException; +import com.thoughtworks.xstream.converters.ConversionException; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.converters.collections.MapConverter; import com.thoughtworks.xstream.io.HierarchicalStreamReader; @@ -64,6 +65,12 @@ final class RobustMapConverter extends MapConverter { } private Object read(HierarchicalStreamReader reader, UnmarshallingContext context, Map map) { + if (!reader.hasMoreChildren()) { + var exception = new ConversionException("Invalid map entry"); + reader.appendErrors(exception); + RobustReflectionConverter.addErrorInContext(context, exception); + return ERROR; + } reader.moveDown(); try { return readBareItem(reader, context, map); diff --git a/core/src/test/java/hudson/util/RobustMapConverterTest.java b/core/src/test/java/hudson/util/RobustMapConverterTest.java index d5ac80124ea8..b74ac9303f71 100644 --- a/core/src/test/java/hudson/util/RobustMapConverterTest.java +++ b/core/src/test/java/hudson/util/RobustMapConverterTest.java @@ -25,6 +25,7 @@ package hudson.util; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThrows; @@ -142,4 +143,48 @@ private Map preparePayload() { } return map; } + + @Test + public void robustAgainstInvalidEntry() { + XStream2 xstream2 = new XStream2(); + String xml = + """ + + + key1 + + key2 + value2 + + + + """; + Data data = (Data) xstream2.fromXML(xml); + assertThat(data.map, equalTo(Map.of("key2", "value2"))); + } + + @Test + public void robustAgainstInvalidEntryWithNoValue() { + XStream2 xstream2 = new XStream2(); + String xml = + """ + + + + key1 + + + key2 + value2 + + + + """; + Data data = (Data) xstream2.fromXML(xml); + assertThat(data.map, equalTo(Map.of("key2", "value2"))); + } + + private static final class Data { + Map map; + } }