Skip to content

Instantly share code, notes, and snippets.

@also
Last active August 19, 2019 21:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save also/412ce859f10f0b501bbfc43d15342dfc to your computer and use it in GitHub Desktop.
Save also/412ce859f10f0b501bbfc43d15342dfc to your computer and use it in GitHub Desktop.

Nashorn Scope Leak

In Java 8, this code prints

1
1

1
1

...

In Java 9-12, this prints

1
1

2
NaN

1
1

2
NaN

NaN
NaN

NaN
NaN

NaN
NaN

NaN
NaN

NaN
NaN

NaN
NaN

NaN
NaN

NaN
NaN

NaN
NaN

NaN
NaN

NaN
NaN

NaN
NaN

NaN
1

2
1

2
1

2
1

The test function is somehow shared between contexts.

Any of these changes will result in the expected behavior:

  • commenting out either x = 1 or eval('');
  • calling print(++test.calls); before x = 1;
  • omitting context in the calls to engine.eval
package test;
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleScriptContext;
public class ScopeLeak {
private static final String script = "var x;\n" +
"function test() {\n" +
" x = 1;\n" +
" print(++test.calls);\n" +
" eval('');\n" +
"}\n" +
"test.calls = 0;\n" +
"test();";
public static void main(String... args) throws ScriptException {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
for (int i = 0; i < 20; i++) {
SimpleScriptContext context = new SimpleScriptContext();
Bindings bindings = engine.createBindings();
context.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
engine.eval(script, context);
engine.eval(script, context);
System.out.println();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment