Filed a bug: https://bugs.openjdk.java.net/browse/JDK-8166186

-Sundar


On 9/15/2016 6:32 PM, Esben Andreasen wrote:
> Nashorn can produce a ClassCastException when executing a plain
> JavaScript program.
>
> The exception happens in a situation where the arguments variable is
> used in conjunction with call and apply.
>
> ## Observed behavior
>
> Code:
> ```
> function F(SOME_PARAMETER) {
>   Function.prototype.call.apply(G, arguments);
> }
>
> function G(){
>   this;
>   F("SOME_ARGUMENT");
> }
>
> G();
> ```
>
> Execution:
> ```
> $ jjs -version test.js
> nashorn 1.8.0_101
> Exception in thread "main" java.lang.ClassCastException: Cannot cast
> jdk.nashorn.internal.objects.NativeArguments to [Ljava.lang.Object;
> at
> java.lang.invoke.MethodHandleImpl.newClassCastException(MethodHandleImpl.java:361)
> at
> java.lang.invoke.MethodHandleImpl.castReference(MethodHandleImpl.java:356)
>         ...
> ```
>
> ## Expected behavior
>
> Something else than a ClassCastException. Especially since the program
> is plain JavaScript.
>
> The minimal example will produce a 'RangeError: Maximum call stack
> size exceeded' and 'InternalError: too much recursion' on Chrome/Node
> and Firefox respectively.
>
> ## Thoughts
>
> The stack trace reveal that the arguments object is being cast to an
> array of objects, that seems wrong.
>
> According to ECMA262-5.1 for Function.prototype.apply, the numeric
> entries of the second argument should be iterated, if that argument is
> array-like. It looks like Nashorn just assumes it is an array already,
> and does the corresponding cast.
>
>
> The minimal example requires several surprising elements that should
> have no effect on the behavior of the program. But the
> ClassCastException disappear if one of them is removed.
>
> - the `this` variable in G
> - the unused `"SOME_ARGUMENT"` argument in G
> - the unused `SOME_PARAMETER` parameter name in F
> - the use use of `call.apply` in F, it should be rewritable to just `apply`
>
>
>
> ## Regression test
>
> The minimal example has been extended with a counter to avoid the
> stack overflow in other engines.
>
> ```
> var i = 0;
> function F(SOME_PARAMETER) {
>   if(i++ > 3){
>     return;
>   }
>   Function.prototype.call.apply(G, arguments);
> }
>
> function G(){
>   this;
>   F("SOME_ARGUMENT");
> }
>
> G();
> ```
>
> -
> Esben

Reply via email to