Title: [109461] trunk
Revision
109461
Author
[email protected]
Date
2012-03-01 16:12:58 -0800 (Thu, 01 Mar 2012)

Log Message

ES5.1-15.3.5.4. prohibits Function.caller from [[Get]]ting a strict caller
https://bugs.webkit.org/show_bug.cgi?id=80011

Reviewed by Oliver Hunt.

Also, fix getting the caller from within a bound function, for within a getter,
or setter (make our implementation match other browsers).

Source/_javascript_Core: 

* interpreter/Interpreter.cpp:
(JSC::getCallerInfo):
    - Allow this to get the caller of host functions.
(JSC::Interpreter::retrieveCallerFromVMCode):
    - This should use getCallerInfo, and should skip over function bindings.
* runtime/JSFunction.cpp:
(JSC::JSFunction::callerGetter):
    - This should never return a strict-mode function.

LayoutTests: 

* fast/js/caller-property-expected.txt:
* fast/js/script-tests/caller-property.js:
    - Add test cases covering permutations of caller/callee being strict/non-strict,
      And for callee being a getter/setter/bound.
* fast/js/stack-trace-expected.txt:
    - Allow stack tracing over host functions.

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (109460 => 109461)


--- trunk/LayoutTests/ChangeLog	2012-03-02 00:11:16 UTC (rev 109460)
+++ trunk/LayoutTests/ChangeLog	2012-03-02 00:12:58 UTC (rev 109461)
@@ -1,3 +1,20 @@
+2012-03-01  Gavin Barraclough  <[email protected]>
+
+        ES5.1-15.3.5.4. prohibits Function.caller from [[Get]]ting a strict caller
+        https://bugs.webkit.org/show_bug.cgi?id=80011
+
+        Reviewed by Oliver Hunt.
+
+        Also, fix getting the caller from within a bound function, for within a getter,
+        or setter (make our implementation match other browsers).
+
+        * fast/js/caller-property-expected.txt:
+        * fast/js/script-tests/caller-property.js:
+            - Add test cases covering permutations of caller/callee being strict/non-strict,
+              And for callee being a getter/setter/bound.
+        * fast/js/stack-trace-expected.txt:
+            - Allow stack tracing over host functions.
+
 2012-03-01  Xingnan Wang  <[email protected]>
 
         Enable IPP for Biquad filter

Modified: trunk/LayoutTests/fast/js/caller-property-expected.txt (109460 => 109461)


--- trunk/LayoutTests/fast/js/caller-property-expected.txt	2012-03-02 00:11:16 UTC (rev 109460)
+++ trunk/LayoutTests/fast/js/caller-property-expected.txt	2012-03-02 00:12:58 UTC (rev 109461)
@@ -6,6 +6,22 @@
 PASS childHasCallerWhenExecutingGlobalCode is false
 PASS childHasCallerWhenCalledWithoutParent is false
 PASS childHasCallerWhenCalledFromWithinParent is true
+PASS nonStrictCaller(nonStrictCallee) is nonStrictCaller
+PASS nonStrictCaller(strictCallee) threw exception TypeError: Type error.
+PASS strictCaller(nonStrictCallee) threw exception TypeError: Function.caller used to retrieve strict caller.
+PASS strictCaller(strictCallee) threw exception TypeError: Type error.
+PASS nonStrictCaller(boundNonStrictCallee) is nonStrictCaller
+PASS nonStrictCaller(boundStrictCallee) threw exception TypeError: Type error.
+PASS strictCaller(boundNonStrictCallee) threw exception TypeError: Function.caller used to retrieve strict caller.
+PASS strictCaller(boundStrictCallee) threw exception TypeError: Type error.
+PASS nonStrictGetter(nonStrictAccessor) is nonStrictGetter
+PASS nonStrictSetter(nonStrictAccessor) is true
+PASS nonStrictGetter(strictAccessor) threw exception TypeError: Type error.
+PASS nonStrictSetter(strictAccessor) threw exception TypeError: Type error.
+PASS strictGetter(nonStrictAccessor) threw exception TypeError: Function.caller used to retrieve strict caller.
+PASS strictSetter(nonStrictAccessor) threw exception TypeError: Function.caller used to retrieve strict caller.
+PASS strictGetter(strictAccessor) threw exception TypeError: Type error.
+PASS strictSetter(strictAccessor) threw exception TypeError: Type error.
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/fast/js/script-tests/caller-property.js (109460 => 109461)


--- trunk/LayoutTests/fast/js/script-tests/caller-property.js	2012-03-02 00:11:16 UTC (rev 109460)
+++ trunk/LayoutTests/fast/js/script-tests/caller-property.js	2012-03-02 00:12:58 UTC (rev 109461)
@@ -18,3 +18,45 @@
 shouldBe('childHasCallerWhenExecutingGlobalCode', 'false');
 shouldBe('childHasCallerWhenCalledWithoutParent', 'false');
 shouldBe('childHasCallerWhenCalledFromWithinParent', 'true')
+
+// The caller property should throw in strict mode, and a non-strict function cannot use caller to reach a strict caller (see ES5.1 15.3.5.4).
+function nonStrictCallee() { return nonStrictCallee.caller; }
+function strictCallee() { "use strict"; return strictCallee.caller; }
+function nonStrictCaller(x) { return x(); }
+function strictCaller(x) { "use strict"; return x(); }
+shouldBe("nonStrictCaller(nonStrictCallee)", "nonStrictCaller");
+shouldThrow("nonStrictCaller(strictCallee)", '"TypeError: Type error"');
+shouldThrow("strictCaller(nonStrictCallee)", '"TypeError: Function.caller used to retrieve strict caller"');
+shouldThrow("strictCaller(strictCallee)", '"TypeError: Type error"');
+
+// .caller within a bound function reaches the caller, ignoring the binding.
+var boundNonStrictCallee = nonStrictCallee.bind();
+var boundStrictCallee = strictCallee.bind();
+shouldBe("nonStrictCaller(boundNonStrictCallee)", "nonStrictCaller");
+shouldThrow("nonStrictCaller(boundStrictCallee)", '"TypeError: Type error"');
+shouldThrow("strictCaller(boundNonStrictCallee)", '"TypeError: Function.caller used to retrieve strict caller"');
+shouldThrow("strictCaller(boundStrictCallee)", '"TypeError: Type error"');
+
+// Check that .caller works (or throws) as expected, over an accessor call.
+function getFooGetter(x) { return Object.getOwnPropertyDescriptor(x, 'foo').get; }
+function getFooSetter(x) { return Object.getOwnPropertyDescriptor(x, 'foo').set; }
+var nonStrictAccessor = {
+    get foo() { return getFooGetter(nonStrictAccessor).caller; },
+    set foo(x) { if (getFooSetter(nonStrictAccessor).caller !==x) throw false; }
+};
+var strictAccessor = {
+    get foo() { "use strict"; return getFooGetter(strictAccessor).caller; },
+    set foo(x) { "use strict"; if (getFooSetter(strictAccessor).caller !==x) throw false; }
+};
+function nonStrictGetter(x) { return x.foo; }
+function nonStrictSetter(x) { x.foo = nonStrictSetter; return true; }
+function strictGetter(x) { "use strict"; return x.foo; }
+function strictSetter(x) { "use strict"; x.foo = nonStrictSetter; return true; }
+shouldBe("nonStrictGetter(nonStrictAccessor)", "nonStrictGetter");
+shouldBeTrue("nonStrictSetter(nonStrictAccessor)");
+shouldThrow("nonStrictGetter(strictAccessor)", '"TypeError: Type error"');
+shouldThrow("nonStrictSetter(strictAccessor)", '"TypeError: Type error"');
+shouldThrow("strictGetter(nonStrictAccessor)", '"TypeError: Function.caller used to retrieve strict caller"');
+shouldThrow("strictSetter(nonStrictAccessor)", '"TypeError: Function.caller used to retrieve strict caller"');
+shouldThrow("strictGetter(strictAccessor)", '"TypeError: Type error"');
+shouldThrow("strictSetter(strictAccessor)", '"TypeError: Type error"');

Modified: trunk/LayoutTests/fast/js/stack-trace-expected.txt (109460 => 109461)


--- trunk/LayoutTests/fast/js/stack-trace-expected.txt	2012-03-02 00:11:16 UTC (rev 109460)
+++ trunk/LayoutTests/fast/js/stack-trace-expected.txt	2012-03-02 00:12:58 UTC (rev 109461)
@@ -12,12 +12,16 @@
     0   inner at stack-trace.js:28
     1    at eval code
     2   eval at [native code]
+    3   evaler at stack-trace.js:29
+    4   global code at stack-trace.js:39
 
 --> Stack Trace:
     0   inner at stack-trace.js:28
     1   outer at stack-trace.js:27
     2    at eval code
     3   eval at [native code]
+    4   evaler at stack-trace.js:29
+    5   global code at stack-trace.js:40
 
 --> Stack Trace:
     0   inner at stack-trace.js:28
@@ -251,6 +255,103 @@
     0   selfRecursive3 at stack-trace.js:69
     1    at eval code
     2   eval at [native code]
+    3   selfRecursive3 at stack-trace.js:69
+    4    at eval code
+    5   eval at [native code]
+    6   selfRecursive3 at stack-trace.js:69
+    7    at eval code
+    8   eval at [native code]
+    9   selfRecursive3 at stack-trace.js:69
+    10    at eval code
+    11   eval at [native code]
+    12   selfRecursive3 at stack-trace.js:69
+    13    at eval code
+    14   eval at [native code]
+    15   selfRecursive3 at stack-trace.js:69
+    16    at eval code
+    17   eval at [native code]
+    18   selfRecursive3 at stack-trace.js:69
+    19    at eval code
+    20   eval at [native code]
+    21   selfRecursive3 at stack-trace.js:69
+    22    at eval code
+    23   eval at [native code]
+    24   selfRecursive3 at stack-trace.js:69
+    25    at eval code
+    26   eval at [native code]
+    27   selfRecursive3 at stack-trace.js:69
+    28    at eval code
+    29   eval at [native code]
+    30   selfRecursive3 at stack-trace.js:69
+    31    at eval code
+    32   eval at [native code]
+    33   selfRecursive3 at stack-trace.js:69
+    34    at eval code
+    35   eval at [native code]
+    36   selfRecursive3 at stack-trace.js:69
+    37    at eval code
+    38   eval at [native code]
+    39   selfRecursive3 at stack-trace.js:69
+    40    at eval code
+    41   eval at [native code]
+    42   selfRecursive3 at stack-trace.js:69
+    43    at eval code
+    44   eval at [native code]
+    45   selfRecursive3 at stack-trace.js:69
+    46    at eval code
+    47   eval at [native code]
+    48   selfRecursive3 at stack-trace.js:69
+    49    at eval code
+    50   eval at [native code]
+    51   selfRecursive3 at stack-trace.js:69
+    52    at eval code
+    53   eval at [native code]
+    54   selfRecursive3 at stack-trace.js:69
+    55    at eval code
+    56   eval at [native code]
+    57   selfRecursive3 at stack-trace.js:69
+    58    at eval code
+    59   eval at [native code]
+    60   selfRecursive3 at stack-trace.js:69
+    61    at eval code
+    62   eval at [native code]
+    63   selfRecursive3 at stack-trace.js:69
+    64    at eval code
+    65   eval at [native code]
+    66   selfRecursive3 at stack-trace.js:69
+    67    at eval code
+    68   eval at [native code]
+    69   selfRecursive3 at stack-trace.js:69
+    70    at eval code
+    71   eval at [native code]
+    72   selfRecursive3 at stack-trace.js:69
+    73    at eval code
+    74   eval at [native code]
+    75   selfRecursive3 at stack-trace.js:69
+    76    at eval code
+    77   eval at [native code]
+    78   selfRecursive3 at stack-trace.js:69
+    79    at eval code
+    80   eval at [native code]
+    81   selfRecursive3 at stack-trace.js:69
+    82    at eval code
+    83   eval at [native code]
+    84   selfRecursive3 at stack-trace.js:69
+    85    at eval code
+    86   eval at [native code]
+    87   selfRecursive3 at stack-trace.js:69
+    88    at eval code
+    89   eval at [native code]
+    90   selfRecursive3 at stack-trace.js:69
+    91    at eval code
+    92   eval at [native code]
+    93   selfRecursive3 at stack-trace.js:69
+    94    at eval code
+    95   eval at [native code]
+    96   selfRecursive3 at stack-trace.js:69
+    97    at eval code
+    98   eval at [native code]
+    99   selfRecursive3 at stack-trace.js:69
 
 --> Stack Trace:
     0   throwError at stack-trace.js:77
@@ -262,6 +363,7 @@
     6   makeInlinableCall at stack-trace.js:131
     7   g at stack-trace.js:140
     8   map at [native code]
+    9   global code at stack-trace.js:143
 
 --> Stack Trace:
     0   throwError at stack-trace.js:77
@@ -272,6 +374,7 @@
     5   makeInlinableCall at stack-trace.js:131
     6   g at stack-trace.js:140
     7   map at [native code]
+    8   global code at stack-trace.js:143
 
 --> Stack Trace:
     0   throwError at stack-trace.js:77
@@ -282,6 +385,7 @@
     5   makeInlinableCall at stack-trace.js:131
     6   g at stack-trace.js:140
     7   map at [native code]
+    8   global code at stack-trace.js:143
 
 --> Stack Trace:
     0   throwError at stack-trace.js:77
@@ -293,19 +397,27 @@
     6   makeInlinableCall at stack-trace.js:131
     7   g at stack-trace.js:140
     8   map at [native code]
+    9   global code at stack-trace.js:143
 
 --> Stack Trace:
     0   h at stack-trace.js:151
     1   map at [native code]
+    2   mapTest at stack-trace.js:158
+    3   mapTestDriver at stack-trace.js:164
+    4   global code at stack-trace.js:169
 
 --> Stack Trace:
     0   h at stack-trace.js:153
     1   map at [native code]
+    2   mapTest at stack-trace.js:158
+    3   mapTestDriver at stack-trace.js:164
+    4   global code at stack-trace.js:175
 
 --> Stack Trace:
     0   throwError at stack-trace.js:77
     1   dfgFunction at stack-trace.js:184
     2   map at [native code]
+    3   global code at stack-trace.js:193
 
 --> Stack Trace:
     0   throwError at stack-trace.js:77

Modified: trunk/Source/_javascript_Core/ChangeLog (109460 => 109461)


--- trunk/Source/_javascript_Core/ChangeLog	2012-03-02 00:11:16 UTC (rev 109460)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-03-02 00:12:58 UTC (rev 109461)
@@ -1,3 +1,22 @@
+2012-03-01  Gavin Barraclough  <[email protected]>
+
+        ES5.1-15.3.5.4. prohibits Function.caller from [[Get]]ting a strict caller
+        https://bugs.webkit.org/show_bug.cgi?id=80011
+
+        Reviewed by Oliver Hunt.
+
+        Also, fix getting the caller from within a bound function, for within a getter,
+        or setter (make our implementation match other browsers).
+
+        * interpreter/Interpreter.cpp:
+        (JSC::getCallerInfo):
+            - Allow this to get the caller of host functions.
+        (JSC::Interpreter::retrieveCallerFromVMCode):
+            - This should use getCallerInfo, and should skip over function bindings.
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::callerGetter):
+            - This should never return a strict-mode function.
+
 2012-03-01  Yuqiang Xian  <[email protected]>
 
         DFG local CSE for a node can be terminated earlier

Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (109460 => 109461)


--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2012-03-02 00:11:16 UTC (rev 109460)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2012-03-02 00:12:58 UTC (rev 109461)
@@ -44,6 +44,7 @@
 #include "GetterSetter.h"
 #include "JSActivation.h"
 #include "JSArray.h"
+#include "JSBoundFunction.h"
 #include "JSByteArray.h"
 #include "JSNotAnObject.h"
 #include "JSPropertyNameIterator.h"
@@ -845,7 +846,7 @@
     unsigned bytecodeOffset = 0;
     lineNumber = -1;
     ASSERT(!callFrame->hasHostCallFrameFlag());
-    CallFrame* callerFrame = callFrame->codeBlock() ? callFrame->trueCallerFrame() : 0;
+    CallFrame* callerFrame = callFrame->codeBlock() ? callFrame->trueCallerFrame() : callFrame->callerFrame()->removeHostCallFrameFlag();
     bool callframeIsHost = callerFrame->addHostCallFrameFlag() == callFrame->callerFrame();
     ASSERT(!callerFrame->hasHostCallFrameFlag());
 
@@ -5301,18 +5302,29 @@
 JSValue Interpreter::retrieveCallerFromVMCode(CallFrame* callFrame, JSFunction* function) const
 {
     CallFrame* functionCallFrame = findFunctionCallFrameFromVMCode(callFrame, function);
+
     if (!functionCallFrame)
         return jsNull();
     
-    if (functionCallFrame->callerFrame()->hasHostCallFrameFlag())
+    int lineNumber;
+    CallFrame* callerFrame = getCallerInfo(&callFrame->globalData(), functionCallFrame, lineNumber);
+    if (!callerFrame)
         return jsNull();
-
-    CallFrame* callerFrame = functionCallFrame->trueCallerFrame();
-
     JSValue caller = callerFrame->callee();
     if (!caller)
         return jsNull();
 
+    // Skip over function bindings.
+    ASSERT(caller.isObject());
+    while (asObject(caller)->inherits(&JSBoundFunction::s_info)) {
+        callerFrame = getCallerInfo(&callFrame->globalData(), callerFrame, lineNumber);
+        if (!callerFrame)
+            return jsNull();
+        caller = callerFrame->callee();
+        if (!caller)
+            return jsNull();
+    }
+
     return caller;
 }
 

Modified: trunk/Source/_javascript_Core/runtime/JSFunction.cpp (109460 => 109461)


--- trunk/Source/_javascript_Core/runtime/JSFunction.cpp	2012-03-02 00:11:16 UTC (rev 109460)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.cpp	2012-03-02 00:12:58 UTC (rev 109461)
@@ -181,7 +181,15 @@
 {
     JSFunction* thisObj = asFunction(slotBase);
     ASSERT(!thisObj->isHostFunction());
-    return exec->interpreter()->retrieveCallerFromVMCode(exec, thisObj);
+    JSValue caller = exec->interpreter()->retrieveCallerFromVMCode(exec, thisObj);
+
+    // See ES5.1 15.3.5.4 - Function.caller may not be used to retrieve a strict caller.
+    if (!caller.isObject() || !asObject(caller)->inherits(&JSFunction::s_info))
+        return caller;
+    JSFunction* function = asFunction(caller);
+    if (function->isHostFunction() || !function->jsExecutable()->isStrictMode())
+        return caller;
+    return throwTypeError(exec, "Function.caller used to retrieve strict caller");
 }
 
 JSValue JSFunction::lengthGetter(ExecState*, JSValue slotBase, const Identifier&)
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to