Reviewers: jochen,
Message:
ptal
Description:
Properly fix enumerate / Object.keys wrt access checked objects
BUG=chromium:509936
LOG=y
Please review this at https://codereview.chromium.org/1241953010/
Base URL: https://chromium.googlesource.com/v8/v8.git@master
Affected files (+53, -26 lines):
M src/objects.cc
M src/runtime/runtime-object.cc
M test/cctest/test-api.cc
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index
554f9dce970f44a62229e6dbd2eb56bf24f1aa47..538fbea0a0bbee899f19c4687cfaa4dc8e3a4575
100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -6147,10 +6147,13 @@ MaybeHandle<FixedArray>
JSReceiver::GetKeys(Handle<JSReceiver> object,
Handle<JSFunction> arguments_function(
JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
+ PrototypeIterator::WhereToEnd end = type == OWN_ONLY
+ ?
PrototypeIterator::END_AT_NON_HIDDEN
+ : PrototypeIterator::END_AT_NULL;
// Only collect keys if access is permitted.
for (PrototypeIterator iter(isolate, object,
PrototypeIterator::START_AT_RECEIVER);
- !iter.IsAtEnd(); iter.Advance()) {
+ !iter.IsAtEnd(end); iter.Advance()) {
if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
Handle<JSProxy>
proxy(JSProxy::cast(*PrototypeIterator::GetCurrent(iter)),
isolate);
@@ -6177,7 +6180,11 @@ MaybeHandle<FixedArray>
JSReceiver::GetKeys(Handle<JSReceiver> object,
// Check access rights if required.
if (current->IsAccessCheckNeeded() && !isolate->MayAccess(current)) {
- return content;
+ if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
+ isolate->ReportFailedAccessCheck(current);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
+ }
+ break;
}
// Compute the element keys.
@@ -6237,10 +6244,6 @@ MaybeHandle<FixedArray>
JSReceiver::GetKeys(Handle<JSReceiver> object,
}
DCHECK(ContainsOnlyValidKeys(content));
}
-
- // If we only want own properties we bail out after the first
- // iteration.
- if (type == OWN_ONLY) break;
}
return content;
}
Index: src/runtime/runtime-object.cc
diff --git a/src/runtime/runtime-object.cc b/src/runtime/runtime-object.cc
index
d0d215d43bb18b53fd6213974c81370517118da2..24ff5a7fc2d5f606cbf8739fedbec1ba1f6cd807
100644
--- a/src/runtime/runtime-object.cc
+++ b/src/runtime/runtime-object.cc
@@ -1010,20 +1010,6 @@ RUNTIME_FUNCTION(Runtime_OwnKeys) {
CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
Handle<JSObject> object(raw_object);
- if (object->IsJSGlobalProxy()) {
- // Do access checks before going to the global object.
- if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) {
- isolate->ReportFailedAccessCheck(object);
- RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
- return *isolate->factory()->NewJSArray(0);
- }
-
- PrototypeIterator iter(isolate, object);
- // If proxy is detached we simply return an empty array.
- if (iter.IsAtEnd()) return *isolate->factory()->NewJSArray(0);
- object = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
- }
-
Handle<FixedArray> contents;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, contents, JSReceiver::GetKeys(object,
JSReceiver::OWN_ONLY));
Index: test/cctest/test-api.cc
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index
ce34d7d29bd768465e5e574db57e029d362a437a..f9f2310f50dcc8525f7293e5d48b96984b539bc4
100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -8140,7 +8140,7 @@ THREADED_TEST(CrossDomainIsPropertyEnumerable) {
}
-THREADED_TEST(CrossDomainForIn) {
+THREADED_TEST(CrossDomainFor) {
LocalContext env1;
v8::HandleScope handle_scope(env1->GetIsolate());
v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
@@ -8164,9 +8164,8 @@ THREADED_TEST(CrossDomainForIn) {
Context::Scope scope_env2(env2);
Local<Value> result = CompileRun(
"(function() {"
- " var obj = { '__proto__': env1 };"
" try {"
- " for (var p in obj) {"
+ " for (var p in env1) {"
" if (p == 'prop') return false;"
" }"
" return true;"
@@ -8179,6 +8178,45 @@ THREADED_TEST(CrossDomainForIn) {
}
+THREADED_TEST(CrossDomainForInOnPrototype) {
+ LocalContext env1;
+ v8::HandleScope handle_scope(env1->GetIsolate());
+ v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
+
+ Local<Value> foo = v8_str("foo");
+ Local<Value> bar = v8_str("bar");
+
+ // Set to the same domain.
+ env1->SetSecurityToken(foo);
+ env2->SetSecurityToken(foo);
+
+ env1->Global()->Set(v8_str("prop"), v8_num(3));
+ env2->Global()->Set(v8_str("env1"), env1->Global());
+
+ // Change env2 to a different domain and set env1's global object
+ // as the __proto__ of an object in env2 and enumerate properties
+ // in for-in. It shouldn't enumerate properties on env1's global
+ // object.
+ env2->SetSecurityToken(bar);
+ {
+ Context::Scope scope_env2(env2);
+ Local<Value> result = CompileRun(
+ "(function() {"
+ " var obj = { '__proto__': env1 };"
+ " try {"
+ " for (var p in obj) {"
+ " if (p == 'prop') return false;"
+ " }"
+ " return false;"
+ " } catch (e) {"
+ " return true;"
+ " }"
+ "})()");
+ CHECK(result->IsTrue());
+ }
+}
+
+
TEST(ContextDetachGlobal) {
LocalContext env1;
v8::HandleScope handle_scope(env1->GetIsolate());
@@ -8627,9 +8665,9 @@ TEST(AccessControl) {
" return false;"
" }"
" }"
- " return true;"
- " } catch (e) {"
" return false;"
+ " } catch (e) {"
+ " return true;"
" }"
"})()");
CHECK(value->IsTrue());
@@ -8673,7 +8711,7 @@ TEST(AccessControlES5) {
global1->Set(v8_str("other"), global0);
// Regression test for issue 1154.
- CHECK(CompileRun("Object.keys(other)").IsEmpty());
+ CHECK(CompileRun("Object.keys(other).length == 0")->BooleanValue());
CHECK(CompileRun("other.blocked_prop").IsEmpty());
// Regression test for issue 1027.
--
--
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/d/optout.