File tomcat-8.0.53-CVE-2025-55754.patch of Package tomcat.41603
Index: apache-tomcat-8.0.53-src/java/org/apache/juli/LogUtil.java
===================================================================
--- /dev/null
+++ apache-tomcat-8.0.53-src/java/org/apache/juli/LogUtil.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.juli;
+
+public class LogUtil {
+
+ private LogUtil() {
+ // Utility class. Hide default constructor
+ }
+
+
+ /**
+ * Escape a string so it can be displayed in a readable format. Characters that may not be printable in some/all of
+ * the contexts in which log messages will be viewed will be escaped using Java \\uNNNN escaping.
+ * <p>
+ * All control characters are escaped apart from horizontal tab (\\u0009), new line (\\u000a) and carriage return
+ * (\\u000d).
+ *
+ * @param input The string to escape
+ *
+ * @return The escaped form of the input string
+ */
+ @SuppressWarnings("null") // sb is not null when used
+ public static String escape(final String input) {
+ final int len = input.length();
+ int i = 0;
+ int lastControl = -1;
+ StringBuilder sb = null;
+ while (i < len) {
+ char c = input.charAt(i);
+ if (Character.getType(c) == Character.CONTROL) {
+ if (!(c == '\t' || c == '\n' || c == '\r')) {
+ if (lastControl == -1) {
+ sb = new StringBuilder(len + 20);
+ }
+ sb.append(input.substring(lastControl + 1, i));
+ sb.append(String.format("\\u%1$04x", Integer.valueOf(c)));
+ lastControl = i;
+ }
+ }
+ i++;
+ }
+ if (lastControl == -1) {
+ return input;
+ } else {
+ sb.append(input.substring(lastControl + 1, len));
+ return sb.toString();
+ }
+ }
+}
Index: apache-tomcat-8.0.53-src/test/org/apache/juli/TestLogUtil.java
===================================================================
--- /dev/null
+++ apache-tomcat-8.0.53-src/test/org/apache/juli/TestLogUtil.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.juli;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestLogUtil {
+
+ @Test
+ public void testEscapeForLoggingEmptyString() {
+ doTestEscapeForLogging("");
+ }
+
+
+ @Test
+ public void testEscapeForLoggingNone() {
+ doTestEscapeForLogging("No escaping");
+ }
+
+
+ @Test
+ public void testEscapeForLoggingControlStart() {
+ doTestEscapeForLogging("\u0006Text", "\\u0006Text");
+ }
+
+
+ @Test
+ public void testEscapeForLoggingControlMiddle() {
+ doTestEscapeForLogging("Text\u0006Text", "Text\\u0006Text");
+ }
+
+
+ @Test
+ public void testEscapeForLoggingControlEnd() {
+ doTestEscapeForLogging("Text\u0006", "Text\\u0006");
+ }
+
+
+ @Test
+ public void testEscapeForLoggingControlOnly() {
+ doTestEscapeForLogging("\u0006", "\\u0006");
+ }
+
+
+ @Test
+ public void testEscapeForLoggingControlsStart() {
+ doTestEscapeForLogging("\u0006\u0007Text", "\\u0006\\u0007Text");
+ }
+
+
+ @Test
+ public void testEscapeForLoggingControlsMiddle() {
+ doTestEscapeForLogging("Text\u0006\u0007Text", "Text\\u0006\\u0007Text");
+ }
+
+
+ @Test
+ public void testEscapeForLoggingControlsEnd() {
+ doTestEscapeForLogging("Text\u0006\u0007", "Text\\u0006\\u0007");
+ }
+
+
+ @Test
+ public void testEscapeForLoggingControlsOnly() {
+ doTestEscapeForLogging("\u0006\u0007", "\\u0006\\u0007");
+ }
+
+
+ private void doTestEscapeForLogging(String input) {
+ doTestEscapeForLogging(input, input);
+ }
+
+
+ private void doTestEscapeForLogging(String input, String expected) {
+ String result = LogUtil.escape(input);
+ Assert.assertEquals(expected, result);
+ }
+}
\ No newline at end of file
Index: apache-tomcat-8.0.53-src/java/org/apache/juli/JdkLoggerFormatter.java
===================================================================
--- apache-tomcat-8.0.53-src.orig/java/org/apache/juli/JdkLoggerFormatter.java
+++ apache-tomcat-8.0.53-src/java/org/apache/juli/JdkLoggerFormatter.java
@@ -87,7 +87,7 @@ public class JdkLoggerFormatter extends
for( int i=0; i<8-buf.length(); i++ ) { buf.append(" "); }
// Append the message
- buf.append(message);
+ buf.append(LogUtil.escape(message));
// Append stack trace if not null
if(t != null) {
@@ -97,7 +97,7 @@ public class JdkLoggerFormatter extends
java.io.PrintWriter pw= new java.io.PrintWriter(sw);
t.printStackTrace(pw);
pw.close();
- buf.append(sw.toString());
+ buf.append(LogUtil.escape(sw.toString()));
}
buf.append(System.lineSeparator());
Index: apache-tomcat-8.0.53-src/java/org/apache/juli/OneLineFormatter.java
===================================================================
--- apache-tomcat-8.0.53-src.orig/java/org/apache/juli/OneLineFormatter.java
+++ apache-tomcat-8.0.53-src/java/org/apache/juli/OneLineFormatter.java
@@ -122,7 +122,7 @@ public class OneLineFormatter extends Fo
// Message
sb.append(' ');
- sb.append(formatMessage(record));
+ sb.append(LogUtil.escape(formatMessage(record)));
// Stack trace
if (record.getThrown() != null) {
@@ -131,7 +131,7 @@ public class OneLineFormatter extends Fo
PrintWriter pw = new PrintWriter(sw);
record.getThrown().printStackTrace(pw);
pw.close();
- sb.append(sw.getBuffer());
+ sb.append(LogUtil.escape(sw.toString()));
}
// New line for next record
Index: apache-tomcat-8.0.53-src/java/org/apache/juli/VerbatimFormatter.java
===================================================================
--- apache-tomcat-8.0.53-src.orig/java/org/apache/juli/VerbatimFormatter.java
+++ apache-tomcat-8.0.53-src/java/org/apache/juli/VerbatimFormatter.java
@@ -21,11 +21,9 @@ import java.util.logging.Formatter;
import java.util.logging.LogRecord;
/**
- * Outputs the just the log message with no additional elements. Stack traces
- * are not logged. Log messages are separated by
- * <code>System.lineSeparator()</code>. This is intended for use
- * by access logs and the like that need complete control over the output
- * format.
+ * Outputs just the log message with no additional elements and no escaping. Stack traces are not logged. Log messages
+ * are separated by <code>System.lineSeparator()</code>. This is intended for use by access logs and the like that need
+ * complete control over the output format.
*/
public class VerbatimFormatter extends Formatter {