Author: [EMAIL PROTECTED]
Date: Wed Nov  5 00:37:42 2008
New Revision: 692

Modified:
    branches/0.3/include/v8.h
    branches/0.3/src/api.cc
    branches/0.3/src/apinatives.js
    branches/0.3/src/bootstrapper.cc
    branches/0.3/src/factory.cc
    branches/0.3/src/objects-inl.h
    branches/0.3/src/objects.cc
    branches/0.3/src/objects.h
    branches/0.3/src/runtime.cc
    branches/0.3/src/runtime.h
    branches/0.3/test/cctest/test-api.cc

Log:
Merge revision 656 from bleeding_edge to 0.3 branch (0.3.9).

Modified: branches/0.3/include/v8.h
==============================================================================
--- branches/0.3/include/v8.h   (original)
+++ branches/0.3/include/v8.h   Wed Nov  5 00:37:42 2008
@@ -1282,11 +1282,18 @@
   * Some accessors should be accessible across contexts.  These
   * accessors have an explicit access control parameter which specifies
   * the kind of cross-context access that should be allowed.
+ *
+ * Additionally, for security, accessors can prohibit overwriting by
+ * accessors defined in JavaScript.  For objects that have such
+ * accessors either locally or in their prototype chain it is not
+ * possible to overwrite the accessor by using __defineGetter__ or
+ * __defineSetter__ from JavaScript code.
   */
  enum AccessControl {
-  DEFAULT         = 0,
-  ALL_CAN_READ    = 1,
-  ALL_CAN_WRITE   = 2
+  DEFAULT               = 0,
+  ALL_CAN_READ          = 1,
+  ALL_CAN_WRITE         = 1 << 1,
+  PROHIBITS_OVERWRITING = 1 << 2
  };



Modified: branches/0.3/src/api.cc
==============================================================================
--- branches/0.3/src/api.cc     (original)
+++ branches/0.3/src/api.cc     Wed Nov  5 00:37:42 2008
@@ -711,6 +711,7 @@
    obj->set_name(*Utils::OpenHandle(*name));
    if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
    if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
+  if (settings & PROHIBITS_OVERWRITING)  
obj->set_prohibits_overwriting(true);
     
obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));

    i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors());
@@ -2222,7 +2223,7 @@


  const char* v8::V8::GetVersion() {
-  return "0.3.8.2";
+  return "0.3.9";
  }



Modified: branches/0.3/src/apinatives.js
==============================================================================
--- branches/0.3/src/apinatives.js      (original)
+++ branches/0.3/src/apinatives.js      Wed Nov  5 00:37:42 2008
@@ -82,12 +82,18 @@
  function ConfigureTemplateInstance(obj, data) {
    var properties = %GetTemplateField(data, kApiPropertyListOffset);
    if (properties) {
-    for (var i = 0; i < properties[0]; i += 3) {
-      var name = properties[i + 1];
-      var prop_data = properties[i + 2];
-      var attributes = properties[i + 3];
-      var value = Instantiate(prop_data, name);
-      %SetProperty(obj, name, value, attributes);
+    // Disable access checks while instantiating the object.
+    var requires_access_checks = %DisableAccessChecks(obj);
+    try {
+      for (var i = 0; i < properties[0]; i += 3) {
+        var name = properties[i + 1];
+        var prop_data = properties[i + 2];
+        var attributes = properties[i + 3];
+        var value = Instantiate(prop_data, name);
+        %SetProperty(obj, name, value, attributes);
+      }
+    } finally {
+      if (requires_access_checks) %EnableAccessChecks(obj);
      }
    }
  }

Modified: branches/0.3/src/bootstrapper.cc
==============================================================================
--- branches/0.3/src/bootstrapper.cc    (original)
+++ branches/0.3/src/bootstrapper.cc    Wed Nov  5 00:37:42 2008
@@ -531,7 +531,7 @@

      SetExpectedNofProperties(global_function, 100);
      global_function->shared()->set_instance_class_name(*global_name);
-    global_function->initial_map()->set_needs_access_check();
+    global_function->initial_map()->set_is_access_check_needed(true);

      Handle<JSGlobalObject> object;
      if (global_object.location() != NULL) {

Modified: branches/0.3/src/factory.cc
==============================================================================
--- branches/0.3/src/factory.cc (original)
+++ branches/0.3/src/factory.cc Wed Nov  5 00:37:42 2008
@@ -715,7 +715,7 @@

    // Mark as needs_access_check if needed.
    if (obj->needs_access_check()) {
-    map->set_needs_access_check();
+    map->set_is_access_check_needed(true);
    }

    // Set interceptor information in the map.

Modified: branches/0.3/src/objects-inl.h
==============================================================================
--- branches/0.3/src/objects-inl.h      (original)
+++ branches/0.3/src/objects-inl.h      Wed Nov  5 00:37:42 2008
@@ -408,7 +408,7 @@

  bool Object::IsAccessCheckNeeded() {
    return IsHeapObject()
-    && HeapObject::cast(this)->map()->needs_access_check();
+    && HeapObject::cast(this)->map()->is_access_check_needed();
  }


@@ -1667,6 +1667,20 @@
  }


+void Map::set_is_access_check_needed(bool access_check_needed) {
+  if (access_check_needed) {
+    set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
+  } else {
+    set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
+  }
+}
+
+
+bool Map::is_access_check_needed() {
+  return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
+}
+
+
  Code::Flags Code::flags() {
    return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
  }
@@ -2284,6 +2298,16 @@

  void AccessorInfo::set_all_can_write(bool value) {
    set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
+}
+
+
+bool AccessorInfo::prohibits_overwriting() {
+  return BooleanBit::get(flag(), kProhibitsOverwritingBit);
+}
+
+
+void AccessorInfo::set_prohibits_overwriting(bool value) {
+  set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
  }



Modified: branches/0.3/src/objects.cc
==============================================================================
--- branches/0.3/src/objects.cc (original)
+++ branches/0.3/src/objects.cc Wed Nov  5 00:37:42 2008
@@ -2213,9 +2213,19 @@
         current != Heap::null_value();
         current = JSObject::cast(current)->GetPrototype()) {
      JSObject::cast(current)->LocalLookup(name, result);
-    if (result->IsValid() && !result->IsTransitionType()) {
-      return;
-    }
+    if (result->IsValid() && !result->IsTransitionType()) return;
+  }
+  result->NotFound();
+}
+
+
+// Search object and it's prototype chain for callback properties.
+void JSObject::LookupCallback(String* name, LookupResult* result) {
+  for (Object* current = this;
+       current != Heap::null_value();
+       current = JSObject::cast(current)->GetPrototype()) {
+    JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
+    if (result->IsValid() && result->type() == CALLBACKS) return;
    }
    result->NotFound();
  }
@@ -2240,6 +2250,22 @@
    // Make sure name is not an index.
    uint32_t index;
    if (name->AsArrayIndex(&index)) return Heap::undefined_value();
+
+  // Check if there is an API defined callback object which prohibits
+  // callback overwriting in this object or it's prototype chain.
+  // This mechanism is needed for instance in a browser setting, where
+  // certain accessors such as window.location should not be allowed
+  // to be overwriten because allowing overwriting could potentially
+  // cause security problems.
+  LookupResult callback_result;
+  LookupCallback(name, &callback_result);
+  if (callback_result.IsValid()) {
+    Object* obj = callback_result.GetCallbackObject();
+    if (obj->IsAccessorInfo() &&
+        AccessorInfo::cast(obj)->prohibits_overwriting()) {
+      return Heap::undefined_value();
+    }
+  }

    // Lookup the name.
    LookupResult result;

Modified: branches/0.3/src/objects.h
==============================================================================
--- branches/0.3/src/objects.h  (original)
+++ branches/0.3/src/objects.h  Wed Nov  5 00:37:42 2008
@@ -1274,6 +1274,7 @@
    void LookupRealNamedProperty(String* name, LookupResult* result);
    void LookupRealNamedPropertyInPrototypes(String* name, LookupResult*  
result);
    void LookupCallbackSetterInPrototypes(String* name, LookupResult*  
result);
+  void LookupCallback(String* name, LookupResult* result);

    // Returns the number of properties on this object filtering out  
properties
    // with the specified attributes (ignoring interceptors).
@@ -2358,13 +2359,8 @@

    // Tells whether the instance needs security checks when accessing its
    // properties.
-  inline void set_needs_access_check() {
-    set_bit_field(bit_field() | (1 << kNeedsAccessCheck));
-  }
-
-  inline bool needs_access_check() {
-    return ((1 << kNeedsAccessCheck) & bit_field()) != 0;
-  }
+  inline void set_is_access_check_needed(bool access_check_needed);
+  inline bool is_access_check_needed();

    // [prototype]: implicit prototype object.
    DECL_ACCESSORS(prototype, Object)
@@ -2466,7 +2462,7 @@
    static const int kHasIndexedInterceptor = 4;
    static const int kIsUndetectable = 5;
    static const int kHasInstanceCallHandler = 6;
-  static const int kNeedsAccessCheck = 7;
+  static const int kIsAccessCheckNeeded = 7;
   private:
    DISALLOW_IMPLICIT_CONSTRUCTORS(Map);
  };
@@ -3679,6 +3675,9 @@
    inline bool all_can_write();
    inline void set_all_can_write(bool value);

+  inline bool prohibits_overwriting();
+  inline void set_prohibits_overwriting(bool value);
+
    inline PropertyAttributes property_attributes();
    inline void set_property_attributes(PropertyAttributes attributes);

@@ -3698,9 +3697,10 @@

   private:
    // Bit positions in flag.
-  static const int kAllCanReadBit  = 0;
+  static const int kAllCanReadBit = 0;
    static const int kAllCanWriteBit = 1;
-  class AttributesField: public BitField<PropertyAttributes, 2, 3> {};
+  static const int kProhibitsOverwritingBit = 2;
+  class AttributesField: public BitField<PropertyAttributes, 3, 3> {};

    DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorInfo);
  };

Modified: branches/0.3/src/runtime.cc
==============================================================================
--- branches/0.3/src/runtime.cc (original)
+++ branches/0.3/src/runtime.cc Wed Nov  5 00:37:42 2008
@@ -343,6 +343,23 @@
  }


+static Object* Runtime_DisableAccessChecks(Arguments args) {
+  ASSERT(args.length() == 1);
+  CONVERT_CHECKED(HeapObject, object, args[0]);
+  bool needs_access_checks = object->map()->is_access_check_needed();
+  object->map()->set_is_access_check_needed(false);
+  return needs_access_checks ? Heap::true_value() : Heap::false_value();
+}
+
+
+static Object* Runtime_EnableAccessChecks(Arguments args) {
+  ASSERT(args.length() == 1);
+  CONVERT_CHECKED(HeapObject, object, args[0]);
+  object->map()->set_is_access_check_needed(true);
+  return Heap::undefined_value();
+}
+
+
  static Object* ThrowRedeclarationError(const char* type, Handle<String>  
name) {
    HandleScope scope;
    Handle<Object> type_handle =  
Factory::NewStringFromAscii(CStrVector(type));

Modified: branches/0.3/src/runtime.h
==============================================================================
--- branches/0.3/src/runtime.h  (original)
+++ branches/0.3/src/runtime.h  Wed Nov  5 00:37:42 2008
@@ -180,6 +180,8 @@
    F(CreateApiFunction, 1) \
    F(IsTemplate, 1) \
    F(GetTemplateField, 2) \
+  F(DisableAccessChecks, 1) \
+  F(EnableAccessChecks, 1) \
    \
    /* Dates */ \
    F(DateCurrentTime, 0) \

Modified: branches/0.3/test/cctest/test-api.cc
==============================================================================
--- branches/0.3/test/cctest/test-api.cc        (original)
+++ branches/0.3/test/cctest/test-api.cc        Wed Nov  5 00:37:42 2008
@@ -4977,3 +4977,80 @@
    v8::String::AsciiValue name(value);
    CHECK_EQ("asdf", *name);
  }
+
+
+static v8::Handle<Value> AccessorProhibitsOverwritingGetter(
+    Local<String> name,
+    const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  return v8::True();
+}
+
+
+THREADED_TEST(AccessorProhibitsOverwriting) {
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetAccessor(v8_str("x"),
+                     AccessorProhibitsOverwritingGetter,
+                     0,
+                     v8::Handle<Value>(),
+                     v8::PROHIBITS_OVERWRITING,
+                     v8::ReadOnly);
+  Local<v8::Object> instance = templ->NewInstance();
+  context->Global()->Set(v8_str("obj"), instance);
+  Local<Value> value = CompileRun(
+      "obj.__defineGetter__('x', function() { return false; });"
+      "obj.x");
+  CHECK(value->BooleanValue());
+  value = CompileRun(
+      "var setter_called = false;"
+      "obj.__defineSetter__('x', function() { setter_called = true; });"
+      "obj.x = 42;"
+      "setter_called");
+  CHECK(!value->BooleanValue());
+  value = CompileRun(
+      "obj2 = {};"
+      "obj2.__proto__ = obj;"
+      "obj2.__defineGetter__('x', function() { return false; });"
+      "obj2.x");
+  CHECK(value->BooleanValue());
+  value = CompileRun(
+      "var setter_called = false;"
+      "obj2 = {};"
+      "obj2.__proto__ = obj;"
+      "obj2.__defineSetter__('x', function() { setter_called = true; });"
+      "obj2.x = 42;"
+      "setter_called");
+  CHECK(!value->BooleanValue());
+}
+
+
+static bool NamedSetAccessBlocker(Local<v8::Object> obj,
+                                  Local<Value> name,
+                                  v8::AccessType type,
+                                  Local<Value> data) {
+  return type != v8::ACCESS_SET;
+}
+
+
+static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
+                                    uint32_t key,
+                                    v8::AccessType type,
+                                    Local<Value> data) {
+  return type != v8::ACCESS_SET;
+}
+
+
+THREADED_TEST(DisableAccessChecksWhileConfiguring) {
+  v8::HandleScope scope;
+  LocalContext context;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
+                                 IndexedSetAccessBlocker);
+  templ->Set(v8_str("x"), v8::True());
+  Local<v8::Object> instance = templ->NewInstance();
+  context->Global()->Set(v8_str("obj"), instance);
+  Local<Value> value = CompileRun("obj.x");
+  CHECK(value->BooleanValue());
+}

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to