From fc2a827c079fc5a0786115dc5809cf895de656f4 Mon Sep 17 00:00:00 2001 From: sk89q Date: Sun, 3 Oct 2010 16:12:29 -0700 Subject: [PATCH] Added maximum script execution time of 3 seconds. --- src/WorldEdit.java | 14 ++-- .../sk89q/worldedit/ScriptContextFactory.java | 69 +++++++++++++++++++ 2 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 src/com/sk89q/worldedit/ScriptContextFactory.java diff --git a/src/WorldEdit.java b/src/WorldEdit.java index b2e985b81..77ab9877d 100644 --- a/src/WorldEdit.java +++ b/src/WorldEdit.java @@ -631,6 +631,7 @@ public class WorldEdit extends Plugin { * @param player * @param filename * @param args + * @return Whether the file was attempted execution */ private boolean runScript(Player player, WorldEditSession session, EditSession editSession, String filename, String[] args) throws @@ -659,7 +660,8 @@ public class WorldEdit extends Plugin { String code = buffer.toString(); // Evaluate - Context cx = Context.enter(); + ScriptContextFactory factory = new ScriptContextFactory(); + Context cx = factory.enterContext(); try { ScriptableObject scope = cx.initStandardObjects(); @@ -682,18 +684,22 @@ public class WorldEdit extends Plugin { ScriptableObject.putProperty(scope, "minecraft", Context.javaToJS(minecraft, scope)); + logger.log(Level.INFO, player.getName() + ": executing " + filename + "..."); cx.evaluateString(scope, code, filename, 1, null); + logger.log(Level.INFO, player.getName() + ": script " + filename + " executed successfully."); player.sendMessage(Colors.LightPurple + filename + " executed successfully."); - - return true; } catch (RhinoException re) { - player.sendMessage(Colors.Rose + "JS error: " + re.getMessage()); + player.sendMessage(Colors.Rose + filename + ": JS error: " + re.getMessage()); re.printStackTrace(); + } catch (Error err) { + player.sendMessage(Colors.Rose + filename + ": execution error: " + err.getMessage()); } finally { Context.exit(); session.remember(editSession); } } + + return true; } catch (IOException e) { player.sendMessage(Colors.Rose + "Script could not read or it does not exist."); } diff --git a/src/com/sk89q/worldedit/ScriptContextFactory.java b/src/com/sk89q/worldedit/ScriptContextFactory.java new file mode 100644 index 000000000..8e9a83ef0 --- /dev/null +++ b/src/com/sk89q/worldedit/ScriptContextFactory.java @@ -0,0 +1,69 @@ +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +package com.sk89q.worldedit; + +import org.mozilla.javascript.*; + +/** + * Context factory for the JavaScript engine. + * + * @author Albert + */ +public class ScriptContextFactory extends ContextFactory { + /** + * Context that will be used to store start time. + */ + private static class ScriptContext extends Context { + long startTime; + } + + static { + ContextFactory.initGlobal(new ScriptContextFactory()); + } + + @Override + protected Context makeContext() + { + ScriptContext ctx = new ScriptContext(); + ctx.setInstructionObserverThreshold(10000); + return ctx; + } + + @Override + protected void observeInstructionCount(Context ctx, int instructionCount) + { + ScriptContext sctx = (ScriptContext)ctx; + long currentTime = System.currentTimeMillis(); + if (currentTime - sctx.startTime > 3 * 1000) { + throw new Error("Exceeded 3 seconds"); + } + } + + @Override + protected Object doTopCall(Callable callable, + Context ctx, Scriptable scope, + Scriptable thisObj, Object[] args) + { + ScriptContext sctx = (ScriptContext)ctx; + sctx.startTime = System.currentTimeMillis(); + return super.doTopCall(callable, ctx, scope, thisObj, args); + } + +}