From ffc40d87d40c7534373372151b53d2d60d01b63b Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Tue, 28 Feb 2017 19:41:36 +0100 Subject: [PATCH] Escape characters like httpd does. --- .../catalina/valves/AbstractAccessLogValve.java | 125 +++++++++++++-------- .../valves/TestAbstractAccessLogValveWrap.java | 62 ++++++++++ 2 files changed, 138 insertions(+), 49 deletions(-) create mode 100644 test/org/apache/catalina/valves/TestAbstractAccessLogValveWrap.java diff --git a/java/org/apache/catalina/valves/AbstractAccessLogValve.java b/java/org/apache/catalina/valves/AbstractAccessLogValve.java index 3d83930..432d2f4 100644 --- a/java/org/apache/catalina/valves/AbstractAccessLogValve.java +++ b/java/org/apache/catalina/valves/AbstractAccessLogValve.java @@ -755,7 +755,7 @@ public abstract class AbstractAccessLogValve extends ValveBase implements Access Response response, long time) { RequestInfo info = request.getCoyoteRequest().getRequestProcessor(); if(info != null) { - buf.append(info.getWorkerThreadName()); + buf.append(wrap(info.getWorkerThreadName())); } else { buf.append("-"); } @@ -777,7 +777,7 @@ public abstract class AbstractAccessLogValve extends ValveBase implements Access ExceptionUtils.handleThrowable(e); init = "127.0.0.1"; } - LOCAL_ADDR_VALUE = init; + LOCAL_ADDR_VALUE = wrap(init); } @Override @@ -797,12 +797,12 @@ public abstract class AbstractAccessLogValve extends ValveBase implements Access if (requestAttributesEnabled) { Object addr = request.getAttribute(REMOTE_ADDR_ATTRIBUTE); if (addr == null) { - buf.append(request.getRemoteAddr()); + buf.append(wrap(request.getRemoteAddr())); } else { - buf.append(addr.toString()); + buf.append(wrap(addr.toString())); } } else { - buf.append(request.getRemoteAddr()); + buf.append(wrap(request.getRemoteAddr())); } } } @@ -827,7 +827,7 @@ public abstract class AbstractAccessLogValve extends ValveBase implements Access if (value == null || value.length() == 0) { value = "-"; } - buf.append(value); + buf.append(wrap(value)); } } @@ -852,12 +852,12 @@ public abstract class AbstractAccessLogValve extends ValveBase implements Access if (requestAttributesEnabled) { Object proto = request.getAttribute(PROTOCOL_ATTRIBUTE); if (proto == null) { - buf.append(request.getProtocol()); + buf.append(wrap(request.getProtocol())); } else { - buf.append(proto.toString()); + buf.append(wrap(proto.toString())); } } else { - buf.append(request.getProtocol()); + buf.append(wrap(request.getProtocol())); } } } @@ -870,12 +870,7 @@ public abstract class AbstractAccessLogValve extends ValveBase implements Access public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { if (request != null) { - String value = request.getRemoteUser(); - if (value != null) { - buf.append(value); - } else { - buf.append('-'); - } + buf.append(wrap(request.getRemoteUser())); } else { buf.append('-'); } @@ -1049,7 +1044,7 @@ public abstract class AbstractAccessLogValve extends ValveBase implements Access temp = temp.replace(trippleMsecPattern, trippleMsec); temp = temp.replace(msecPattern, Long.toString(frac)); } - buf.append(temp); + buf.append(wrap(temp)); break; } } @@ -1068,15 +1063,15 @@ public abstract class AbstractAccessLogValve extends ValveBase implements Access // No method means no request line buf.append('-'); } else { - buf.append(request.getMethod()); + buf.append(wrap(request.getMethod())); buf.append(' '); - buf.append(request.getRequestURI()); + buf.append(wrap(request.getRequestURI())); if (request.getQueryString() != null) { buf.append('?'); - buf.append(request.getQueryString()); + buf.append(wrap(request.getQueryString())); } buf.append(' '); - buf.append(request.getProtocol()); + buf.append(wrap(request.getProtocol())); } } else { buf.append('-'); @@ -1147,7 +1142,7 @@ public abstract class AbstractAccessLogValve extends ValveBase implements Access if (port == null) { buf.append(Integer.toString(request.getServerPort())); } else { - buf.append(port.toString()); + buf.append(wrap(port.toString())); } } else { if (portType == PortType.LOCAL) { @@ -1208,7 +1203,7 @@ public abstract class AbstractAccessLogValve extends ValveBase implements Access public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { if (request != null) { - buf.append(request.getMethod()); + buf.append(wrap(request.getMethod())); } } } @@ -1274,7 +1269,7 @@ public abstract class AbstractAccessLogValve extends ValveBase implements Access } if (query != null) { buf.append('?'); - buf.append(query); + buf.append(wrap(query)); } } } @@ -1293,7 +1288,7 @@ public abstract class AbstractAccessLogValve extends ValveBase implements Access if (session == null) { buf.append('-'); } else { - buf.append(session.getIdInternal()); + buf.append(wrap(session.getIdInternal())); } } } @@ -1307,7 +1302,7 @@ public abstract class AbstractAccessLogValve extends ValveBase implements Access public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { if (request != null) { - buf.append(request.getRequestURI()); + buf.append(wrap(request.getRequestURI())); } else { buf.append('-'); } @@ -1321,7 +1316,7 @@ public abstract class AbstractAccessLogValve extends ValveBase implements Access @Override public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { - buf.append(request.getServerName()); + buf.append(wrap(request.getServerName())); } } @@ -1357,9 +1352,9 @@ public abstract class AbstractAccessLogValve extends ValveBase implements Access Response response, long time) { Enumeration iter = request.getHeaders(header); if (iter.hasMoreElements()) { - buf.append(iter.nextElement()); + buf.append(wrap(iter.nextElement())); while (iter.hasMoreElements()) { - buf.append(',').append(iter.nextElement()); + buf.append(',').append(wrap(iter.nextElement())); } return; } @@ -1390,7 +1385,7 @@ public abstract class AbstractAccessLogValve extends ValveBase implements Access } } } - buf.append(value); + buf.append(wrap(value)); } } @@ -1410,9 +1405,9 @@ public abstract class AbstractAccessLogValve extends ValveBase implements Access if (null != response) { Iterator iter = response.getHeaders(header).iterator(); if (iter.hasNext()) { - buf.append(iter.next()); + buf.append(wrap(iter.next())); while (iter.hasNext()) { - buf.append(',').append(iter.next()); + buf.append(',').append(wrap(iter.next())); } return; } @@ -1440,15 +1435,7 @@ public abstract class AbstractAccessLogValve extends ValveBase implements Access } else { value = "??"; } - if (value != null) { - if (value instanceof String) { - buf.append((String) value); - } else { - buf.append(value.toString()); - } - } else { - buf.append('-'); - } + buf.append(wrap(value)); } } @@ -1474,15 +1461,7 @@ public abstract class AbstractAccessLogValve extends ValveBase implements Access } else { value = "??"; } - if (value != null) { - if (value instanceof String) { - buf.append((String) value); - } else { - buf.append(value.toString()); - } - } else { - buf.append('-'); - } + buf.append(wrap(value)); } } @@ -1617,4 +1596,52 @@ public abstract class AbstractAccessLogValve extends ValveBase implements Access return new StringElement("???" + pattern + "???"); } } + + static String wrap(Object value) { + if (value == null || "-".equals(value)) { + return "-"; + } + String svalue; + try { + svalue = value.toString(); + } catch (Throwable e) { + ExceptionUtils.handleThrowable(e); + return "-"; + } + StringBuilder buffer = new StringBuilder(svalue.length()); + for (byte b: svalue.getBytes()) { + switch (b) { + case '"': + buffer.append("\\\""); + break; + case '\\': + buffer.append("\\\\"); + break; + case '\t': + buffer.append("\\t"); + break; + case '\n': + buffer.append("\\n"); + break; + case '\r': + buffer.append("\\r"); + break; + case '\b': + buffer.append("\\b"); + break; + case '\f': + buffer.append("\\f"); + break; + default: + if (b >= 32 && b < 127) { + buffer.append((char)b); + } else { + buffer.append(String.format("\\x%02x", Byte.valueOf(b))); + } + break; + } + } + return buffer.toString(); + + } } diff --git a/test/org/apache/catalina/valves/TestAbstractAccessLogValveWrap.java b/test/org/apache/catalina/valves/TestAbstractAccessLogValveWrap.java new file mode 100644 index 0000000..db1e84b --- /dev/null +++ b/test/org/apache/catalina/valves/TestAbstractAccessLogValveWrap.java @@ -0,0 +1,62 @@ +/* + * 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.catalina.valves; + +import static org.junit.Assert.*; + +import java.util.Arrays; +import java.util.Collection; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class TestAbstractAccessLogValveWrap { + + private static final class ThrowingObject { + @Override + public String toString() { + throw new RuntimeException(); + } + } + + private final Object input; + private final String expected; + + public TestAbstractAccessLogValveWrap(Object input, String expected) { + this.input = input; + this.expected = expected; + } + + @Test + public void testWrap() { + assertEquals(expected, AbstractAccessLogValve.wrap(input)); + } + + @Parameters + public static Collection parameters() { + ThrowingObject t = new ThrowingObject(); + return Arrays.asList(new Object[][] { { null, "-" }, { "-", "-" }, + { " ", " " }, { t, "-" }, { "foo", "foo" }, + { "\b\t\r\n\\\"", "\\b\\t\\r\\n\\\\\\\"" }, + { new String(new byte[] { 127 }), "\\x7f" }, + { "'", "'" } }); + } + +} -- 2.7.4