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&gt;yp&lt;e&amp;" + XmlFixture.ENCODED_TEXT
+                + "</type>\n"
+                + "<id>i&lt;&amp;d&gt;" + 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&gt;yp&lt;e&amp;" + XmlFixture.ENCODED_TEXT
+                + "</type>\n"
+                + "<id>" + "id&amp;&lt;-name&gt;" + XmlFixture.ENCODED_TEXT
+                + "@id&amp;&lt;-enterprise-number&gt;" + 
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 = " &apos;&quot;\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>

Reply via email to