From f41b1fc82131842409fed2df1c702cda36b06bd2 Mon Sep 17 00:00:00 2001 From: md_5 Date: Thu, 20 Feb 2020 12:24:01 +1100 Subject: [PATCH] Do not allow plugins to make multiple instances of their main class. Prevents foot shooting, eg #2772 --- .../net/md_5/bungee/api/plugin/Plugin.java | 17 +++++++++ .../bungee/api/plugin/PluginClassloader.java | 37 +++++++++++++++---- .../md_5/bungee/api/plugin/PluginManager.java | 3 +- .../md_5/bungee/api/plugin/DummyPlugin.java | 11 +++--- 4 files changed, 54 insertions(+), 14 deletions(-) diff --git a/api/src/main/java/net/md_5/bungee/api/plugin/Plugin.java b/api/src/main/java/net/md_5/bungee/api/plugin/Plugin.java index bc91208a7..2286a1ab8 100644 --- a/api/src/main/java/net/md_5/bungee/api/plugin/Plugin.java +++ b/api/src/main/java/net/md_5/bungee/api/plugin/Plugin.java @@ -1,5 +1,6 @@ package net.md_5.bungee.api.plugin; +import com.google.common.base.Preconditions; import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.io.File; import java.io.InputStream; @@ -27,6 +28,22 @@ public class Plugin @Getter private Logger logger; + public Plugin() + { + ClassLoader classLoader = getClass().getClassLoader(); + Preconditions.checkState( classLoader instanceof PluginClassloader, "Plugin requires " + PluginClassloader.class.getName() ); + + ( (PluginClassloader) classLoader ).init( this ); + } + + protected Plugin(ProxyServer proxy, PluginDescription description) + { + ClassLoader classLoader = getClass().getClassLoader(); + Preconditions.checkState( !( classLoader instanceof PluginClassloader ), "Cannot use initialization constructor at runtime" ); + + // init( proxy, description ); + } + /** * Called when the plugin has just been loaded. Most of the proxy will not * be initialized, so only use it for registering diff --git a/api/src/main/java/net/md_5/bungee/api/plugin/PluginClassloader.java b/api/src/main/java/net/md_5/bungee/api/plugin/PluginClassloader.java index 85203fb8a..26ab119ac 100644 --- a/api/src/main/java/net/md_5/bungee/api/plugin/PluginClassloader.java +++ b/api/src/main/java/net/md_5/bungee/api/plugin/PluginClassloader.java @@ -1,37 +1,47 @@ package net.md_5.bungee.api.plugin; +import com.google.common.base.Preconditions; import java.net.URL; import java.net.URLClassLoader; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; +import net.md_5.bungee.api.ProxyServer; -public class PluginClassloader extends URLClassLoader +final class PluginClassloader extends URLClassLoader { private static final Set allLoaders = new CopyOnWriteArraySet<>(); + // + private final ProxyServer proxy; + private final PluginDescription desc; + // + private Plugin plugin; static { ClassLoader.registerAsParallelCapable(); } - public PluginClassloader(URL[] urls) + public PluginClassloader(ProxyServer proxy, PluginDescription desc, URL[] urls) { super( urls ); + this.proxy = proxy; + this.desc = desc; + allLoaders.add( this ); } @Override - protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException + protected Class findClass(String name) throws ClassNotFoundException { - return loadClass0( name, resolve, true ); + return findClass0( name, true ); } - private Class loadClass0(String name, boolean resolve, boolean checkOther) throws ClassNotFoundException + private Class findClass0(String name, boolean checkOther) throws ClassNotFoundException { try { - return super.loadClass( name, resolve ); + return super.findClass( name ); } catch ( ClassNotFoundException ex ) { } @@ -43,7 +53,7 @@ public class PluginClassloader extends URLClassLoader { try { - return loader.loadClass0( name, resolve, false ); + return loader.findClass0( name, false ); } catch ( ClassNotFoundException ex ) { } @@ -52,4 +62,17 @@ public class PluginClassloader extends URLClassLoader } throw new ClassNotFoundException( name ); } + + void init(Plugin plugin) + { + Preconditions.checkArgument( plugin != null, "plugin" ); + Preconditions.checkArgument( plugin.getClass().getClassLoader() == this, "Plugin has incorrect ClassLoader" ); + if ( this.plugin != null ) + { + throw new IllegalArgumentException( "Plugin already initialized!" ); + } + + this.plugin = plugin; + plugin.init( proxy, desc ); + } } diff --git a/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java b/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java index 7af0bd1e0..36af79c65 100644 --- a/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java +++ b/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java @@ -320,14 +320,13 @@ public class PluginManager { try { - URLClassLoader loader = new PluginClassloader( new URL[] + URLClassLoader loader = new PluginClassloader( proxy, plugin, new URL[] { plugin.getFile().toURI().toURL() } ); Class main = loader.loadClass( plugin.getMain() ); Plugin clazz = (Plugin) main.getDeclaredConstructor().newInstance(); - clazz.init( proxy, plugin ); plugins.put( plugin.getName(), clazz ); clazz.onLoad(); ProxyServer.getInstance().getLogger().log( Level.INFO, "Loaded plugin {0} version {1} by {2}", new Object[] diff --git a/proxy/src/test/java/net/md_5/bungee/api/plugin/DummyPlugin.java b/proxy/src/test/java/net/md_5/bungee/api/plugin/DummyPlugin.java index 3e2f126d2..5e13aa73a 100644 --- a/proxy/src/test/java/net/md_5/bungee/api/plugin/DummyPlugin.java +++ b/proxy/src/test/java/net/md_5/bungee/api/plugin/DummyPlugin.java @@ -1,11 +1,12 @@ package net.md_5.bungee.api.plugin; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class DummyPlugin extends Plugin +public final class DummyPlugin extends Plugin { public static final DummyPlugin INSTANCE = new DummyPlugin(); + + private DummyPlugin() + { + super( null, null ); + } }