Merge pull request #755 from OneShotMC/master
fix //calc still being able to crash servers
This commit is contained in:
commit
3babe53f91
@ -116,6 +116,7 @@ import com.sk89q.worldedit.internal.LocalWorldAdapter;
|
||||
import com.sk89q.worldedit.internal.command.WorldEditBinding;
|
||||
import com.sk89q.worldedit.internal.expression.Expression;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.ExpressionEnvironment;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.For;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.Functions;
|
||||
import com.sk89q.worldedit.math.convolution.HeightMap;
|
||||
import com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation;
|
||||
@ -645,6 +646,7 @@ public class Fawe {
|
||||
WorldEditExpressionEnvironment.inject(); // Optimizations + features
|
||||
Expression.inject(); // Optimizations
|
||||
Functions.inject(); // Optimizations
|
||||
For.inject(); // Fixes
|
||||
// BlockData
|
||||
BlockData.inject(); // Temporary fix for 1.9.4
|
||||
BundledBlockData.inject(); // Add custom rotation
|
||||
|
@ -87,10 +87,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@ -552,21 +549,30 @@ public class UtilityCommands extends MethodCommands {
|
||||
try {
|
||||
FaweLimit limit = FawePlayer.wrap(actor).getLimit();
|
||||
final Expression expression = Expression.compile(input);
|
||||
double[] result = new double[] { Double.NaN };
|
||||
|
||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
Future<Double> futureResult = executor.submit(new Callable<Double>() {
|
||||
@Override
|
||||
public Double call() throws Exception {
|
||||
|
||||
return expression.evaluate();
|
||||
}
|
||||
});
|
||||
|
||||
Double result = Double.NaN;
|
||||
try {
|
||||
executor.invokeAll(Arrays.asList(new Callable<Object>() {
|
||||
@Override
|
||||
public Object call() throws Exception {
|
||||
result[0] = expression.evaluate();
|
||||
return null;
|
||||
}
|
||||
}), limit.MAX_EXPRESSION_MS, TimeUnit.MILLISECONDS); // Default timeout of 50 milliseconds to prevent abuse.
|
||||
result = futureResult.get(limit.MAX_EXPRESSION_MS, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
e.printStackTrace();
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
} catch (TimeoutException e) {
|
||||
futureResult.cancel(true);
|
||||
e.printStackTrace();
|
||||
}
|
||||
executor.shutdown();
|
||||
actor.print(BBC.getPrefix() + "= " + result[0]);
|
||||
|
||||
executor.shutdownNow();
|
||||
actor.print(BBC.getPrefix() + "= " + result);
|
||||
} catch (EvaluationException e) {
|
||||
actor.printError(String.format(
|
||||
"'%s' could not be parsed as a valid expression", input));
|
||||
|
@ -0,0 +1,76 @@
|
||||
package com.sk89q.worldedit.internal.expression.runtime;
|
||||
|
||||
import com.sk89q.worldedit.command.UtilityCommands;
|
||||
import com.sk89q.worldedit.internal.expression.Expression;
|
||||
import com.sk89q.worldedit.internal.expression.parser.ParserException;
|
||||
|
||||
public class For extends Node {
|
||||
RValue init;
|
||||
RValue condition;
|
||||
RValue increment;
|
||||
RValue body;
|
||||
|
||||
public For(int position, RValue init, RValue condition, RValue increment, RValue body) {
|
||||
super(position);
|
||||
this.init = init;
|
||||
this.condition = condition;
|
||||
this.increment = increment;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public double getValue() throws EvaluationException {
|
||||
|
||||
int iterations = 0;
|
||||
double ret = 0.0D;
|
||||
this.init.getValue();
|
||||
|
||||
for(; this.condition.getValue() > 0.0D; this.increment.getValue()) {
|
||||
|
||||
if(iterations > 256) {
|
||||
throw new EvaluationException(this.getPosition(), "Loop exceeded 256 iterations.");
|
||||
}
|
||||
|
||||
if(Thread.currentThread().isInterrupted()){
|
||||
throw new EvaluationException(this.getPosition(), "Thread has been interuppted.");
|
||||
}
|
||||
|
||||
++iterations;
|
||||
|
||||
try {
|
||||
ret = this.body.getValue();
|
||||
} catch (BreakException var5) {
|
||||
if(!var5.doContinue) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public char id() {
|
||||
return 'F';
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "for (" + this.init + "; " + this.condition + "; " + this.increment + ") { " + this.body + " }";
|
||||
}
|
||||
|
||||
public RValue optimize() throws EvaluationException {
|
||||
RValue newCondition = this.condition.optimize();
|
||||
return (RValue)(newCondition instanceof Constant && newCondition.getValue() <= 0.0D?(new Sequence(this.getPosition(), new RValue[]{this.init, new Constant(this.getPosition(), 0.0D)})).optimize():new For(this.getPosition(), this.init.optimize(), newCondition, this.increment.optimize(), this.body.optimize()));
|
||||
}
|
||||
|
||||
public RValue bindVariables(Expression expression, boolean preferLValue) throws ParserException {
|
||||
this.init = this.init.bindVariables(expression, false);
|
||||
this.condition = this.condition.bindVariables(expression, false);
|
||||
this.increment = this.increment.bindVariables(expression, false);
|
||||
this.body = this.body.bindVariables(expression, false);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static Class<For> inject() {
|
||||
return For.class;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user