Revision: 6154
Author: [email protected]
Date: Tue Jan  4 04:19:55 2011
Log: Don't let JSON parsed objects hit inherited setters.

Review URL: http://codereview.chromium.org/6101001
http://code.google.com/p/v8/source/detail?r=6154

Added:
 /branches/bleeding_edge/test/mjsunit/bugs/bug-1015.js
Modified:
 /branches/bleeding_edge/src/heap-inl.h
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/parser.cc

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/bugs/bug-1015.js Tue Jan 4 04:19:55 2011
@@ -0,0 +1,66 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// See: http://code.google.com/p/v8/issues/detail?id=1015
+
+// Object and array literals should be created using DefineOwnProperty, and
+// therefore not hit setters in the prototype.
+
+function mkFail(message) {
+  return function () { assertUnreachable(message); }
+}
+
+Object.defineProperty(Object.prototype, "foo",
+                             {get: mkFail("oget"), set: mkFail("oset")});
+Object.defineProperty(Array.prototype, "2",
+                      {get: mkFail("aget"), set: mkFail("aset")});
+
+function inFunction() {
+  for (var i = 0; i < 10; i++) {
+    // in loop.
+    var ja = JSON.parse('[1,2,3,4]');
+    var jo = JSON.parse('{"bar": 10, "foo": 20}')
+    var jop = JSON.parse('{"bar": 10, "__proto__": { }, "foo": 20}')
+    var a = [1,2,3,4];
+    var o = { bar: 10, foo: 20 };
+    var op = { __proto__: { set bar(v) { assertUnreachable("bset"); } },
+               bar: 10 };
+  }
+}
+
+for (var i = 0; i < 10; i++) {
+  // In global scope.
+  var ja = JSON.parse('[1,2,3,4]');
+  var jo = JSON.parse('{"bar": 10, "foo": 20}')
+  var jop = JSON.parse('{"bar": 10, "__proto__": { }, "foo": 20}')
+  var a = [1,2,3,4];
+  var o = { bar: 10, foo: 20 };
+  var op = { __proto__: { set bar(v) { assertUnreachable("bset"); } },
+             bar: 10 };
+  // In function scope.
+  inFunction();
+}
=======================================
--- /branches/bleeding_edge/src/heap-inl.h      Wed Dec 22 12:14:19 2010
+++ /branches/bleeding_edge/src/heap-inl.h      Tue Jan  4 04:19:55 2011
@@ -521,6 +521,10 @@
   CALL_AND_RETRY(FUNCTION_CALL, return, return)


+#define CALL_HEAP_FUNCTION_INLINE(FUNCTION_CALL) \
+  CALL_AND_RETRY(FUNCTION_CALL, break, break)
+
+
 #ifdef DEBUG

 inline bool Heap::allow_allocation(bool new_state) {
=======================================
--- /branches/bleeding_edge/src/objects.cc      Wed Dec 22 12:14:19 2010
+++ /branches/bleeding_edge/src/objects.cc      Tue Jan  4 04:19:55 2011
@@ -6795,7 +6795,8 @@


 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index,
-                                                 Object* value) {
+                                                 Object* value,
+                                                 bool check_prototype) {
   // Make sure that the top context does not change when doing
   // callbacks or interceptor calls.
   AssertNoContextChange ncc;
@@ -6819,7 +6820,9 @@
     if (!result.IsEmpty()) return *value_handle;
   }
   MaybeObject* raw_result =
-      this_handle->SetElementWithoutInterceptor(index, *value_handle);
+      this_handle->SetElementWithoutInterceptor(index,
+                                                *value_handle,
+                                                check_prototype);
   RETURN_IF_SCHEDULED_EXCEPTION();
   return raw_result;
 }
@@ -6930,7 +6933,9 @@
 // Adding n elements in fast case is O(n*n).
 // Note: revisit design to have dual undefined values to capture absent
 // elements.
-MaybeObject* JSObject::SetFastElement(uint32_t index, Object* value) {
+MaybeObject* JSObject::SetFastElement(uint32_t index,
+                                      Object* value,
+                                      bool check_prototype) {
   ASSERT(HasFastElements());

   Object* elms_obj;
@@ -6940,7 +6945,8 @@
   FixedArray* elms = FixedArray::cast(elms_obj);
   uint32_t elms_length = static_cast<uint32_t>(elms->length());

- if (!IsJSArray() && (index >= elms_length || elms->get(index)->IsTheHole())) {
+  if (check_prototype && !IsJSArray() &&
+      (index >= elms_length || elms->get(index)->IsTheHole())) {
     if (SetElementWithCallbackSetterInPrototypes(index, value)) {
       return value;
     }
@@ -6983,11 +6989,13 @@
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   }
   ASSERT(HasDictionaryElements());
-  return SetElement(index, value);
+  return SetElement(index, value, check_prototype);
 }


-MaybeObject* JSObject::SetElement(uint32_t index, Object* value) {
+MaybeObject* JSObject::SetElement(uint32_t index,
+                                  Object* value,
+                                  bool check_prototype) {
   // Check access rights if needed.
   if (IsAccessCheckNeeded() &&
       !Top::MayIndexedAccess(this, index, v8::ACCESS_SET)) {
@@ -7001,24 +7009,25 @@
     Object* proto = GetPrototype();
     if (proto->IsNull()) return value;
     ASSERT(proto->IsJSGlobalObject());
-    return JSObject::cast(proto)->SetElement(index, value);
+ return JSObject::cast(proto)->SetElement(index, value, check_prototype);
   }

   // Check for lookup interceptor
   if (HasIndexedInterceptor()) {
-    return SetElementWithInterceptor(index, value);
+    return SetElementWithInterceptor(index, value, check_prototype);
   }

-  return SetElementWithoutInterceptor(index, value);
+  return SetElementWithoutInterceptor(index, value, check_prototype);
 }


 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
-                                                    Object* value) {
+                                                    Object* value,
+                                                    bool check_prototype) {
   switch (GetElementsKind()) {
     case FAST_ELEMENTS:
       // Fast case.
-      return SetFastElement(index, value);
+      return SetFastElement(index, value, check_prototype);
     case PIXEL_ELEMENTS: {
       PixelArray* pixels = PixelArray::cast(elements());
       return pixels->SetValue(index, value);
@@ -7071,10 +7080,9 @@
         }
       } else {
// Index not already used. Look for an accessor in the prototype chain.
-        if (!IsJSArray()) {
-          if (SetElementWithCallbackSetterInPrototypes(index, value)) {
-            return value;
-          }
+        if (check_prototype && !IsJSArray() &&
+            SetElementWithCallbackSetterInPrototypes(index, value)) {
+          return value;
         }
         // When we set the is_extensible flag to false we always force
         // the element into dictionary mode (and force them to stay there).
=======================================
--- /branches/bleeding_edge/src/objects.h       Wed Dec 22 12:14:19 2010
+++ /branches/bleeding_edge/src/objects.h       Tue Jan  4 04:19:55 2011
@@ -1505,11 +1505,15 @@
   bool HasElementWithInterceptor(JSObject* receiver, uint32_t index);
   bool HasElementPostInterceptor(JSObject* receiver, uint32_t index);

- MUST_USE_RESULT MaybeObject* SetFastElement(uint32_t index, Object* value);
+  MUST_USE_RESULT MaybeObject* SetFastElement(uint32_t index,
+                                              Object* value,
+                                              bool check_prototype = true);

   // Set the index'th array element.
   // A Failure object is returned if GC is needed.
-  MUST_USE_RESULT MaybeObject* SetElement(uint32_t index, Object* value);
+  MUST_USE_RESULT MaybeObject* SetElement(uint32_t index,
+                                          Object* value,
+                                          bool check_prototype = true);

   // Returns the index'th element.
   // The undefined object if index is out of bounds.
@@ -1763,9 +1767,12 @@
                                       Object* value,
                                       JSObject* holder);
   MUST_USE_RESULT MaybeObject* SetElementWithInterceptor(uint32_t index,
-                                                         Object* value);
-  MUST_USE_RESULT MaybeObject* SetElementWithoutInterceptor(uint32_t index,
-                                                            Object* value);
+                                                         Object* value,
+ bool check_prototype);
+  MUST_USE_RESULT MaybeObject* SetElementWithoutInterceptor(
+      uint32_t index,
+      Object* value,
+      bool check_prototype);

MaybeObject* GetElementPostInterceptor(JSObject* receiver, uint32_t index);

=======================================
--- /branches/bleeding_edge/src/parser.cc       Tue Jan  4 04:07:16 2011
+++ /branches/bleeding_edge/src/parser.cc       Tue Jan  4 04:19:55 2011
@@ -3680,9 +3680,11 @@
       if (value.is_null()) return Handle<Object>::null();
       uint32_t index;
       if (key->AsArrayIndex(&index)) {
-        SetElement(json_object, index, value);
+        CALL_HEAP_FUNCTION_INLINE(
+            (*json_object)->SetElement(index, *value, true));
       } else {
-        SetProperty(json_object, key, value, NONE);
+        CALL_HEAP_FUNCTION_INLINE(
+ (*json_object)->SetPropertyPostInterceptor(*key, *value, NONE));
       }
     } while (scanner_.Next() == Token::COMMA);
     if (scanner_.current_token() != Token::RBRACE) {

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

Reply via email to