Do not allow plugins to make multiple instances of their main class.

Prevents foot shooting, eg #2772
This commit is contained in:
md_5 2020-02-20 12:24:01 +11:00
parent e6b0d43d66
commit f41b1fc821
4 changed files with 54 additions and 14 deletions

View File

@ -1,5 +1,6 @@
package net.md_5.bungee.api.plugin; package net.md_5.bungee.api.plugin;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;
@ -27,6 +28,22 @@ public class Plugin
@Getter @Getter
private Logger logger; 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 * Called when the plugin has just been loaded. Most of the proxy will not
* be initialized, so only use it for registering * be initialized, so only use it for registering

View File

@ -1,37 +1,47 @@
package net.md_5.bungee.api.plugin; package net.md_5.bungee.api.plugin;
import com.google.common.base.Preconditions;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet; 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<PluginClassloader> allLoaders = new CopyOnWriteArraySet<>(); private static final Set<PluginClassloader> allLoaders = new CopyOnWriteArraySet<>();
//
private final ProxyServer proxy;
private final PluginDescription desc;
//
private Plugin plugin;
static static
{ {
ClassLoader.registerAsParallelCapable(); ClassLoader.registerAsParallelCapable();
} }
public PluginClassloader(URL[] urls) public PluginClassloader(ProxyServer proxy, PluginDescription desc, URL[] urls)
{ {
super( urls ); super( urls );
this.proxy = proxy;
this.desc = desc;
allLoaders.add( this ); allLoaders.add( this );
} }
@Override @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 try
{ {
return super.loadClass( name, resolve ); return super.findClass( name );
} catch ( ClassNotFoundException ex ) } catch ( ClassNotFoundException ex )
{ {
} }
@ -43,7 +53,7 @@ public class PluginClassloader extends URLClassLoader
{ {
try try
{ {
return loader.loadClass0( name, resolve, false ); return loader.findClass0( name, false );
} catch ( ClassNotFoundException ex ) } catch ( ClassNotFoundException ex )
{ {
} }
@ -52,4 +62,17 @@ public class PluginClassloader extends URLClassLoader
} }
throw new ClassNotFoundException( name ); 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 );
}
} }

View File

@ -320,14 +320,13 @@ public class PluginManager
{ {
try try
{ {
URLClassLoader loader = new PluginClassloader( new URL[] URLClassLoader loader = new PluginClassloader( proxy, plugin, new URL[]
{ {
plugin.getFile().toURI().toURL() plugin.getFile().toURI().toURL()
} ); } );
Class<?> main = loader.loadClass( plugin.getMain() ); Class<?> main = loader.loadClass( plugin.getMain() );
Plugin clazz = (Plugin) main.getDeclaredConstructor().newInstance(); Plugin clazz = (Plugin) main.getDeclaredConstructor().newInstance();
clazz.init( proxy, plugin );
plugins.put( plugin.getName(), clazz ); plugins.put( plugin.getName(), clazz );
clazz.onLoad(); clazz.onLoad();
ProxyServer.getInstance().getLogger().log( Level.INFO, "Loaded plugin {0} version {1} by {2}", new Object[] ProxyServer.getInstance().getLogger().log( Level.INFO, "Loaded plugin {0} version {1} by {2}", new Object[]

View File

@ -1,11 +1,12 @@
package net.md_5.bungee.api.plugin; package net.md_5.bungee.api.plugin;
import lombok.AccessLevel; public final class DummyPlugin extends Plugin
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class DummyPlugin extends Plugin
{ {
public static final DummyPlugin INSTANCE = new DummyPlugin(); public static final DummyPlugin INSTANCE = new DummyPlugin();
private DummyPlugin()
{
super( null, null );
}
} }