From 7346fbba81321b61049b881687321d4599a993ab Mon Sep 17 00:00:00 2001 From: "mmaly@chromium.org" Date: Wed, 23 Mar 2011 03:45:48 +0000 Subject: [PATCH] Implement poison pill for non-strict mode function.caller when caller is strict mode function. Review URL: http://codereview.chromium.org/6713059/ git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7313 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/accessors.cc | 17 +++++++++++++-- src/messages.js | 1 + test/mjsunit/strict-mode.js | 51 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/src/accessors.cc b/src/accessors.cc index 7326aed..af344d1 100644 --- a/src/accessors.cc +++ b/src/accessors.cc @@ -827,6 +827,19 @@ const AccessorDescriptor Accessors::FunctionArguments = { // +static MaybeObject* CheckNonStrictCallerOrThrow( + Isolate* isolate, + JSFunction* caller) { + DisableAssertNoAllocation enable_allocation; + if (caller->shared()->strict_mode()) { + return isolate->Throw( + *isolate->factory()->NewTypeError("strict_caller", + HandleVector(NULL, 0))); + } + return caller; +} + + MaybeObject* Accessors::FunctionGetCaller(Object* object, void*) { Isolate* isolate = Isolate::Current(); HandleScope scope(isolate); @@ -847,14 +860,14 @@ MaybeObject* Accessors::FunctionGetCaller(Object* object, void*) { // frames, e.g. frames for scripts not functions. if (i > 0) { ASSERT(!functions[i - 1]->shared()->is_toplevel()); - return functions[i - 1]; + return CheckNonStrictCallerOrThrow(isolate, functions[i - 1]); } else { for (it.Advance(); !it.done(); it.Advance()) { frame = it.frame(); functions.Rewind(0); frame->GetFunctions(&functions); if (!functions.last()->shared()->is_toplevel()) { - return functions.last(); + return CheckNonStrictCallerOrThrow(isolate, functions.last()); } ASSERT(functions.length() == 1); } diff --git a/src/messages.js b/src/messages.js index 2ba12fd..3eb056f 100644 --- a/src/messages.js +++ b/src/messages.js @@ -234,6 +234,7 @@ function FormatMessage(message) { strict_arguments_caller: ["Cannot access property 'caller' of strict mode arguments"], strict_function_caller: ["Cannot access property 'caller' of a strict mode function"], strict_function_arguments: ["Cannot access property 'arguments' of a strict mode function"], + strict_caller: ["Illegal access to a strict mode caller function."], }; } var message_type = %MessageGetType(message); diff --git a/test/mjsunit/strict-mode.js b/test/mjsunit/strict-mode.js index e8f6e1c..1f7666f 100644 --- a/test/mjsunit/strict-mode.js +++ b/test/mjsunit/strict-mode.js @@ -1081,3 +1081,54 @@ function CheckPillDescriptor(func, name) { CheckPillDescriptor(args, "caller"); CheckPillDescriptor(args, "callee"); })(); + + +(function TestNonStrictFunctionCallerPillSimple() { + function return_my_caller() { + return return_my_caller.caller; + } + + function strict() { + "use strict"; + return_my_caller(); + } + assertThrows(strict, TypeError); + + function non_strict() { + return return_my_caller(); + } + assertSame(non_strict(), non_strict); +})(); + + +(function TestNonStrictFunctionCallerPill() { + function strict(n) { + "use strict"; + non_strict(n); + } + + function recurse(n, then) { + if (n > 0) { + recurse(n - 1); + } else { + return then(); + } + } + + function non_strict(n) { + recurse(n, function() { non_strict.caller; }); + } + + function test(n) { + try { + recurse(n, function() { strict(n); }); + } catch(e) { + return e instanceof TypeError; + } + return false; + } + + for (var i = 0; i < 10; i ++) { + assertEquals(test(i), true); + } +})(); -- 2.7.4