Commit e7ecb74b authored by lrn@chromium.org's avatar lrn@chromium.org

Don't let JSON parsed objects hit inherited setters.

Review URL: http://codereview.chromium.org/6101001

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6154 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f95f295d
......@@ -521,6 +521,10 @@ void Heap::SetLastScriptId(Object* last_script_id) {
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) {
......
......@@ -6795,7 +6795,8 @@ bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) {
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 @@ MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index,
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 @@ MaybeObject* JSObject::SetElementWithCallback(Object* structure,
// 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 @@ MaybeObject* JSObject::SetFastElement(uint32_t index, Object* value) {
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 @@ MaybeObject* JSObject::SetFastElement(uint32_t index, Object* value) {
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 @@ MaybeObject* JSObject::SetElement(uint32_t index, Object* value) {
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 @@ MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
}
} 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).
......
......@@ -1505,11 +1505,15 @@ class JSObject: public HeapObject {
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 @@ class JSObject: public HeapObject {
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);
......
......@@ -3680,9 +3680,11 @@ Handle<Object> JsonParser::ParseJsonObject() {
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) {
......
// 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();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment