Issue #1475 - SIOOBE in ContextHandler startup

+ Fixed ContextHandler logname creation to be more resilient to
  bad characters that are unsuitable for a log name
+ Corrected AbstractLogger condensePackageString() to be
  more resilient to bad characters and classname formatting
This commit is contained in:
Joakim Erdfelt 2017-04-14 12:04:18 -07:00
parent 509f59c32d
commit ccfe579a55
5 changed files with 102 additions and 19 deletions

View File

@ -753,20 +753,12 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
if (_contextPath == null)
throw new IllegalStateException("Null contextPath");
if (_logger==null)
if (_logger == null)
{
String log_name = getDisplayName();
if (log_name == null || log_name.isEmpty())
{
log_name = getContextPath();
if (log_name!=null || log_name.startsWith("/"))
log_name = log_name.substring(1);
if (log_name==null || log_name.isEmpty())
log_name = Integer.toHexString(hashCode());
}
_logger = Log.getLogger("org.eclipse.jetty.ContextHandler."+log_name);
_logger = Log.getLogger(ContextHandler.class.getName() + getLogName());
}
ClassLoader old_classloader = null;
Thread current_thread = null;
Context old_context = null;
@ -806,6 +798,40 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
current_thread.setContextClassLoader(old_classloader);
}
}
private String getLogName()
{
// Use display name first
String log_name = getDisplayName();
if (StringUtil.isBlank(log_name))
{
// try context path
log_name = getContextPath();
if (log_name != null)
{
// Strip prefix slash
if (log_name.startsWith("/"))
{
log_name = log_name.substring(1);
}
}
if (StringUtil.isNotBlank(log_name))
{
// try hex of hashcode
log_name = Integer.toHexString(hashCode());
}
}
if (StringUtil.isBlank(log_name))
{
// still blank?
return "";
}
// Replace bad characters.
return '.' + log_name.replaceAll("\\W", "_");
}
/* ------------------------------------------------------------ */
/**

View File

@ -18,6 +18,9 @@
package org.eclipse.jetty.server.handler;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
@ -448,10 +451,28 @@ public class ContextHandlerTest
}
@Test
public void testIsShutdown() {
public void testIsShutdown()
{
ContextHandler handler = new ContextHandler();
Assert.assertEquals(false, handler.isShutdown());
}
@Test
public void testLogName() throws Exception
{
ContextHandler handler = new ContextHandler();
handler.setServer(new Server());
handler.setDisplayName(".");
try
{
handler.start();
assertThat("handler.get", handler.getLogger().getName(), is(ContextHandler.class.getName()));
}
finally
{
handler.stop();
}
}
private void checkResourcePathsForExampleWebApp(String root) throws IOException
{

View File

@ -200,11 +200,24 @@ public abstract class AbstractLogger implements Logger
*/
protected static String condensePackageString(String classname)
{
String parts[] = classname.split("\\.");
if(classname == null || classname.isEmpty())
{
return "";
}
// strip non-allowed character
String allowed = classname.replaceAll("[^\\w.]", "");
int len = allowed.length();
// find end of classname (strip empty sections. eg: "org.Foo.")
while(allowed.charAt(--len) == '.');
String parts[] = allowed.substring(0,len+1).split("\\.");
StringBuilder dense = new StringBuilder();
for (int i = 0; i < (parts.length - 1); i++)
{
dense.append(parts[i].charAt(0));
String part = parts[i].trim();
if(!part.isEmpty())
{
dense.append(part.charAt(0));
}
}
if (dense.length() > 0)
{

View File

@ -21,7 +21,6 @@ package org.eclipse.jetty.util.log;
import java.io.PrintStream;
import java.security.AccessControlException;
import java.util.Properties;
import java.util.logging.Level;
import org.eclipse.jetty.util.DateCache;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
@ -143,7 +142,7 @@ public class StdErrLog extends AbstractLogger
// The full log name, as provided by the system.
private final String _name;
// The abbreviated log name (used by default, unless _long is specified)
private final String _abbrevname;
protected final String _abbrevname;
private boolean _hideStacks = false;

View File

@ -19,6 +19,9 @@
package org.eclipse.jetty.util.log;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import java.util.HashMap;
import java.util.Map;
@ -54,8 +57,8 @@ public class LogTest
Logger log = Log.getLogger(LogTest.class);
log.info("Test default logging");
}
// @Test
@Test
public void testNamedLogNamed_StdErrLog()
{
Log.setLog(new StdErrLog());
@ -90,4 +93,25 @@ public class LogTest
Logger lc = Log.getLogger(clazz);
Assert.assertEquals("Named logging (impl=" + Log.getLog().getClass().getName() + ")",lc.getName(),clazz.getName());
}
@Test
public void testCondensePackage()
{
String cases[][] = new String[][]{
{null, ""},
{"org.eclipse.Foo.\u0000", "oe.Foo"},
{".foo", "foo"},
{".bar.Foo", "b.Foo"},
{"org...bar..Foo", "ob.Foo"}
};
StdErrLog log = new StdErrLog();
for (int i = 0; i < cases.length; i++)
{
// System.err.printf("newLogger(%s)%n", cases[i][0]);
StdErrLog logger = (StdErrLog) log.newLogger(cases[i][0]);
assertThat("log[" + cases[i][0] + "] condenses to name", logger._abbrevname, is(cases[i][1]));
}
}
}