This is an automated email from the ASF dual-hosted git repository.
joerghoh pushed a commit to branch master
in repository
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-engine.git
The following commit(s) were added to refs/heads/master by this push:
new 68b028f SLING-13360 all log directives should handle CR/LF escaping
(#91)
68b028f is described below
commit 68b028ffe29ad8dc56a1792a3427915a8614aa76
Author: Jörg Hoh <[email protected]>
AuthorDate: Wed Sep 23 19:17:07 2026 +0200
SLING-13360 all log directives should handle CR/LF escaping (#91)
---
.../sling/engine/impl/log/CustomLogFormat.java | 11 ++--
.../sling/engine/impl/log/CustomLogFormatTest.java | 60 ++++++++++++++++++++++
2 files changed, 67 insertions(+), 4 deletions(-)
diff --git
a/src/main/java/org/apache/sling/engine/impl/log/CustomLogFormat.java
b/src/main/java/org/apache/sling/engine/impl/log/CustomLogFormat.java
index 8d353b5..e67b119 100644
--- a/src/main/java/org/apache/sling/engine/impl/log/CustomLogFormat.java
+++ b/src/main/java/org/apache/sling/engine/impl/log/CustomLogFormat.java
@@ -547,7 +547,7 @@ class CustomLogFormat {
}
protected String getValue(RequestLoggerRequest request) {
- return Thread.currentThread().getName();
+ return escape(Thread.currentThread().getName());
}
protected String getValue(RequestLoggerResponse response) {
@@ -561,7 +561,7 @@ class CustomLogFormat {
}
protected String getValue(RequestLoggerRequest request) {
- return request.getParameter(this.getParParam());
+ return escape(request.getParameter(this.getParParam()));
}
protected String getValue(RequestLoggerResponse response) {
@@ -705,7 +705,7 @@ class CustomLogFormat {
}
protected String getValue(RequestLoggerRequest request) {
- return request.getRemoteHost();
+ return escape(request.getRemoteHost());
}
protected String getValue(RequestLoggerResponse response) {
@@ -763,7 +763,10 @@ class CustomLogFormat {
protected String getValue(RequestLoggerRequest request) {
final Object resourcePath =
request.getAttribute(RequestData.REQUEST_RESOURCE_PATH_ATTR);
if (resourcePath instanceof String) {
- return (String) resourcePath;
+ // the resolved resource path is derived from the decoded
request
+ // path and may contain control characters (e.g. for
non-existing
+ // resources), so it must be escaped like other request data
+ return escape((String) resourcePath);
}
return null;
}
diff --git
a/src/test/java/org/apache/sling/engine/impl/log/CustomLogFormatTest.java
b/src/test/java/org/apache/sling/engine/impl/log/CustomLogFormatTest.java
index 1553e88..404e9cf 100644
--- a/src/test/java/org/apache/sling/engine/impl/log/CustomLogFormatTest.java
+++ b/src/test/java/org/apache/sling/engine/impl/log/CustomLogFormatTest.java
@@ -19,6 +19,8 @@
package org.apache.sling.engine.impl.log;
import junit.framework.TestCase;
+import org.apache.sling.engine.impl.request.RequestData;
+import org.mockito.Mockito;
/**
* The <code>CustomLogFormatTest</code> class tests the
@@ -69,4 +71,62 @@ public class CustomLogFormatTest extends TestCase {
"This is a special character \\u1234",
CustomLogFormat.HeaderParameter.escape("This is a special
character \u1234"));
}
+
+ public void testRequestParameterValueEscaped() {
+ final RequestLoggerRequest request =
Mockito.mock(RequestLoggerRequest.class);
+ Mockito.when(request.getParameter("ref"))
+ .thenReturn("x\r\n192.168.1.1 - admin \"POST /system/console
HTTP/1.1\" 200");
+
+ final CustomLogFormat.ParamParameter param = new
CustomLogFormat.ParamParameter("ref");
+ final String value = param.getValue(request);
+
+ // no raw CR/LF may end up in the log line
+ assertFalse(value.contains("\r"));
+ assertFalse(value.contains("\n"));
+ assertEquals("x\\r\\n192.168.1.1 - admin \\\"POST /system/console
HTTP/1.1\\\" 200", value);
+ }
+
+ public void testContentPathEscaped() {
+ final RequestLoggerRequest request =
Mockito.mock(RequestLoggerRequest.class);
+
Mockito.when(request.getAttribute(RequestData.REQUEST_RESOURCE_PATH_ATTR))
+ .thenReturn("/content/foo\r\nFORGED LINE");
+
+ final CustomLogFormat.ContentPathParameter param = new
CustomLogFormat.ContentPathParameter();
+ final String value = param.getValue(request);
+
+ assertFalse(value.contains("\r"));
+ assertFalse(value.contains("\n"));
+ assertEquals("/content/foo\\r\\nFORGED LINE", value);
+ }
+
+ public void testRemoteHostEscaped() {
+ final RequestLoggerRequest request =
Mockito.mock(RequestLoggerRequest.class);
+
Mockito.when(request.getRemoteHost()).thenReturn("evil\nhost.example.com");
+
+ final CustomLogFormat.RemoteHostParameter param = new
CustomLogFormat.RemoteHostParameter();
+ final String value = param.getValue(request);
+
+ assertFalse(value.contains("\n"));
+ assertEquals("evil\\nhost.example.com", value);
+ }
+
+ public void testThreadNameEscaped() {
+ // %P (ThreadParameter) does not read from the request but from the
+ // name of the thread handling it, and the threadname can contain the
+ // requested path
+ final Thread currentThread = Thread.currentThread();
+ final String originalName = currentThread.getName();
+ currentThread.setName("/content/\r\nfoo");
+ try {
+ final RequestLoggerRequest request =
Mockito.mock(RequestLoggerRequest.class);
+ final CustomLogFormat.ThreadParameter param = new
CustomLogFormat.ThreadParameter(null);
+ final String value = param.getValue(request);
+
+ assertFalse(value.contains("\r"));
+ assertFalse(value.contains("\n"));
+ assertEquals("/content/\\r\\nfoo", value);
+ } finally {
+ currentThread.setName(originalName);
+ }
+ }
}