This is an automated email from the ASF dual-hosted git repository.
vy pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
The following commit(s) were added to refs/heads/2.x by this push:
new 6beea3feb0 Fix encoding of `MSGID` and `SD-ID` fields of
`StructuredDataMessage` to XML (#4136)
6beea3feb0 is described below
commit 6beea3feb0e5ec59ed85db14075bb7837b0a968f
Author: Volkan Yazıcı <[email protected]>
AuthorDate: Fri Jun 5 10:13:02 2026 +0200
Fix encoding of `MSGID` and `SD-ID` fields of `StructuredDataMessage` to
XML (#4136)
---
.../log4j/message/StructuredDataMessageTest.java | 58 ++++++++++++++++++++++
.../log4j/message/StructuredDataMessage.java | 20 +++++++-
.../fix-StructuredDataMessage-XML-encoding.xml | 12 +++++
3 files changed, 88 insertions(+), 2 deletions(-)
diff --git
a/log4j-api-test/src/test/java/org/apache/logging/log4j/message/StructuredDataMessageTest.java
b/log4j-api-test/src/test/java/org/apache/logging/log4j/message/StructuredDataMessageTest.java
index f02d95eefe..3d3f403bef 100644
---
a/log4j-api-test/src/test/java/org/apache/logging/log4j/message/StructuredDataMessageTest.java
+++
b/log4j-api-test/src/test/java/org/apache/logging/log4j/message/StructuredDataMessageTest.java
@@ -73,6 +73,64 @@ class StructuredDataMessageTest {
assertEquals(expected, result);
}
+ @Test
+ void testXmlEncodingOfIdAndType1() {
+ final String id = "i<&d>" + XmlFixture.TEXT;
+ final String type = "t>yp<e&" + XmlFixture.TEXT;
+ final String actualXml =
+ new StructuredDataMessage(id, "discarded message",
type).getFormattedMessage(new String[] {"XML"});
+ final String expectedXml = "<StructuredData>\n"
+ + "<type>t>yp<e&" + XmlFixture.ENCODED_TEXT
+ + "</type>\n"
+ + "<id>i<&d>" + XmlFixture.ENCODED_TEXT
+ + "</id>\n"
+ // Following part is encoded by `MapMessage::asXml`, hence,
fuzzed & tested elsewhere
+ + "<Map>\n"
+ + "</Map>\n"
+ + "</StructuredData>\n";
+ assertEquals(expectedXml, actualXml);
+ }
+
+ @Test
+ void testXmlEncodingOfIdAndType2() {
+ final String idName = "id&<-name>" + XmlFixture.TEXT;
+ final String idEnterpriseNumber = "id&<-enterprise-number>" +
XmlFixture.TEXT;
+ final String[] idRequired = {"id&<-required>" + XmlFixture.TEXT};
+ final String[] idOptional = {"id&<-optional>" + XmlFixture.TEXT};
+ final String type = "t>yp<e&" + XmlFixture.TEXT;
+ final StructuredDataId id =
+ new StructuredDataId(idName, idEnterpriseNumber, idRequired,
idOptional, Integer.MAX_VALUE);
+ final String actualXml =
+ new StructuredDataMessage(id, "discarded message",
type).getFormattedMessage(new String[] {"XML"});
+ final String expectedXml = "<StructuredData>\n"
+ + "<type>t>yp<e&" + XmlFixture.ENCODED_TEXT
+ + "</type>\n"
+ + "<id>" + "id&<-name>" + XmlFixture.ENCODED_TEXT
+ + "@id&<-enterprise-number>" +
XmlFixture.ENCODED_TEXT
+ + "</id>\n"
+ // Following part is encoded by `MapMessage::asXml`, hence,
fuzzed & tested elsewhere
+ + "<Map>\n"
+ + "</Map>\n"
+ + "</StructuredData>\n";
+ assertEquals(expectedXml, actualXml);
+ }
+
+ private enum XmlFixture {
+ ;
+
+ private static final String TEXT;
+
+ private static final String ENCODED_TEXT;
+
+ static {
+ final String notBmp = new String(Character.toChars(0x10000));
+ final String invalid = "A\uD800B\uDE00C\0\1\2\3";
+ final String encodedInvalid =
"A\uFFFDB\uFFFDC\uFFFD\uFFFD\uFFFD\uFFFD";
+ TEXT = " '\"\t\r\n" + notBmp + invalid;
+ ENCODED_TEXT = " '"\t\r\n" + notBmp + encodedInvalid;
+ }
+ }
+
@Test
void testBuilder() {
final String testMsg = "Test message {}";
diff --git
a/log4j-api/src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java
b/log4j-api/src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java
index 46b757d54f..69fa3fb8cb 100644
---
a/log4j-api/src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java
+++
b/log4j-api/src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java
@@ -356,10 +356,26 @@ public class StructuredDataMessage extends
MapMessage<StructuredDataMessage, Str
}
private void asXml(final StructuredDataId structuredDataId, final
StringBuilder sb) {
+
sb.append("<StructuredData>\n");
- sb.append("<type>").append(type).append("</type>\n");
- sb.append("<id>").append(structuredDataId).append("</id>\n");
+
+ // Encode type
+ sb.append("<type>");
+ int start = sb.length();
+ sb.append(type);
+ StringBuilders.escapeXml(sb, start);
+ sb.append("</type>\n");
+
+ // Encode ID
+ sb.append("<id>");
+ start = sb.length();
+ structuredDataId.formatTo(sb);
+ StringBuilders.escapeXml(sb, start);
+ sb.append("</id>\n");
+
+ // Encode the rest
super.asXml(sb);
+
sb.append("\n</StructuredData>\n");
}
diff --git a/src/changelog/.2.x.x/fix-StructuredDataMessage-XML-encoding.xml
b/src/changelog/.2.x.x/fix-StructuredDataMessage-XML-encoding.xml
new file mode 100644
index 0000000000..ae324c0d21
--- /dev/null
+++ b/src/changelog/.2.x.x/fix-StructuredDataMessage-XML-encoding.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entry xmlns="https://logging.apache.org/xml/ns"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ https://logging.apache.org/xml/ns
+ https://logging.apache.org/xml/ns/log4j-changelog-0.xsd"
+ type="fixed">
+ <issue id="4136" link="https://github.com/apache/logging-log4j2/pull/4136"/>
+ <description format="asciidoc">
+ Fix encoding of `MSGID` and `SD-ID` fields of `StructuredDataMessage` to
XML
+ </description>
+</entry>