Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

javax.script.ScriptException when eval special js #66

Open
wzhonggo opened this issue Jul 30, 2018 · 5 comments
Open

javax.script.ScriptException when eval special js #66

wzhonggo opened this issue Jul 30, 2018 · 5 comments

Comments

@wzhonggo
Copy link

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.

jsonata-es5.zip

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
@wzhonggo
Copy link
Author

wzhonggo commented Aug 1, 2018

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();
        }

@wzhonggo wzhonggo changed the title javax.script.ScriptException with jsonata.js javax.script.ScriptException when eval special js Aug 1, 2018
@mxro
Copy link
Collaborator

mxro commented Aug 1, 2018

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

@mxro mxro added the bug label Aug 1, 2018
@wzhonggo
Copy link
Author

wzhonggo commented Aug 2, 2018

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":
}

mxro pushed a commit that referenced this issue Nov 4, 2018
@mxro
Copy link
Collaborator

mxro commented Nov 4, 2018

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?

@mxro mxro added the solved label Nov 4, 2018
@KluSe
Copy link

KluSe commented Apr 12, 2019

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants