File: 04-CVE-2025-54812-1-Escape-loggername.patch

package info (click to toggle)
log4cxx 1.4.0-1%2Bdeb13u1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 5,636 kB
  • sloc: cpp: 47,740; xml: 1,041; sh: 43; makefile: 17
file content (131 lines) | stat: -rw-r--r-- 4,530 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
Description: CVE-2025-54812 - part 1 - Improper HTML escaping in HTMLLayout
Origin: https://github.com/apache/logging-log4cxx/commit/1c599de956ae9eedd8b5e3f744bfb867c39e8bba
Bug: https://logging.apache.org/security.html#CVE-2025-54812
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1111879

From 1c599de956ae9eedd8b5e3f744bfb867c39e8bba Mon Sep 17 00:00:00 2001
From: Stephen Webb <stephen.webb@ieee.org>
Date: Sat, 12 Jul 2025 10:19:03 +1000
Subject: [PATCH] Escape any logger name '&' or '"' in html attribute data
 (#509)

---
 src/main/cpp/htmllayout.cpp        |  8 ++---
 src/test/cpp/xml/xmllayouttest.cpp | 49 ++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/src/main/cpp/htmllayout.cpp b/src/main/cpp/htmllayout.cpp
index c2411ece9..ed6e61d76 100644
--- a/src/main/cpp/htmllayout.cpp
+++ b/src/main/cpp/htmllayout.cpp
@@ -109,25 +109,25 @@ void HTMLLayout::format(LogString& output,
 	if (event->getLevel()->equals(Level::getDebug()))
 	{
 		output.append(LOG4CXX_STR("<font color=\"#339933\">"));
-		output.append(event->getLevel()->toString());
+		Transform::appendEscapingTags(output, event->getLevel()->toString());
 		output.append(LOG4CXX_STR("</font>"));
 	}
 	else if (event->getLevel()->isGreaterOrEqual(Level::getWarn()))
 	{
 		output.append(LOG4CXX_STR("<font color=\"#993300\"><strong>"));
-		output.append(event->getLevel()->toString());
+		Transform::appendEscapingTags(output, event->getLevel()->toString());
 		output.append(LOG4CXX_STR("</strong></font>"));
 	}
 	else
 	{
-		output.append(event->getLevel()->toString());
+		Transform::appendEscapingTags(output, event->getLevel()->toString());
 	}
 
 	output.append(LOG4CXX_STR("</td>"));
 	output.append(LOG4CXX_EOL);
 
 	output.append(LOG4CXX_STR("<td title=\""));
-	output.append(event->getLoggerName());
+	Transform::appendEscapingTags(output, event->getLoggerName());
 	output.append(LOG4CXX_STR(" logger\">"));
 	Transform::appendEscapingTags(output, event->getLoggerName());
 	output.append(LOG4CXX_STR("</td>"));
diff --git a/src/test/cpp/xml/xmllayouttest.cpp b/src/test/cpp/xml/xmllayouttest.cpp
index 78f1c1183..710e9fca4 100644
--- a/src/test/cpp/xml/xmllayouttest.cpp
+++ b/src/test/cpp/xml/xmllayouttest.cpp
@@ -18,6 +18,7 @@
 #include "../logunit.h"
 #include <log4cxx/logger.h>
 #include <log4cxx/xml/xmllayout.h>
+#include <log4cxx/htmllayout.h>
 #include <log4cxx/fileappender.h>
 #include <log4cxx/mdc.h>
 
@@ -37,6 +38,7 @@
 #include "../xml/xlevel.h"
 #include <log4cxx/helpers/bytebuffer.h>
 #include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/loglog.h>
 
 
 using namespace log4cxx;
@@ -67,6 +69,7 @@ LOGUNIT_CLASS(XMLLayoutTest)
 	LOGUNIT_TEST(testActivateOptions);
 	LOGUNIT_TEST(testProblemCharacters);
 	LOGUNIT_TEST(testNDCWithCDATA);
+	LOGUNIT_TEST(testHTMLLayout);
 	LOGUNIT_TEST_SUITE_END();
 
 
@@ -453,6 +456,52 @@ LOGUNIT_CLASS(XMLLayoutTest)
 		LOGUNIT_ASSERT_EQUAL(1, ndcCount);
 	}
 
+	/**
+	 * Tests problematic characters in multiple fields.
+	 * @throws Exception if parser can not be constructed or source is not a valid XML document.
+	 */
+	void testHTMLLayout()
+	{
+		LogString problemName = LOG4CXX_STR("com.example.bar<>&\"'");
+		auto level = std::make_shared<XLevel>(6000, problemName, 7);
+		NDC context(problemName);
+		auto event = std::make_shared<LoggingEvent>(problemName, level, problemName, LOG4CXX_LOCATION);
+
+		HTMLLayout layout;
+		Pool p;
+		LogString html(LOG4CXX_STR("<body>"));
+		layout.format(html, event, p);
+		html += LOG4CXX_STR("</body>");
+
+		LogLog::debug(html);
+		char backing[3000];
+		ByteBuffer buf(backing, sizeof(backing));
+		CharsetEncoderPtr encoder(CharsetEncoder::getUTF8Encoder());
+		LogString::const_iterator iter{ html.begin() };
+		encoder->encode(html, iter, buf);
+		LOGUNIT_ASSERT(iter == html.end());
+		buf.flip();
+		auto parser = apr_xml_parser_create(p.getAPRPool());
+		LOGUNIT_ASSERT(parser != 0);
+		auto stat = apr_xml_parser_feed(parser, buf.data(), buf.remaining());
+		LOGUNIT_ASSERT(stat == APR_SUCCESS);
+		apr_xml_doc* doc = 0;
+		stat = apr_xml_parser_done(parser, &doc);
+		LOGUNIT_ASSERT(doc != 0);
+		auto parsedResult = doc->root;
+		LOGUNIT_ASSERT(parsedResult != 0);
+
+		int childElementCount = 0;
+		for ( auto node = parsedResult->first_child
+		    ; node != NULL
+		    ; node = node->next)
+		{
+			++childElementCount;
+			LOGUNIT_ASSERT_EQUAL(std::string("tr"), std::string(node->name));
+		}
+		LOGUNIT_ASSERT(1 < childElementCount);
+	}
+
 };