From eee93ec99bfd38336fdd507b7dd21b015e7ba88a Mon Sep 17 00:00:00 2001 From: "yurys@chromium.org" Date: Mon, 15 Oct 2012 10:15:25 +0000 Subject: [PATCH] Allow evals for debugger even if they are prohibited in the debugee context. BUG=154733 Review URL: https://codereview.chromium.org/11111015 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12726 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/runtime.cc | 13 +++++++ test/cctest/test-debug.cc | 94 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 106 insertions(+), 1 deletion(-) diff --git a/src/runtime.cc b/src/runtime.cc index cd77c00..356b6fc 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -11793,6 +11793,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { scope_info, function_context); + // Check if eval is blocked in the context and temporarily allow it + // for debugger. + Handle native_context = Handle(context->native_context()); + bool eval_disabled = + native_context->allow_code_gen_from_strings()->IsFalse(); + if (eval_disabled) { + native_context->set_allow_code_gen_from_strings( + isolate->heap()->true_value()); + } // Invoke the evaluation function and return the result. Handle argv[] = { arguments, source }; Handle result = @@ -11801,6 +11810,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { ARRAY_SIZE(argv), argv, &has_pending_exception); + if (eval_disabled) { + native_context->set_allow_code_gen_from_strings( + isolate->heap()->false_value()); + } if (has_pending_exception) return Failure::Exception(); // Skip the global proxy as it has no properties and always delegates to the diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc index e00ad5a..f2253e3 100644 --- a/test/cctest/test-debug.cc +++ b/test/cctest/test-debug.cc @@ -2381,7 +2381,7 @@ TEST(DebuggerStatementBreakpoint) { } -// Thest that the evaluation of expressions when a break point is hit generates +// Test that the evaluation of expressions when a break point is hit generates // the correct results. TEST(DebugEvaluate) { v8::HandleScope scope; @@ -2497,6 +2497,98 @@ TEST(DebugEvaluate) { CheckDebuggerUnloaded(); } + +int debugEventCount = 0; +static void CheckDebugEvent(const v8::Debug::EventDetails& eventDetails) { + if (eventDetails.GetEvent() == v8::Break) ++debugEventCount; +} + +// Test that the conditional breakpoints work event if code generation from +// strings is prohibited in the debugee context. +TEST(ConditionalBreakpointWithCodeGenerationDisallowed) { + v8::HandleScope scope; + DebugLocalContext env; + env.ExposeDebug(); + + v8::Debug::SetDebugEventListener2(CheckDebugEvent); + + v8::Local foo = CompileFunction(&env, + "function foo(x) {\n" + " var s = 'String value2';\n" + " return s + x;\n" + "}", + "foo"); + + // Set conditional breakpoint with condition 'true'. + CompileRun("debug.Debug.setBreakPoint(foo, 2, 0, 'true')"); + + debugEventCount = 0; + env->AllowCodeGenerationFromStrings(false); + foo->Call(env->Global(), 0, NULL); + CHECK_EQ(1, debugEventCount); + + v8::Debug::SetDebugEventListener2(NULL); + CheckDebuggerUnloaded(); +} + + +bool checkedDebugEvals = true; +v8::Handle checkGlobalEvalFunction; +v8::Handle checkFrameEvalFunction; +static void CheckDebugEval(const v8::Debug::EventDetails& eventDetails) { + if (eventDetails.GetEvent() == v8::Break) { + ++debugEventCount; + v8::HandleScope handleScope; + + v8::Handle args[] = { eventDetails.GetExecutionState() }; + CHECK(checkGlobalEvalFunction->Call( + eventDetails.GetEventContext()->Global(), 1, args)->IsTrue()); + CHECK(checkFrameEvalFunction->Call( + eventDetails.GetEventContext()->Global(), 1, args)->IsTrue()); + } +} + +// Test that the evaluation of expressions when a break point is hit generates +// the correct results in case code generation from strings is disallowed in the +// debugee context. +TEST(DebugEvaluateWithCodeGenerationDisallowed) { + v8::HandleScope scope; + DebugLocalContext env; + env.ExposeDebug(); + + v8::Debug::SetDebugEventListener2(CheckDebugEval); + + v8::Local foo = CompileFunction(&env, + "var global = 'Global';\n" + "function foo(x) {\n" + " var local = 'Local';\n" + " debugger;\n" + " return local + x;\n" + "}", + "foo"); + checkGlobalEvalFunction = CompileFunction(&env, + "function checkGlobalEval(exec_state) {\n" + " return exec_state.evaluateGlobal('global').value() === 'Global';\n" + "}", + "checkGlobalEval"); + + checkFrameEvalFunction = CompileFunction(&env, + "function checkFrameEval(exec_state) {\n" + " return exec_state.frame(0).evaluate('local').value() === 'Local';\n" + "}", + "checkFrameEval"); + debugEventCount = 0; + env->AllowCodeGenerationFromStrings(false); + foo->Call(env->Global(), 0, NULL); + CHECK_EQ(1, debugEventCount); + + checkGlobalEvalFunction.Clear(); + checkFrameEvalFunction.Clear(); + v8::Debug::SetDebugEventListener2(NULL); + CheckDebuggerUnloaded(); +} + + // Copies a C string to a 16-bit string. Does not check for buffer overflow. // Does not use the V8 engine to convert strings, so it can be used // in any thread. Returns the length of the string. -- 2.7.4