From 921e21bf9e1ebca11062c3ec99dad9ed41882221 Mon Sep 17 00:00:00 2001 From: Thomas Neidhart Date: Fri, 27 Jun 2014 11:10:16 +0000 Subject: [PATCH] [LOGGING-37] Add testcase when calling Thread.getCurrentThread().getContextClassLoader() results in a SecurityException. git-svn-id: https://svn.apache.org/repos/asf/commons/proper/logging/trunk@1606029 13f79535-47bb-0310-9956-ffa450edef68 --- .../commons/logging/security/DummyClass.java | 21 +++++++ .../security/SecurityForbiddenTestCase.java | 57 +++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 src/test/java/org/apache/commons/logging/security/DummyClass.java diff --git a/src/test/java/org/apache/commons/logging/security/DummyClass.java b/src/test/java/org/apache/commons/logging/security/DummyClass.java new file mode 100644 index 0000000..ece0e7c --- /dev/null +++ b/src/test/java/org/apache/commons/logging/security/DummyClass.java @@ -0,0 +1,21 @@ +/* + * 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.commons.logging.security; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class DummyClass { + + public DummyClass() { + Log log = LogFactory.getLog(DummyClass.class); + log.info("Some log message"); + } +} diff --git a/src/test/java/org/apache/commons/logging/security/SecurityForbiddenTestCase.java b/src/test/java/org/apache/commons/logging/security/SecurityForbiddenTestCase.java index b3f07eb..08c5af9 100644 --- a/src/test/java/org/apache/commons/logging/security/SecurityForbiddenTestCase.java +++ b/src/test/java/org/apache/commons/logging/security/SecurityForbiddenTestCase.java @@ -47,6 +47,7 @@ import org.apache.commons.logging.PathableTestSuite; public class SecurityForbiddenTestCase extends TestCase { private SecurityManager oldSecMgr; + private ClassLoader otherClassLoader; // Dummy special hashtable, so we can tell JCL to use this instead of // the standard one. @@ -75,6 +76,12 @@ public class SecurityForbiddenTestCase extends TestCase public void setUp() { // save security manager so it can be restored in tearDown oldSecMgr = System.getSecurityManager(); + + PathableClassLoader classLoader = new PathableClassLoader(null); + classLoader.addLogicalLib("commons-logging"); + classLoader.addLogicalLib("testclasses"); + + otherClassLoader = classLoader; } public void tearDown() { @@ -131,4 +138,54 @@ public class SecurityForbiddenTestCase extends TestCase fail("Unexpected exception:" + t.getMessage() + ":" + sw.toString()); } } + + /** + * Test what happens when JCL is run with absolutely no security + * privileges at all and a class loaded with a different classloader + * than the context classloader of the current thread tries to log something. + */ + public void testContextClassLoader() { + System.setProperty( + LogFactory.HASHTABLE_IMPLEMENTATION_PROPERTY, + CustomHashtable.class.getName()); + MockSecurityManager mySecurityManager = new MockSecurityManager(); + + System.setSecurityManager(mySecurityManager); + + try { + // load a dummy class with another classloader + // to force a SecurityException when the LogFactory calls + // Thread.getCurrentThread().getContextClassLoader() + loadClass("org.apache.commons.logging.security.DummyClass", otherClassLoader); + + System.setSecurityManager(oldSecMgr); + assertEquals(0, mySecurityManager.getUntrustedCodeCount()); + } catch(Throwable t) { + // Restore original security manager so output can be generated; the + // PrintWriter constructor tries to read the line.separator + // system property. + System.setSecurityManager(oldSecMgr); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + t.printStackTrace(pw); + fail("Unexpected exception:" + t.getMessage() + ":" + sw.toString()); + } + } + + /** + * Loads a class with the given classloader. + */ + private Object loadClass(String name, ClassLoader classLoader) { + try { + Class clazz = classLoader.loadClass(name); + Object obj = clazz.newInstance(); + return obj; + } catch ( Exception e ) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + e.printStackTrace(pw); + fail("Unexpected exception:" + e.getMessage() + ":" + sw.toString()); + } + return null; + } }