javax.script.ScriptException when eval special js
wzhonggo opened this issue · 5 comments
Hi,
I want to eval jsonata.js by NashornSandbox(version is 0.1.16). Jsonata.js ie write by es6, jdk8 no full support es6, so i use jsonata-es5.js to test, but still hava problem. It is ok if only use jdk8.
only jdk8
NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
NashornScriptEngine engine = (NashornScriptEngine) factory.getScriptEngine();
Invocable inv = (Invocable) engine;
FileReader jsonata = new FileReader(Demo.class.getResource("/jsonata-es5.js").getFile());
engine.eval(jsonata);
String sample = FileUtils.readFileToString(new File(Demo.class.getResource("/sample.json").getFile()), "UTF-8");
engine.put("input", sample);
Object inputjson = engine.eval("JSON.parse(input);");
String expression = "Address.City"; // JSONata expression
Object expr = inv.invokeFunction("jsonata", expression);
Object resultjson = inv.invokeMethod(expr, "evaluate", inputjson);
engine.put("resultjson", resultjson);
Object result = engine.eval("JSON.stringify(resultjson);");
System.out.println(result);
use NashornSandbox
NashornSandbox sandbox = NashornSandboxes.create();
try {
sandbox.setMaxCPUTime(6000);
sandbox.setMaxMemory(5000*1024);
sandbox.allowNoBraces(true);
sandbox.allowExitFunctions(true);
sandbox.allowGlobalsObjects(true);
sandbox.allowLoadFunctions(true);
sandbox.allowPrintFunctions(true);
sandbox.allowReadFunctions(true);
sandbox.setMaxPreparedStatements(10000);
sandbox.setExecutor(Executors.newSingleThreadExecutor());
String jsonata = FileUtils.readFileToString(new File(NashornSandboxDemo.class.getResource("/jsonata-es5.js").getFile()),"UTF-8");
sandbox.eval(jsonata);
String expression = "Address.City"; // JSONata expression
} catch (ScriptException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
sandbox.getExecutor().shutdown();
}
sample.json
{
"FirstName": "Fred",
"Surname": "Smith",
"Age": 28,
"Address": {
"Street": "Hursley Park",
"City": "Winchester",
"Postcode": "SO21 2JN"
},
"Phone": [
{
"type": "home",
"number": "0203 544 1234"
},
{
"type": "office",
"number": "01962 001234"
},
{
"type": "office",
"number": "01962 001235"
},
{
"type": "mobile",
"number": "077 7700 1234"
}
],
"Email": [
{
"type": "work",
"address": ["fred.smith@my-work.com", "fsmith@my-work.com"]
},
{
"type": "home",
"address": ["freddy@my-social.com", "frederic.smith@very-serious.com"]
}
],
"Other": {
"Over 18 ?": true,
"Misc": null,
"Alternative.Address": {
"Street": "Brick Lane",
"City": "London",
"Postcode": "E1 6RF"
}
}
}
error stack
javax.script.ScriptException: <eval>:131:26 Expected : but found (
var operators = {__if();
^ in <eval> at line number 131 at column number 26
at jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:467)
at jdk.nashorn.api.scripting.NashornScriptEngine.compileImpl(NashornScriptEngine.java:534)
at jdk.nashorn.api.scripting.NashornScriptEngine.compileImpl(NashornScriptEngine.java:521)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:399)
at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:155)
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
at delight.nashornsandbox.internal.EvaluateOperation.executeScriptEngineOperation(EvaluateOperation.java:47)
at delight.nashornsandbox.internal.JsEvaluator.run(JsEvaluator.java:54)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: jdk.nashorn.internal.runtime.ParserException: <eval>:131:26 Expected : but found (
var operators = {__if();
^
at jdk.nashorn.internal.parser.AbstractParser.error(AbstractParser.java:292)
at jdk.nashorn.internal.parser.AbstractParser.error(AbstractParser.java:277)
at jdk.nashorn.internal.parser.AbstractParser.expectDontAdvance(AbstractParser.java:348)
at jdk.nashorn.internal.parser.AbstractParser.expect(AbstractParser.java:335)
at jdk.nashorn.internal.parser.Parser.propertyAssignment(Parser.java:2297)
at jdk.nashorn.internal.parser.Parser.objectLiteral(Parser.java:2155)
at jdk.nashorn.internal.parser.Parser.primaryExpression(Parser.java:1988)
at jdk.nashorn.internal.parser.Parser.memberExpression(Parser.java:2511)
at jdk.nashorn.internal.parser.Parser.leftHandSideExpression(Parser.java:2372)
at jdk.nashorn.internal.parser.Parser.unaryExpression(Parser.java:3147)
at jdk.nashorn.internal.parser.Parser.assignmentExpression(Parser.java:3353)
at jdk.nashorn.internal.parser.Parser.variableStatement(Parser.java:1088)
at jdk.nashorn.internal.parser.Parser.statement(Parser.java:884)
at jdk.nashorn.internal.parser.Parser.sourceElements(Parser.java:773)
at jdk.nashorn.internal.parser.Parser.functionBody(Parser.java:2901)
at jdk.nashorn.internal.parser.Parser.functionExpression(Parser.java:2663)
at jdk.nashorn.internal.parser.Parser.memberExpression(Parser.java:2506)
at jdk.nashorn.internal.parser.Parser.leftHandSideExpression(Parser.java:2372)
at jdk.nashorn.internal.parser.Parser.unaryExpression(Parser.java:3147)
at jdk.nashorn.internal.parser.Parser.assignmentExpression(Parser.java:3353)
at jdk.nashorn.internal.parser.Parser.variableStatement(Parser.java:1088)
at jdk.nashorn.internal.parser.Parser.statement(Parser.java:884)
at jdk.nashorn.internal.parser.Parser.sourceElements(Parser.java:773)
at jdk.nashorn.internal.parser.Parser.functionBody(Parser.java:2901)
at jdk.nashorn.internal.parser.Parser.functionExpression(Parser.java:2663)
at jdk.nashorn.internal.parser.Parser.memberExpression(Parser.java:2506)
at jdk.nashorn.internal.parser.Parser.leftHandSideExpression(Parser.java:2372)
at jdk.nashorn.internal.parser.Parser.unaryExpression(Parser.java:3147)
at jdk.nashorn.internal.parser.Parser.expression(Parser.java:3282)
at jdk.nashorn.internal.parser.Parser.primaryExpression(Parser.java:1992)
at jdk.nashorn.internal.parser.Parser.memberExpression(Parser.java:2511)
at jdk.nashorn.internal.parser.Parser.leftHandSideExpression(Parser.java:2372)
at jdk.nashorn.internal.parser.Parser.unaryExpression(Parser.java:3147)
at jdk.nashorn.internal.parser.Parser.expression(Parser.java:3282)
at jdk.nashorn.internal.parser.Parser.expressionStatement(Parser.java:1150)
at jdk.nashorn.internal.parser.Parser.statement(Parser.java:967)
at jdk.nashorn.internal.parser.Parser.sourceElements(Parser.java:773)
at jdk.nashorn.internal.parser.Parser.functionBody(Parser.java:2901)
at jdk.nashorn.internal.parser.Parser.functionExpression(Parser.java:2663)
at jdk.nashorn.internal.parser.Parser.memberExpression(Parser.java:2506)
at jdk.nashorn.internal.parser.Parser.leftHandSideExpression(Parser.java:2372)
at jdk.nashorn.internal.parser.Parser.unaryExpression(Parser.java:3147)
at jdk.nashorn.internal.parser.Parser.assignmentExpression(Parser.java:3353)
at jdk.nashorn.internal.parser.Parser.arrayLiteral(Parser.java:2090)
at jdk.nashorn.internal.parser.Parser.primaryExpression(Parser.java:1986)
at jdk.nashorn.internal.parser.Parser.memberExpression(Parser.java:2511)
at jdk.nashorn.internal.parser.Parser.leftHandSideExpression(Parser.java:2372)
at jdk.nashorn.internal.parser.Parser.unaryExpression(Parser.java:3147)
at jdk.nashorn.internal.parser.Parser.assignmentExpression(Parser.java:3353)
at jdk.nashorn.internal.parser.Parser.propertyAssignment(Parser.java:2301)
at jdk.nashorn.internal.parser.Parser.objectLiteral(Parser.java:2155)
at jdk.nashorn.internal.parser.Parser.primaryExpression(Parser.java:1988)
at jdk.nashorn.internal.parser.Parser.memberExpression(Parser.java:2511)
at jdk.nashorn.internal.parser.Parser.leftHandSideExpression(Parser.java:2372)
at jdk.nashorn.internal.parser.Parser.unaryExpression(Parser.java:3147)
at jdk.nashorn.internal.parser.Parser.assignmentExpression(Parser.java:3353)
at jdk.nashorn.internal.parser.Parser.argumentList(Parser.java:2588)
at jdk.nashorn.internal.parser.Parser.leftHandSideExpression(Parser.java:2394)
at jdk.nashorn.internal.parser.Parser.unaryExpression(Parser.java:3147)
at jdk.nashorn.internal.parser.Parser.expression(Parser.java:3282)
at jdk.nashorn.internal.parser.Parser.returnStatement(Parser.java:1565)
at jdk.nashorn.internal.parser.Parser.statement(Parser.java:908)
at jdk.nashorn.internal.parser.Parser.sourceElements(Parser.java:773)
at jdk.nashorn.internal.parser.Parser.functionBody(Parser.java:2901)
at jdk.nashorn.internal.parser.Parser.functionExpression(Parser.java:2663)
at jdk.nashorn.internal.parser.Parser.memberExpression(Parser.java:2506)
at jdk.nashorn.internal.parser.Parser.leftHandSideExpression(Parser.java:2372)
at jdk.nashorn.internal.parser.Parser.unaryExpression(Parser.java:3147)
at jdk.nashorn.internal.parser.Parser.assignmentExpression(Parser.java:3353)
at jdk.nashorn.internal.parser.Parser.argumentList(Parser.java:2588)
at jdk.nashorn.internal.parser.Parser.leftHandSideExpression(Parser.java:2375)
at jdk.nashorn.internal.parser.Parser.unaryExpression(Parser.java:3147)
at jdk.nashorn.internal.parser.Parser.expression(Parser.java:3282)
at jdk.nashorn.internal.parser.Parser.expressionStatement(Parser.java:1150)
at jdk.nashorn.internal.parser.Parser.statement(Parser.java:967)
at jdk.nashorn.internal.parser.Parser.sourceElements(Parser.java:773)
at jdk.nashorn.internal.parser.Parser.program(Parser.java:709)
at jdk.nashorn.internal.parser.Parser.parse(Parser.java:283)
at jdk.nashorn.internal.parser.Parser.parse(Parser.java:249)
at jdk.nashorn.internal.runtime.Context.compile(Context.java:1286)
at jdk.nashorn.internal.runtime.Context.compileScript(Context.java:1253)
at jdk.nashorn.internal.runtime.Context.compileScript(Context.java:625)
at jdk.nashorn.api.scripting.NashornScriptEngine.compileImpl(NashornScriptEngine.java:532)
... 9 more
Now i can easy reproduce. It has problem when call injectInterruptionCalls method in JsSanitizer class. The Regular expression (\s*([^"]?function[^"])\s*[^\{]+\{)
will add __if() in error postion.
source demo.js
var t1 = "(function)";
var person={
"name": "test"
};
print("t1" + person.name);
demo.js (after call injectInterruptionCalls method)
var t1 = "(function)";
var person = {__if();
"name": "test"
};
print("t1" + person.name);
only jdk8
NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
NashornScriptEngine engine = (NashornScriptEngine) factory.getScriptEngine();
String demo = FileUtils.readFileToString(new File(NashornSandboxDemo.class.getResource("/demo.js").getFile()),"UTF-8");
engine.eval(demo);
use NashornSandbox
NashornSandbox sandbox = NashornSandboxes.create();
try {
sandbox.setMaxCPUTime(6000);
sandbox.setMaxMemory(50*1024*1024L);
sandbox.allowNoBraces(true);
sandbox.allowExitFunctions(true);
sandbox.allowGlobalsObjects(true);
sandbox.allowLoadFunctions(true);
sandbox.allowPrintFunctions(true);
sandbox.allowReadFunctions(true);
sandbox.setMaxPreparedStatements(10000);
sandbox.setExecutor(Executors.newSingleThreadExecutor());
String demo = FileUtils.readFileToString(new File(NashornSandboxDemo.class.getResource("/demo.js").getFile()),"UTF-8");
sandbox.eval(demo);
} catch (ScriptException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
sandbox.getExecutor().shutdown();
}
Hello! Thank you for reporting this issue and for digging a bit deeper to find out the cause.
It's definitely possible that the injected JS causes problems in some edge cases. I will hopefully have time on the weekend to look into finding a workaround for this. In the meantime, be welcome to have a look if you can find anything obvious. The code is injected here: https://github.com/javadelight/delight-nashorn-sandbox/blob/master/src/main/java/delight/nashornsandbox/internal/JsSanitizer.java
change regex expression
// in delight.nashornsandbox.internal.JsSanitizer line 83
//"(\\s*([^\"]?function[^\"])\\s*[^\\{]+\\{)"
"(\\s*([^\"]?function)\\s*[^\"]*\\([^\\{]*\\)\\s*\\{)"
After change code , demo.js is test ok. But it is still not work with other special js.
source demo1.js
function a() {
}
switch (name) {
case "s":
case "n":
}
demo1.js (after call injectInterruptionCalls method)
function a() {}
switch (name) {__if();
case "s":
case "n":
}
Thank you for the solution. With some minor modifications this also solves the second case. See the pull request linked above.
Is this issue resolved now?
Hello,
This problem still seems to persist when the switch-statement is inside the function:
function a() {
switch (name) {
case "s":
case "n":
}
}
The regex matches everything up to the parenthesis after the switch
. Only matching valid identifiers would probably be overkill, so maybe the group matching the function name should exclude the parenthesis. Alternatively, it could be a lazy match to avoid matching beyond the first parenthesis. Not sure which approach would be better.