Throw a more descriptive exception when blocking 'eval' via CSP.
authorulan@chromium.org <ulan@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 17 Sep 2012 09:58:22 +0000 (09:58 +0000)
committerulan@chromium.org <ulan@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 17 Sep 2012 09:58:22 +0000 (09:58 +0000)
BUG=140191

R=svenpanne@chromium.org,mkwst@chromium.org

Review URL: https://chromiumcodereview.appspot.com/10837358

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12525 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

include/v8.h
src/api.cc
src/contexts.cc
src/contexts.h
src/messages.js
src/runtime.cc
test/cctest/test-api.cc

index 850ebe442b982d6381cefe7cebd3fa472b094c2d..92d928b328822aaec30f9b2dc421aa2a42050d56 100644 (file)
@@ -3742,6 +3742,13 @@ class V8EXPORT Context {
    */
   bool IsCodeGenerationFromStringsAllowed();
 
+  /**
+   * Sets the error description for the exception that is thrown when
+   * code generation from strings is not allowed and 'eval' or the 'Function'
+   * constructor are called.
+   */
+  void SetErrorMessageForCodeGenerationFromStrings(Handle<String> message);
+
   /**
    * Stack-allocated class which sets the execution context for all
    * operations executed within a local scope.
index 87692ed0015a81ba08a2409b42c13103e8e37ba6..dcadf52a6a64dcb2a6022fbbe80a10fff2d3ad33 100644 (file)
@@ -4599,6 +4599,22 @@ bool Context::IsCodeGenerationFromStringsAllowed() {
 }
 
 
+void Context::SetErrorMessageForCodeGenerationFromStrings(
+    Handle<String> error) {
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate,
+      "v8::Context::SetErrorMessageForCodeGenerationFromStrings()")) {
+    return;
+  }
+  ENTER_V8(isolate);
+  i::Object** ctx = reinterpret_cast<i::Object**>(this);
+  i::Handle<i::Context> context =
+      i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
+  i::Handle<i::Object> error_handle = Utils::OpenHandle(*error);
+  context->set_error_message_for_code_gen_from_strings(*error_handle);
+}
+
+
 void V8::SetWrapperClassId(i::Object** global_handle, uint16_t class_id) {
   i::GlobalHandles::SetWrapperClassId(global_handle, class_id);
 }
index 169d9a12232772a523145e2b3c45db186f02bb1e..93c9795404bb52690c6cc3c4e1b560b4f9a076c6 100644 (file)
@@ -305,6 +305,18 @@ void Context::ClearOptimizedFunctions() {
 }
 
 
+Handle<Object> Context::ErrorMessageForCodeGenerationFromStrings() {
+  Handle<Object> result(error_message_for_code_gen_from_strings());
+  if (result->IsUndefined()) {
+    const char* error =
+        "Code generation from strings disallowed for this context";
+    Isolate* isolate = Isolate::Current();
+    result = isolate->factory()->NewStringFromAscii(i::CStrVector(error));
+  }
+  return result;
+}
+
+
 #ifdef DEBUG
 bool Context::IsBootstrappingOrValidParentContext(
     Object* object, Context* child) {
index cfc576cecb6fedb6d83d893650824f39ed55cccf..28e4af53682b2fa6a55623914720d7939bbd0285 100644 (file)
@@ -154,6 +154,8 @@ enum BindingFlags {
   V(MAP_CACHE_INDEX, Object, map_cache) \
   V(CONTEXT_DATA_INDEX, Object, data) \
   V(ALLOW_CODE_GEN_FROM_STRINGS_INDEX, Object, allow_code_gen_from_strings) \
+  V(ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX, Object, \
+    error_message_for_code_gen_from_strings) \
   V(TO_COMPLETE_PROPERTY_DESCRIPTOR_INDEX, JSFunction, \
     to_complete_property_descriptor) \
   V(DERIVED_HAS_TRAP_INDEX, JSFunction, derived_has_trap) \
@@ -281,6 +283,7 @@ class Context: public FixedArray {
     OUT_OF_MEMORY_INDEX,
     CONTEXT_DATA_INDEX,
     ALLOW_CODE_GEN_FROM_STRINGS_INDEX,
+    ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX,
     TO_COMPLETE_PROPERTY_DESCRIPTOR_INDEX,
     DERIVED_HAS_TRAP_INDEX,
     DERIVED_GET_TRAP_INDEX,
@@ -381,6 +384,8 @@ class Context: public FixedArray {
   Object* OptimizedFunctionsListHead();
   void ClearOptimizedFunctions();
 
+  Handle<Object> ErrorMessageForCodeGenerationFromStrings();
+
 #define NATIVE_CONTEXT_FIELD_ACCESSORS(index, type, name) \
   void  set_##name(type* value) {                         \
     ASSERT(IsNativeContext());                            \
index b819724a1034957e0422da4deb6fd8176db5140f..4b389a085b1ef44360b59d8790f80762c09dc02d 100644 (file)
@@ -140,7 +140,7 @@ function FormatMessage(message) {
     var messagesDictionary = [
       // Error
       "cyclic_proto",                 ["Cyclic __proto__ value"],
-      "code_gen_from_strings",        ["Code generation from strings disallowed for this context"],
+      "code_gen_from_strings",        ["%0"],
       // TypeError
       "unexpected_token",             ["Unexpected token ", "%0"],
       "unexpected_token_number",      ["Unexpected number"],
index ab462490e193fc78d76279939cc3f4678edfcc59..b822814744517f08e268521602b2327d74cde14a 100644 (file)
@@ -9061,8 +9061,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
   // strings. Throw an exception if it doesn't.
   if (context->allow_code_gen_from_strings()->IsFalse() &&
       !CodeGenerationFromStringsAllowed(isolate, context)) {
-    return isolate->Throw(*isolate->factory()->NewError(
-        "code_gen_from_strings", HandleVector<Object>(NULL, 0)));
+    Handle<Object> error_message =
+        context->ErrorMessageForCodeGenerationFromStrings();
+    return isolate->Throw(*isolate->factory()->NewEvalError(
+        "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
   }
 
   // Compile source string in the native context.
@@ -9089,8 +9091,10 @@ static ObjectPair CompileGlobalEval(Isolate* isolate,
   // strings. Throw an exception if it doesn't.
   if (native_context->allow_code_gen_from_strings()->IsFalse() &&
       !CodeGenerationFromStringsAllowed(isolate, native_context)) {
-    isolate->Throw(*isolate->factory()->NewError(
-        "code_gen_from_strings", HandleVector<Object>(NULL, 0)));
+    Handle<Object> error_message =
+        context->ErrorMessageForCodeGenerationFromStrings();
+    isolate->Throw(*isolate->factory()->NewEvalError(
+        "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
     return MakePair(Failure::Exception(), NULL);
   }
 
index 18025e14a076210b454a8cc4bcc2e7a3dd9d8f47..7ba9e639ae26b994505959249561dcaa81575a0a 100644 (file)
@@ -16524,6 +16524,24 @@ THREADED_TEST(AllowCodeGenFromStrings) {
 }
 
 
+TEST(SetErrorMessageForCodeGenFromStrings) {
+  v8::HandleScope scope;
+  LocalContext context;
+  TryCatch try_catch;
+
+  Handle<String> message = v8_str("Message") ;
+  Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
+  V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
+  context->AllowCodeGenerationFromStrings(false);
+  context->SetErrorMessageForCodeGenerationFromStrings(message);
+  Handle<Value> result = CompileRun("eval('42')");
+  CHECK(result.IsEmpty());
+  CHECK(try_catch.HasCaught());
+  Handle<String> actual_message = try_catch.Message()->Get();
+  CHECK(expected_message->Equals(actual_message));
+}
+
+
 static v8::Handle<Value> NonObjectThis(const v8::Arguments& args) {
   return v8::Undefined();
 }