undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
384
test/jdk/java/lang/instrument/RedefineModuleTest.java
Normal file
384
test/jdk/java/lang/instrument/RedefineModuleTest.java
Normal file
|
|
@ -0,0 +1,384 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Basic test for redefineModule
|
||||
*
|
||||
* @build java.base/java.lang.TestProvider
|
||||
* java.base/jdk.internal.test.TestProviderImpl1
|
||||
* java.base/jdk.internal.test.TestProviderImpl2
|
||||
* @run shell MakeJAR3.sh RedefineModuleAgent
|
||||
* @run testng/othervm -javaagent:RedefineModuleAgent.jar RedefineModuleTest
|
||||
*/
|
||||
|
||||
import java.lang.TestProvider;
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import java.net.URLStreamHandler;
|
||||
import java.net.spi.URLStreamHandlerProvider;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
@Test
|
||||
public class RedefineModuleTest {
|
||||
|
||||
static void redefineModule(Module module,
|
||||
Set<Module> extraReads,
|
||||
Map<String, Set<Module>> extraExports,
|
||||
Map<String, Set<Module>> extraOpens,
|
||||
Set<Class<?>> extraUses,
|
||||
Map<Class<?>, List<Class<?>>> extraProvides) {
|
||||
RedefineModuleAgent.redefineModule(module,
|
||||
extraReads,
|
||||
extraExports,
|
||||
extraOpens,
|
||||
extraUses,
|
||||
extraProvides);
|
||||
}
|
||||
|
||||
static boolean isModifiableModule(Module module) {
|
||||
return RedefineModuleAgent.isModifiableModule(module);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Use redefineModule to update java.base to read java.instrument
|
||||
*/
|
||||
public void testAddReads() {
|
||||
Module baseModule = Object.class.getModule();
|
||||
Module instrumentModule = Instrumentation.class.getModule();
|
||||
|
||||
// pre-conditions
|
||||
assertFalse(baseModule.canRead(instrumentModule));
|
||||
|
||||
// update java.base to read java.instrument
|
||||
Set<Module> extraReads = Set.of(instrumentModule);
|
||||
redefineModule(baseModule, extraReads, Map.of(), Map.of(), Set.of(), Map.of());
|
||||
assertTrue(baseModule.canRead(instrumentModule));
|
||||
}
|
||||
|
||||
/**
|
||||
* Use redefineModule to update java.base to export jdk.internal.misc
|
||||
*/
|
||||
public void testAddExports() {
|
||||
Module baseModule = Object.class.getModule();
|
||||
Module thisModule = this.getClass().getClassLoader().getUnnamedModule();
|
||||
String pkg = "jdk.internal.misc";
|
||||
|
||||
// pre-conditions
|
||||
assertFalse(baseModule.isExported(pkg));
|
||||
assertFalse(baseModule.isExported(pkg, thisModule));
|
||||
|
||||
// update java.base to export jdk.internal.misc to an unnamed module
|
||||
Map<String, Set<Module>> extraExports = Map.of(pkg, Set.of(thisModule));
|
||||
redefineModule(baseModule, Set.of(), extraExports, Map.of(), Set.of(), Map.of());
|
||||
assertFalse(baseModule.isExported(pkg));
|
||||
assertTrue(baseModule.isExported(pkg, thisModule));
|
||||
assertFalse(baseModule.isOpen(pkg));
|
||||
assertFalse(baseModule.isOpen(pkg, thisModule));
|
||||
}
|
||||
|
||||
/**
|
||||
* Use redefineModule to update java.base to open jdk.internal.loader
|
||||
*/
|
||||
public void testAddOpens() {
|
||||
Module baseModule = Object.class.getModule();
|
||||
Module thisModule = this.getClass().getClassLoader().getUnnamedModule();
|
||||
String pkg = "jdk.internal.loader";
|
||||
|
||||
// pre-conditions
|
||||
assertFalse(baseModule.isOpen(pkg));
|
||||
assertFalse(baseModule.isOpen(pkg, thisModule));
|
||||
|
||||
// update java.base to open dk.internal.loader to an unnamed module
|
||||
Map<String, Set<Module>> extraExports = Map.of(pkg, Set.of(thisModule));
|
||||
redefineModule(baseModule, Set.of(), Map.of(), extraExports, Set.of(), Map.of());
|
||||
assertFalse(baseModule.isExported(pkg));
|
||||
assertTrue(baseModule.isExported(pkg, thisModule));
|
||||
assertFalse(baseModule.isOpen(pkg));
|
||||
assertTrue(baseModule.isOpen(pkg, thisModule));
|
||||
}
|
||||
|
||||
/**
|
||||
* Use redefineModule to update java.base to use TestProvider and
|
||||
* provide implementations of TestProvider.
|
||||
*/
|
||||
public void testAddUsesAndProvides() throws Exception {
|
||||
Module baseModule = Object.class.getModule();
|
||||
Class<TestProvider> service = TestProvider.class;
|
||||
|
||||
// pre-conditions
|
||||
assertFalse(baseModule.canUse(service));
|
||||
assertTrue(collect(ServiceLoader.load(service)).isEmpty());
|
||||
assertTrue(collect(ServiceLoader.load(ModuleLayer.boot(), service)).isEmpty());
|
||||
|
||||
// update java.base to use TestProvider
|
||||
redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(service), Map.of());
|
||||
assertTrue(baseModule.canUse(service));
|
||||
assertTrue(collect(ServiceLoader.load(service)).isEmpty());
|
||||
assertTrue(collect(ServiceLoader.load(ModuleLayer.boot(), service)).isEmpty());
|
||||
|
||||
// update java.base to provide an implementation of TestProvider
|
||||
Class<?> type1 = Class.forName("jdk.internal.test.TestProviderImpl1");
|
||||
Map<Class<?>, List<Class<?>>> extraProvides = Map.of(service, List.of(type1));
|
||||
redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides);
|
||||
|
||||
// invoke ServiceLoader from java.base to find providers
|
||||
Set<TestProvider> providers = collect(TestProvider.providers());
|
||||
assertTrue(providers.size() == 1);
|
||||
assertTrue(containsInstanceOf(providers, type1));
|
||||
|
||||
// use ServiceLoader to load implementations visible via TCCL
|
||||
providers = collect(ServiceLoader.load(service));
|
||||
assertTrue(collect(providers).size() == 1);
|
||||
assertTrue(containsInstanceOf(collect(providers), type1));
|
||||
|
||||
// use ServiceLoader to load implementations in the boot layer
|
||||
providers = collect(ServiceLoader.load(ModuleLayer.boot(), service));
|
||||
assertTrue(collect(providers).size() == 1);
|
||||
assertTrue(containsInstanceOf(collect(providers), type1));
|
||||
|
||||
// update java.base to provide a second implementation of TestProvider
|
||||
Class<?> type2 = Class.forName("jdk.internal.test.TestProviderImpl2");
|
||||
extraProvides = Map.of(service, List.of(type2));
|
||||
redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides);
|
||||
|
||||
// invoke ServiceLoader from java.base to find providers
|
||||
providers = collect(TestProvider.providers());
|
||||
assertTrue(providers.size() == 2);
|
||||
assertTrue(containsInstanceOf(providers, type1));
|
||||
assertTrue(containsInstanceOf(providers, type2));
|
||||
|
||||
// use ServiceLoader to load implementations visible via TCCL
|
||||
providers = collect(ServiceLoader.load(service));
|
||||
assertTrue(collect(providers).size() == 2);
|
||||
assertTrue(containsInstanceOf(providers, type1));
|
||||
assertTrue(containsInstanceOf(providers, type2));
|
||||
|
||||
// use ServiceLoader to load implementations in the boot layer
|
||||
providers = collect(ServiceLoader.load(ModuleLayer.boot(), service));
|
||||
assertTrue(collect(providers).size() == 2);
|
||||
assertTrue(containsInstanceOf(providers, type1));
|
||||
assertTrue(containsInstanceOf(providers, type2));
|
||||
}
|
||||
|
||||
private <S> Set<S> collect(Iterable<S> sl) {
|
||||
Set<S> providers = new HashSet<>();
|
||||
sl.forEach(providers::add);
|
||||
return providers;
|
||||
}
|
||||
|
||||
private boolean containsInstanceOf(Collection<?> c, Class<?> type) {
|
||||
for (Object o : c) {
|
||||
if (type.isInstance(o)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testExportPackageToEmptySet() {
|
||||
// attempt to update java.base to export jdk.internal.misc to nobody
|
||||
Module baseModule = Object.class.getModule();
|
||||
Map<String, Set<Module>> extraExports = Map.of("jdk.internal.misc", Set.of());
|
||||
redefineModule(baseModule, Set.of(), extraExports, Map.of(), Set.of(), Map.of());
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testOpenPackageToEmptySet() {
|
||||
// attempt to update java.base to open jdk.internal.misc to nobody
|
||||
Module baseModule = Object.class.getModule();
|
||||
Map<String, Set<Module>> extraOpens = Map.of("jdk.internal.misc", Set.of());
|
||||
redefineModule(baseModule, Set.of(), Map.of(), extraOpens, Set.of(), Map.of());
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testProvideServiceWithEmptyList() throws Exception {
|
||||
// update java.base to provide an empty list of TestProvider
|
||||
Module baseModule = Object.class.getModule();
|
||||
Class<?> service = TestProvider.class;
|
||||
Map<Class<?>, List<Class<?>>> extraProvides = Map.of(service, List.of());
|
||||
redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test redefineClass by attempting to update java.base to export a package
|
||||
* that it does not contain.
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testExportPackageNotInModule() {
|
||||
Module baseModule = Object.class.getModule();
|
||||
String pkg = "jdk.doesnotexist";
|
||||
|
||||
// attempt to update java.base to export jdk.doesnotexist
|
||||
Map<String, Set<Module>> extraExports = Map.of(pkg, Set.of());
|
||||
redefineModule(baseModule, Set.of(), extraExports, Map.of(), Set.of(), Map.of());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test redefineClass by attempting to update java.base to provide a service
|
||||
* where the service provider class is not in the module.
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testProvideServiceNotInModule() {
|
||||
Module baseModule = Object.class.getModule();
|
||||
class MyProvider extends URLStreamHandlerProvider {
|
||||
@Override
|
||||
public URLStreamHandler createURLStreamHandler(String protocol) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// attempt to update java.base to provide MyProvider
|
||||
Map<Class<?>, List<Class<?>>> extraProvides
|
||||
= Map.of(URLStreamHandlerProvider.class, List.of(MyProvider.class));
|
||||
redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test redefineClass by attempting to update java.base to provide a
|
||||
* service where the service provider class is not a sub-type.
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testProvideServiceNotSubtype() {
|
||||
Module baseModule = Object.class.getModule();
|
||||
|
||||
Class<?> service = TestProvider.class;
|
||||
Class<?> impl = FileSystems.getDefault().provider().getClass();
|
||||
|
||||
// attempt to update java.base to provide an implementation of TestProvider
|
||||
Map<Class<?>, List<Class<?>>> extraProvides = Map.of(service, List.of(impl));
|
||||
redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exercise IsModifiableModule
|
||||
*/
|
||||
@Test
|
||||
public void testIsModifiableModule() {
|
||||
ClassLoader pcl = ClassLoader.getPlatformClassLoader();
|
||||
ClassLoader scl = ClassLoader.getSystemClassLoader();
|
||||
assertTrue(isModifiableModule(pcl.getUnnamedModule()));
|
||||
assertTrue(isModifiableModule(scl.getUnnamedModule()));
|
||||
assertTrue(isModifiableModule(RedefineModuleTest.class.getModule()));
|
||||
assertTrue(isModifiableModule(Object.class.getModule()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test redefineClass with null
|
||||
*/
|
||||
public void testNulls() {
|
||||
Module baseModule = Object.class.getModule();
|
||||
|
||||
try {
|
||||
redefineModule(null, Set.of(), Map.of(), Map.of(), Set.of(), Map.of());
|
||||
assertTrue(false);
|
||||
} catch (NullPointerException e) { }
|
||||
|
||||
try {
|
||||
redefineModule(baseModule, null, Map.of(), Map.of(), Set.of(), Map.of());
|
||||
assertTrue(false);
|
||||
} catch (NullPointerException e) { }
|
||||
|
||||
try {
|
||||
redefineModule(baseModule, Set.of(), null, Map.of(), Set.of(), Map.of());
|
||||
assertTrue(false);
|
||||
} catch (NullPointerException e) { }
|
||||
|
||||
try {
|
||||
redefineModule(baseModule, Set.of(), Map.of(), null, Set.of(), Map.of());
|
||||
assertTrue(false);
|
||||
} catch (NullPointerException e) { }
|
||||
|
||||
try {
|
||||
redefineModule(baseModule, Set.of(), Map.of(), Map.of(), null, Map.of());
|
||||
assertTrue(false);
|
||||
} catch (NullPointerException e) { }
|
||||
|
||||
try {
|
||||
redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), null);
|
||||
assertTrue(false);
|
||||
} catch (NullPointerException e) { }
|
||||
|
||||
try {
|
||||
Set<Module> containsNull = new HashSet<>();
|
||||
containsNull.add(null);
|
||||
redefineModule(baseModule, containsNull, Map.of(), Map.of(), Set.of(), Map.of());
|
||||
assertTrue(false);
|
||||
} catch (NullPointerException e) { }
|
||||
|
||||
try {
|
||||
Map<String, Set<Module>> extraExports = new HashMap<>();
|
||||
extraExports.put(null, Set.of());
|
||||
redefineModule(baseModule, Set.of(), extraExports, Map.of(), Set.of(), Map.of());
|
||||
assertTrue(false);
|
||||
} catch (NullPointerException e) { }
|
||||
|
||||
try {
|
||||
Map<String, Set<Module>> extraExports = new HashMap<>();
|
||||
extraExports.put(null, Set.of());
|
||||
redefineModule(baseModule, Set.of(), Map.of(), extraExports, Set.of(), Map.of());
|
||||
assertTrue(false);
|
||||
} catch (NullPointerException e) { }
|
||||
|
||||
try {
|
||||
Set<Module> containsNull = new HashSet<>();
|
||||
containsNull.add(null);
|
||||
Map<String, Set<Module>> extraExports = Map.of("java.lang", containsNull);
|
||||
redefineModule(baseModule, Set.of(), extraExports, Map.of(), Set.of(), Map.of());
|
||||
assertTrue(false);
|
||||
} catch (NullPointerException e) { }
|
||||
|
||||
try {
|
||||
Set<Class<?>> containsNull = new HashSet<>();
|
||||
containsNull.add(null);
|
||||
redefineModule(baseModule, Set.of(), Map.of(), Map.of(), containsNull, Map.of());
|
||||
assertTrue(false);
|
||||
} catch (NullPointerException e) { }
|
||||
|
||||
try {
|
||||
Map<Class<?>, List<Class<?>>> extraProvides = new HashMap<>();
|
||||
extraProvides.put(null, List.of());
|
||||
redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides);
|
||||
assertTrue(false);
|
||||
} catch (NullPointerException e) { }
|
||||
|
||||
try {
|
||||
List<Class<?>> containsNull = new ArrayList<>();
|
||||
containsNull.add(null);
|
||||
Map<Class<?>, List<Class<?>>> extraProvides = Map.of(TestProvider.class, containsNull);
|
||||
redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides);
|
||||
assertTrue(false);
|
||||
} catch (NullPointerException e) { }
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue