Revision: 15963
Author:   [email protected]
Date:     Tue Jul 30 10:05:50 2013
Log:      Pipe a script's CORS status through V8 during compilation.

In order to properly sanitize exception data during a 'window.onerror'
handler, we need to know whether a script was served with proper CORS
headers at the time it was loaded into V8. This patch adds a single bool
to ScriptOrigin, and pipes that through the compiler to land on the
Script object. We can then retrieve the parameter when calling the
embedder's exception callback.

BUG=crbug.com/159566
[email protected]

Review URL: https://codereview.chromium.org/20646006

Patch from Mike West <[email protected]>.
http://code.google.com/p/v8/source/detail?r=15963

Modified:
 /branches/bleeding_edge/include/v8.h
 /branches/bleeding_edge/src/api.cc
 /branches/bleeding_edge/src/bootstrapper.cc
 /branches/bleeding_edge/src/compilation-cache.cc
 /branches/bleeding_edge/src/compilation-cache.h
 /branches/bleeding_edge/src/compiler.cc
 /branches/bleeding_edge/src/compiler.h
 /branches/bleeding_edge/src/debug.cc
 /branches/bleeding_edge/src/objects-inl.h
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/test/cctest/test-api.cc
 /branches/bleeding_edge/test/cctest/test-compiler.cc

=======================================
--- /branches/bleeding_edge/include/v8.h        Tue Jul 30 00:05:15 2013
+++ /branches/bleeding_edge/include/v8.h        Tue Jul 30 10:05:50 2013
@@ -942,17 +942,21 @@
   V8_INLINE(ScriptOrigin(
       Handle<Value> resource_name,
       Handle<Integer> resource_line_offset = Handle<Integer>(),
-      Handle<Integer> resource_column_offset = Handle<Integer>()))
+      Handle<Integer> resource_column_offset = Handle<Integer>(),
+      Handle<Boolean> resource_is_shared_cross_origin = Handle<Boolean>()))
       : resource_name_(resource_name),
         resource_line_offset_(resource_line_offset),
-        resource_column_offset_(resource_column_offset) { }
+        resource_column_offset_(resource_column_offset),
+ resource_is_shared_cross_origin_(resource_is_shared_cross_origin) { }
   V8_INLINE(Handle<Value> ResourceName() const);
   V8_INLINE(Handle<Integer> ResourceLineOffset() const);
   V8_INLINE(Handle<Integer> ResourceColumnOffset() const);
+  V8_INLINE(Handle<Boolean> ResourceIsSharedCrossOrigin() const);
  private:
   Handle<Value> resource_name_;
   Handle<Integer> resource_line_offset_;
   Handle<Integer> resource_column_offset_;
+  Handle<Boolean> resource_is_shared_cross_origin_;
 };


@@ -1130,6 +1134,12 @@
    */
   int GetEndColumn() const;

+  /**
+ * Passes on the value set by the embedder when it fed the script from which
+   * this Message was generated to V8.
+   */
+  bool IsSharedCrossOrigin() const;
+
   // TODO(1245381): Print to a string instead of on a FILE.
   static void PrintCurrentStackTrace(FILE* out);

@@ -5995,6 +6005,10 @@
 Handle<Integer> ScriptOrigin::ResourceColumnOffset() const {
   return resource_column_offset_;
 }
+
+Handle<Boolean> ScriptOrigin::ResourceIsSharedCrossOrigin() const {
+  return resource_is_shared_cross_origin_;
+}


 Handle<Boolean> Boolean::New(bool value) {
=======================================
--- /branches/bleeding_edge/src/api.cc  Tue Jul 30 01:35:48 2013
+++ /branches/bleeding_edge/src/api.cc  Tue Jul 30 10:05:50 2013
@@ -1918,6 +1918,7 @@
     i::Handle<i::Object> name_obj;
     int line_offset = 0;
     int column_offset = 0;
+    bool is_shared_cross_origin = false;
     if (origin != NULL) {
       if (!origin->ResourceName().IsEmpty()) {
         name_obj = Utils::OpenHandle(*origin->ResourceName());
@@ -1929,6 +1930,10 @@
         column_offset =
             static_cast<int>(origin->ResourceColumnOffset()->Value());
       }
+      if (!origin->ResourceIsSharedCrossOrigin().IsEmpty()) {
+        is_shared_cross_origin =
+            origin->ResourceIsSharedCrossOrigin() == v8::True();
+      }
     }
     EXCEPTION_PREAMBLE(isolate);
     i::ScriptDataImpl* pre_data_impl =
@@ -1945,6 +1950,7 @@
                            name_obj,
                            line_offset,
                            column_offset,
+                           is_shared_cross_origin,
                            isolate->global_context(),
                            NULL,
                            pre_data_impl,
@@ -2410,6 +2416,20 @@
   int end = message->end_position();
   return static_cast<int>(start_col_obj->Number()) + (end - start);
 }
+
+
+bool Message::IsSharedCrossOrigin() const {
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::Message::IsSharedCrossOrigin()")) return 0;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
+  i::Handle<i::JSMessageObject> message =
+      i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
+  i::Handle<i::JSValue> script =
+      i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script(),
+                                                       isolate));
+  return i::Script::cast(script->value())->is_shared_cross_origin();
+}


 Local<String> Message::GetSourceLine() const {
=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Tue Jul 30 09:33:08 2013
+++ /branches/bleeding_edge/src/bootstrapper.cc Tue Jul 30 10:05:50 2013
@@ -1525,6 +1525,7 @@
         script_name,
         0,
         0,
+        false,
         top_context,
         extension,
         NULL,
=======================================
--- /branches/bleeding_edge/src/compilation-cache.cc Fri Jul 5 02:52:11 2013 +++ /branches/bleeding_edge/src/compilation-cache.cc Tue Jul 30 10:05:50 2013
@@ -144,7 +144,8 @@
     Handle<SharedFunctionInfo> function_info,
     Handle<Object> name,
     int line_offset,
-    int column_offset) {
+    int column_offset,
+    bool is_shared_cross_origin) {
   Handle<Script> script =
       Handle<Script>(Script::cast(function_info->script()), isolate());
   // If the script name isn't set, the boilerplate script should have
@@ -157,6 +158,8 @@
   if (column_offset != script->column_offset()->value()) return false;
   // Check that both names are strings. If not, no match.
   if (!name->IsString() || !script->name()->IsString()) return false;
+  // Were both scripts tagged by the embedder as being shared cross-origin?
+ if (is_shared_cross_origin != script->is_shared_cross_origin()) return false;
   // Compare the two name strings for equality.
   return String::cast(*name)->Equals(String::cast(script->name()));
 }
@@ -171,6 +174,7 @@
     Handle<Object> name,
     int line_offset,
     int column_offset,
+    bool is_shared_cross_origin,
     Handle<Context> context) {
   Object* result = NULL;
   int generation;
@@ -186,7 +190,11 @@
             Handle<SharedFunctionInfo>::cast(probe);
         // Break when we've found a suitable shared function info that
         // matches the origin.
-        if (HasOrigin(function_info, name, line_offset, column_offset)) {
+        if (HasOrigin(function_info,
+                      name,
+                      line_offset,
+                      column_offset,
+                      is_shared_cross_origin)) {
           result = *function_info;
           break;
         }
@@ -214,7 +222,11 @@
   if (result != NULL) {
     Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result),
                                       isolate());
-    ASSERT(HasOrigin(shared, name, line_offset, column_offset));
+    ASSERT(HasOrigin(shared,
+                     name,
+                     line_offset,
+                     column_offset,
+                     is_shared_cross_origin));
     // If the script was found in a later generation, we promote it to
     // the first generation to let it survive longer in the cache.
     if (generation != 0) Put(source, context, shared);
@@ -391,12 +403,18 @@
     Handle<Object> name,
     int line_offset,
     int column_offset,
+    bool is_shared_cross_origin,
     Handle<Context> context) {
   if (!IsEnabled()) {
     return Handle<SharedFunctionInfo>::null();
   }

-  return script_.Lookup(source, name, line_offset, column_offset, context);
+  return script_.Lookup(source,
+                        name,
+                        line_offset,
+                        column_offset,
+                        is_shared_cross_origin,
+                        context);
 }


=======================================
--- /branches/bleeding_edge/src/compilation-cache.h     Tue Aug 28 03:49:23 2012
+++ /branches/bleeding_edge/src/compilation-cache.h     Tue Jul 30 10:05:50 2013
@@ -99,6 +99,7 @@
                                     Handle<Object> name,
                                     int line_offset,
                                     int column_offset,
+                                    bool is_shared_cross_origin,
                                     Handle<Context> context);
   void Put(Handle<String> source,
            Handle<Context> context,
@@ -119,7 +120,8 @@
   bool HasOrigin(Handle<SharedFunctionInfo> function_info,
                  Handle<Object> name,
                  int line_offset,
-                 int column_offset);
+                 int column_offset,
+                 bool is_shared_cross_origin);

   void* script_histogram_;
   bool script_histogram_initialized_;
@@ -212,6 +214,7 @@
                                           Handle<Object> name,
                                           int line_offset,
                                           int column_offset,
+                                          bool is_shared_cross_origin,
                                           Handle<Context> context);

   // Finds the shared function info for a source string for eval in a
=======================================
--- /branches/bleeding_edge/src/compiler.cc     Tue Jul 30 10:00:05 2013
+++ /branches/bleeding_edge/src/compiler.cc     Tue Jul 30 10:05:50 2013
@@ -667,6 +667,7 @@
                                              Handle<Object> script_name,
                                              int line_offset,
                                              int column_offset,
+                                             bool is_shared_cross_origin,
                                              Handle<Context> context,
                                              v8::Extension* extension,
                                              ScriptDataImpl* pre_data,
@@ -689,6 +690,7 @@
                                              script_name,
                                              line_offset,
                                              column_offset,
+                                             is_shared_cross_origin,
                                              context);
   }

@@ -712,6 +714,7 @@
       script->set_line_offset(Smi::FromInt(line_offset));
       script->set_column_offset(Smi::FromInt(column_offset));
     }
+    script->set_is_shared_cross_origin(is_shared_cross_origin);

     script->set_data(script_data.is_null() ? HEAP->undefined_value()
                                            : *script_data);
=======================================
--- /branches/bleeding_edge/src/compiler.h      Wed Jul 17 01:44:10 2013
+++ /branches/bleeding_edge/src/compiler.h      Tue Jul 30 10:05:50 2013
@@ -572,6 +572,7 @@
                                             Handle<Object> script_name,
                                             int line_offset,
                                             int column_offset,
+                                            bool is_shared_cross_origin,
                                             Handle<Context> context,
                                             v8::Extension* extension,
                                             ScriptDataImpl* pre_data,
=======================================
--- /branches/bleeding_edge/src/debug.cc        Tue Jul 30 01:35:48 2013
+++ /branches/bleeding_edge/src/debug.cc        Tue Jul 30 10:05:50 2013
@@ -786,6 +786,7 @@
   function_info = Compiler::Compile(source_code,
                                     script_name,
                                     0, 0,
+                                    false,
                                     context,
                                     NULL, NULL,
                                     Handle<String>::null(),
=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Tue Jul 30 10:00:05 2013
+++ /branches/bleeding_edge/src/objects-inl.h   Tue Jul 30 10:05:50 2013
@@ -4499,6 +4499,7 @@
 ACCESSORS_TO_SMI(Script, eval_from_instructions_offset,
                  kEvalFrominstructionsOffsetOffset)
 ACCESSORS_TO_SMI(Script, flags, kFlagsOffset)
+BOOL_ACCESSORS(Script, flags, is_shared_cross_origin, kIsSharedCrossOriginBit)

 Script::CompilationType Script::compilation_type() {
   return BooleanBit::get(flags(), kCompilationTypeBit) ?
=======================================
--- /branches/bleeding_edge/src/objects.h       Tue Jul 30 10:00:05 2013
+++ /branches/bleeding_edge/src/objects.h       Tue Jul 30 10:05:50 2013
@@ -5876,6 +5876,12 @@
   inline CompilationState compilation_state();
   inline void set_compilation_state(CompilationState state);

+  // [is_shared_cross_origin]: An opaque boolean set by the embedder via
+  // ScriptOrigin, and used by the embedder to make decisions about the
+  // script's level of privilege. V8 just passes this through. Encoded in
+  // the 'flags' field.
+  DECL_BOOLEAN_ACCESSORS(is_shared_cross_origin)
+
   static inline Script* cast(Object* obj);

   // If script source is an external string, check that the underlying
@@ -5907,6 +5913,7 @@
   // Bit positions in the flags field.
   static const int kCompilationTypeBit = 0;
   static const int kCompilationStateBit = 1;
+  static const int kIsSharedCrossOriginBit = 2;

   DISALLOW_IMPLICIT_CONSTRUCTORS(Script);
 };
=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc     Tue Jul 30 00:05:15 2013
+++ /branches/bleeding_edge/test/cctest/test-api.cc     Tue Jul 30 10:05:50 2013
@@ -3565,6 +3565,7 @@
   CHECK_EQ(5.76, data->NumberValue());
   CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
   CHECK_EQ(7.56, message->GetScriptData()->NumberValue());
+  CHECK(!message->IsSharedCrossOrigin());
   message_received = true;
 }

@@ -3591,6 +3592,7 @@
                             v8::Handle<Value> data) {
   CHECK(data->IsNumber());
   CHECK_EQ(1337, data->Int32Value());
+  CHECK(!message->IsSharedCrossOrigin());
   message_received = true;
 }

@@ -3615,6 +3617,7 @@
   v8::Local<v8::Value> hidden_property =
       v8::Object::Cast(*data)->GetHiddenValue(v8_str("hidden key"));
   CHECK(v8_str("hidden value")->Equals(hidden_property));
+  CHECK(!message->IsSharedCrossOrigin());
   message_received = true;
 }

@@ -3634,6 +3637,112 @@
   // clear out the message listener
   v8::V8::RemoveMessageListeners(check_message_2);
 }
+
+
+static void check_message_3(v8::Handle<v8::Message> message,
+                            v8::Handle<Value> data) {
+  CHECK(message->IsSharedCrossOrigin());
+  CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
+  message_received = true;
+}
+
+
+TEST(MessageHandler3) {
+  message_received = false;
+  v8::HandleScope scope(v8::Isolate::GetCurrent());
+  CHECK(!message_received);
+  v8::V8::AddMessageListener(check_message_3);
+  LocalContext context;
+  v8::ScriptOrigin origin =
+      v8::ScriptOrigin(v8_str("6.75"),
+                       v8::Integer::New(1),
+                       v8::Integer::New(2),
+                       v8::True());
+  v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
+                                                  &origin);
+  script->Run();
+  CHECK(message_received);
+  // clear out the message listener
+  v8::V8::RemoveMessageListeners(check_message_3);
+}
+
+
+static void check_message_4(v8::Handle<v8::Message> message,
+                            v8::Handle<Value> data) {
+  CHECK(!message->IsSharedCrossOrigin());
+  CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
+  message_received = true;
+}
+
+
+TEST(MessageHandler4) {
+  message_received = false;
+  v8::HandleScope scope(v8::Isolate::GetCurrent());
+  CHECK(!message_received);
+  v8::V8::AddMessageListener(check_message_4);
+  LocalContext context;
+  v8::ScriptOrigin origin =
+      v8::ScriptOrigin(v8_str("6.75"),
+                       v8::Integer::New(1),
+                       v8::Integer::New(2),
+                       v8::False());
+  v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
+                                                  &origin);
+  script->Run();
+  CHECK(message_received);
+  // clear out the message listener
+  v8::V8::RemoveMessageListeners(check_message_4);
+}
+
+
+static void check_message_5a(v8::Handle<v8::Message> message,
+                            v8::Handle<Value> data) {
+  CHECK(message->IsSharedCrossOrigin());
+  CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
+  message_received = true;
+}
+
+
+static void check_message_5b(v8::Handle<v8::Message> message,
+                            v8::Handle<Value> data) {
+  CHECK(!message->IsSharedCrossOrigin());
+  CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
+  message_received = true;
+}
+
+
+TEST(MessageHandler5) {
+  message_received = false;
+  v8::HandleScope scope(v8::Isolate::GetCurrent());
+  CHECK(!message_received);
+  v8::V8::AddMessageListener(check_message_5a);
+  LocalContext context;
+  v8::ScriptOrigin origin =
+      v8::ScriptOrigin(v8_str("6.75"),
+                       v8::Integer::New(1),
+                       v8::Integer::New(2),
+                       v8::True());
+  v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
+                                                  &origin);
+  script->Run();
+  CHECK(message_received);
+  // clear out the message listener
+  v8::V8::RemoveMessageListeners(check_message_5a);
+
+  message_received = false;
+  v8::V8::AddMessageListener(check_message_5b);
+  origin =
+      v8::ScriptOrigin(v8_str("6.75"),
+                       v8::Integer::New(1),
+                       v8::Integer::New(2),
+                       v8::False());
+  script = Script::Compile(v8_str("throw 'error'"),
+                           &origin);
+  script->Run();
+  CHECK(message_received);
+  // clear out the message listener
+  v8::V8::RemoveMessageListeners(check_message_5b);
+}


 THREADED_TEST(GetSetProperty) {
=======================================
--- /branches/bleeding_edge/test/cctest/test-compiler.cc Tue Jun 25 04:16:13 2013 +++ /branches/bleeding_edge/test/cctest/test-compiler.cc Tue Jul 30 10:05:50 2013
@@ -105,6 +105,7 @@
                         Handle<String>(),
                         0,
                         0,
+                        false,
                         Handle<Context>(isolate->native_context()),
                         NULL,
                         NULL,

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to