Revision: 22698
Author: [email protected]
Date: Wed Jul 30 09:31:06 2014 UTC
Log: Throw an exception when an access check fails and no external
callback is installed
[email protected]
Review URL: https://codereview.chromium.org/428733007
http://code.google.com/p/v8/source/detail?r=22698
Modified:
/branches/bleeding_edge/src/isolate.cc
/branches/bleeding_edge/src/mirror-debugger.js
/branches/bleeding_edge/test/cctest/test-api.cc
/branches/bleeding_edge/tools/generate-runtime-tests.py
=======================================
--- /branches/bleeding_edge/src/isolate.cc Tue Jul 29 16:07:34 2014 UTC
+++ /branches/bleeding_edge/src/isolate.cc Wed Jul 30 09:31:06 2014 UTC
@@ -638,7 +638,11 @@
void Isolate::ReportFailedAccessCheck(Handle<JSObject> receiver,
v8::AccessType type) {
- if (!thread_local_top()->failed_access_check_callback_) return;
+ if (!thread_local_top()->failed_access_check_callback_) {
+ Handle<String> message = factory()->InternalizeUtf8String("no access");
+ ScheduleThrow(*factory()->NewTypeError(message));
+ return;
+ }
ASSERT(receiver->IsAccessCheckNeeded());
ASSERT(context());
=======================================
--- /branches/bleeding_edge/src/mirror-debugger.js Wed Jul 23 07:33:47 2014
UTC
+++ /branches/bleeding_edge/src/mirror-debugger.js Wed Jul 30 09:31:06 2014
UTC
@@ -171,7 +171,7 @@
PropertyKind.Indexed = 2;
-// A copy of the PropertyType enum from global.h
+// A copy of the PropertyType enum from property-details.h
var PropertyType = {};
PropertyType.Normal = 0;
PropertyType.Field = 1;
@@ -179,8 +179,7 @@
PropertyType.Callbacks = 3;
PropertyType.Handler = 4;
PropertyType.Interceptor = 5;
-PropertyType.Transition = 6;
-PropertyType.Nonexistent = 7;
+PropertyType.Nonexistent = 6;
// Different attributes for a property.
@@ -682,6 +681,19 @@
var x = %GetInterceptorInfo(this.value_);
return (x & 1) != 0;
};
+
+
+// Get all own property names except for private symbols.
+function TryGetPropertyNames(object) {
+ try {
+ // TODO(yangguo): Should there be a special debugger implementation of
+ // %GetOwnPropertyNames that doesn't perform access checks?
+ return %GetOwnPropertyNames(object,
PROPERTY_ATTRIBUTES_PRIVATE_SYMBOL);
+ } catch (e) {
+ // Might have hit a failed access check.
+ return [];
+ }
+}
/**
@@ -702,9 +714,7 @@
// Find all the named properties.
if (kind & PropertyKind.Named) {
- // Get all own property names except for private symbols.
- propertyNames =
- %GetOwnPropertyNames(this.value_,
PROPERTY_ATTRIBUTES_PRIVATE_SYMBOL);
+ propertyNames = TryGetPropertyNames(this.value_);
total += propertyNames.length;
// Get names for named interceptor properties if any.
=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc Tue Jul 29 18:02:26
2014 UTC
+++ /branches/bleeding_edge/test/cctest/test-api.cc Wed Jul 30 09:31:06
2014 UTC
@@ -6178,15 +6178,17 @@
context->Global()->Set(v8_str("obj"), obj);
const char* code =
- "try {"
- " for (var i = 0; i < 100; i++) {"
+ "var result = 'PASSED';"
+ "for (var i = 0; i < 100; i++) {"
+ " try {"
" var v = obj[0];"
- " if (v != undefined) throw 'Wrong value ' + v + ' at iteration '
+ i;"
+ " result = 'Wrong value ' + v + ' at iteration ' + i;"
+ " break;"
+ " } catch (e) {"
+ " /* pass */"
" }"
- " 'PASSED'"
- "} catch(e) {"
- " e"
- "}";
+ "}"
+ "result";
ExpectString(code, "PASSED");
}
@@ -6203,21 +6205,29 @@
context->Global()->Set(v8_str("obj"), obj);
const char* code =
- "try {"
- " for (var i = 0; i < 100; i++) {"
- " var expected = i;"
+ "var result = 'PASSED';"
+ "for (var i = 0; i < 100; i++) {"
+ " var expected = i;"
+ " if (i == 5) {"
+ " %EnableAccessChecks(obj);"
+ " }"
+ " try {"
+ " var v = obj[i];"
" if (i == 5) {"
- " %EnableAccessChecks(obj);"
- " expected = undefined;"
+ " result = 'Should not have reached this!';"
+ " break;"
+ " } else if (v != expected) {"
+ " result = 'Wrong value ' + v + ' at iteration ' + i;"
+ " break;"
" }"
- " var v = obj[i];"
- " if (v != expected) throw 'Wrong value ' + v + ' at iteration '
+ i;"
- " if (i == 5) %DisableAccessChecks(obj);"
+ " } catch (e) {"
+ " if (i != 5) {"
+ " result = e;"
+ " }"
" }"
- " 'PASSED'"
- "} catch(e) {"
- " e"
- "}";
+ " if (i == 5) %DisableAccessChecks(obj);"
+ "}"
+ "result";
ExpectString(code, "PASSED");
}
@@ -8628,10 +8638,8 @@
v8::Local<Script> access_other0 = v8_compile("other.Object");
v8::Local<Script> access_other1 = v8_compile("other[42]");
for (int i = 0; i < 5; i++) {
- CHECK(!access_other0->Run()->Equals(other_object));
- CHECK(access_other0->Run()->IsUndefined());
- CHECK(!access_other1->Run()->Equals(v8_num(87)));
- CHECK(access_other1->Run()->IsUndefined());
+ CHECK(access_other0->Run().IsEmpty());
+ CHECK(access_other1->Run().IsEmpty());
}
// Create an object that has 'other' in its prototype chain and make
@@ -8643,10 +8651,8 @@
v8::Local<Script> access_f0 = v8_compile("f.Object");
v8::Local<Script> access_f1 = v8_compile("f[42]");
for (int j = 0; j < 5; j++) {
- CHECK(!access_f0->Run()->Equals(other_object));
- CHECK(access_f0->Run()->IsUndefined());
- CHECK(!access_f1->Run()->Equals(v8_num(87)));
- CHECK(access_f1->Run()->IsUndefined());
+ CHECK(access_f0->Run().IsEmpty());
+ CHECK(access_f1->Run().IsEmpty());
}
// Now it gets hairy: Set the prototype for the other global object
@@ -8665,10 +8671,8 @@
Local<Script> access_f2 = v8_compile("f.foo");
Local<Script> access_f3 = v8_compile("f[99]");
for (int k = 0; k < 5; k++) {
- CHECK(!access_f2->Run()->Equals(v8_num(100)));
- CHECK(access_f2->Run()->IsUndefined());
- CHECK(!access_f3->Run()->Equals(v8_num(101)));
- CHECK(access_f3->Run()->IsUndefined());
+ CHECK(access_f2->Run().IsEmpty());
+ CHECK(access_f3->Run().IsEmpty());
}
}
@@ -8749,7 +8753,7 @@
Context::Scope scope_env2(env2);
Local<Value> result =
CompileRun("delete env1.prop");
- CHECK(result->IsFalse());
+ CHECK(result.IsEmpty());
}
// Check that env1.prop still exists.
@@ -8787,7 +8791,7 @@
{
Context::Scope scope_env2(env2);
Local<Value> result = CompileRun(test);
- CHECK(result->IsFalse());
+ CHECK(result.IsEmpty());
}
}
@@ -8814,11 +8818,18 @@
env2->SetSecurityToken(bar);
{
Context::Scope scope_env2(env2);
- Local<Value> result =
- CompileRun("(function(){var obj = {'__proto__':env1};"
- "for (var p in obj)"
- " if (p == 'prop') return false;"
- "return true;})()");
+ 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());
}
}
@@ -8880,7 +8891,7 @@
// Check that env3 is not accessible from env1
{
Local<Value> r = global3->Get(v8_str("prop2"));
- CHECK(r->IsUndefined());
+ CHECK(r.IsEmpty());
}
}
@@ -8919,7 +8930,7 @@
// Check that the global has been detached. No other.p property can
// be found.
result = CompileRun("other.p");
- CHECK(result->IsUndefined());
+ CHECK(result.IsEmpty());
// Reuse global2 for env3.
v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
@@ -8949,7 +8960,7 @@
// the global object for env3 which has a different security token,
// so access should be blocked.
result = CompileRun("other.p");
- CHECK(result->IsUndefined());
+ CHECK(result.IsEmpty());
}
@@ -9002,9 +9013,9 @@
result = CompileRun("bound_x()");
CHECK_EQ(v8_str("env2_x"), result);
result = CompileRun("get_x()");
- CHECK(result->IsUndefined());
+ CHECK(result.IsEmpty());
result = CompileRun("get_x_w()");
- CHECK(result->IsUndefined());
+ CHECK(result.IsEmpty());
result = CompileRun("this_x()");
CHECK_EQ(v8_str("env2_x"), result);
@@ -9200,33 +9211,35 @@
// Access blocked property.
CompileRun("other.blocked_prop = 1");
- ExpectUndefined("other.blocked_prop");
- ExpectUndefined(
- "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
- ExpectFalse("propertyIsEnumerable.call(other, 'blocked_prop')");
+ CHECK(CompileRun("other.blocked_prop").IsEmpty());
+
CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
+ .IsEmpty());
+ CHECK(
+
CompileRun("propertyIsEnumerable.call(other, 'blocked_prop')").IsEmpty());
// Access blocked element.
- CompileRun("other[239] = 1");
+ CHECK(CompileRun("other[239] = 1").IsEmpty());
- ExpectUndefined("other[239]");
- ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239')");
- ExpectFalse("propertyIsEnumerable.call(other, '239')");
+ CHECK(CompileRun("other[239]").IsEmpty());
+
CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239')").IsEmpty());
+ CHECK(CompileRun("propertyIsEnumerable.call(other, '239')").IsEmpty());
// Enable ACCESS_HAS
allowed_access_type[v8::ACCESS_HAS] = true;
- ExpectUndefined("other[239]");
+ CHECK(CompileRun("other[239]").IsEmpty());
// ... and now we can get the descriptor...
- ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239').value");
+ CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239').value")
+ .IsEmpty());
// ... and enumerate the property.
ExpectTrue("propertyIsEnumerable.call(other, '239')");
allowed_access_type[v8::ACCESS_HAS] = false;
// Access a property with JS accessor.
- CompileRun("other.js_accessor_p = 2");
+ CHECK(CompileRun("other.js_accessor_p = 2").IsEmpty());
- ExpectUndefined("other.js_accessor_p");
- ExpectUndefined(
- "Object.getOwnPropertyDescriptor(other, 'js_accessor_p')");
+ CHECK(CompileRun("other.js_accessor_p").IsEmpty());
+
CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'js_accessor_p')")
+ .IsEmpty());
// Enable both ACCESS_HAS and ACCESS_GET.
allowed_access_type[v8::ACCESS_HAS] = true;
@@ -9244,10 +9257,10 @@
allowed_access_type[v8::ACCESS_GET] = false;
// Access an element with JS accessor.
- CompileRun("other[42] = 2");
+ CHECK(CompileRun("other[42] = 2").IsEmpty());
- ExpectUndefined("other[42]");
- ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42')");
+ CHECK(CompileRun("other[42]").IsEmpty());
+
CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '42')").IsEmpty());
// Enable both ACCESS_HAS and ACCESS_GET.
allowed_access_type[v8::ACCESS_HAS] = true;
@@ -9283,15 +9296,22 @@
// Enumeration doesn't enumerate accessors from inaccessible objects in
// the prototype chain even if the accessors are in themselves
accessible.
- value =
- CompileRun("(function(){var obj = {'__proto__':other};"
- "for (var p in obj)"
- " if (p == 'accessible_prop' ||"
- " p == 'blocked_js_prop' ||"
- " p == 'blocked_js_prop') {"
- " return false;"
- " }"
- "return true;})()");
+ value = CompileRun(
+ "(function() {"
+ " var obj = { '__proto__': other };"
+ " try {"
+ " for (var p in obj) {"
+ " if (p == 'accessible_prop' ||"
+ " p == 'blocked_js_prop' ||"
+ " p == 'blocked_js_prop') {"
+ " return false;"
+ " }"
+ " }"
+ " return false;"
+ " } catch (e) {"
+ " return true;"
+ " }"
+ "})()");
CHECK(value->IsTrue());
context1->Exit();
@@ -9334,16 +9354,15 @@
global1->Set(v8_str("other"), global0);
// Regression test for issue 1154.
- ExpectTrue("Object.keys(other).indexOf('blocked_prop') == -1");
-
- ExpectUndefined("other.blocked_prop");
+ CHECK(CompileRun("Object.keys(other)").IsEmpty());
+ CHECK(CompileRun("other.blocked_prop").IsEmpty());
// Regression test for issue 1027.
CompileRun("Object.defineProperty(\n"
" other, 'blocked_prop', {configurable: false})");
- ExpectUndefined("other.blocked_prop");
- ExpectUndefined(
- "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
+ CHECK(CompileRun("other.blocked_prop").IsEmpty());
+
CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
+ .IsEmpty());
// Regression test for issue 1171.
ExpectTrue("Object.isExtensible(other)");
@@ -9419,10 +9438,10 @@
// proxy object. Accessing the object that requires access checks
// is blocked by the access checks on the object itself.
value = CompileRun("Object.getOwnPropertyNames(other).length == 0");
- CHECK(value->IsTrue());
+ CHECK(value.IsEmpty());
value = CompileRun("Object.getOwnPropertyNames(object).length == 0");
- CHECK(value->IsTrue());
+ CHECK(value.IsEmpty());
context1->Exit();
context0->Exit();
@@ -9530,7 +9549,7 @@
CHECK_EQ(10, value->Int32Value());
value = v8_compile("other.unreachable")->Run();
- CHECK(value->IsUndefined());
+ CHECK(value.IsEmpty());
context1->Exit();
context0->Exit();
@@ -14642,13 +14661,13 @@
context->Global()->Set(v8_str("obj_1"), instance_1);
Local<Value> value_1 = CompileRun("obj_1.a");
- CHECK(value_1->IsUndefined());
+ CHECK(value_1.IsEmpty());
Local<v8::Object> instance_2 = templ->NewInstance();
context->Global()->Set(v8_str("obj_2"), instance_2);
Local<Value> value_2 = CompileRun("obj_2.a");
- CHECK(value_2->IsUndefined());
+ CHECK(value_2.IsEmpty());
}
@@ -14729,11 +14748,9 @@
context->DetachGlobal();
hidden_global->TurnOnAccessCheck();
- // Failing access check to property get results in undefined.
- CHECK(f1->Call(global, 0, NULL)->IsUndefined());
- CHECK(f2->Call(global, 0, NULL)->IsUndefined());
-
- // Failing access check to function call results in exception.
+ // Failing access check results in exception.
+ CHECK(f1->Call(global, 0, NULL).IsEmpty());
+ CHECK(f2->Call(global, 0, NULL).IsEmpty());
CHECK(g1->Call(global, 0, NULL).IsEmpty());
CHECK(g2->Call(global, 0, NULL).IsEmpty());
@@ -14817,11 +14834,9 @@
context->DetachGlobal();
hidden_global->TurnOnAccessCheck();
- // Failing access check to property get results in undefined.
- CHECK(f1->Call(global, 0, NULL)->IsUndefined());
- CHECK(f2->Call(global, 0, NULL)->IsUndefined());
-
- // Failing access check to function call results in exception.
+ // Failing access check results in exception.
+ CHECK(f1->Call(global, 0, NULL).IsEmpty());
+ CHECK(f2->Call(global, 0, NULL).IsEmpty());
CHECK(g1->Call(global, 0, NULL).IsEmpty());
CHECK(g2->Call(global, 0, NULL).IsEmpty());
@@ -14835,13 +14850,13 @@
f2 = Local<Function>::Cast(hidden_global->Get(v8_str("f2")));
g1 = Local<Function>::Cast(hidden_global->Get(v8_str("g1")));
g2 = Local<Function>::Cast(hidden_global->Get(v8_str("g2")));
- CHECK(hidden_global->Get(v8_str("h"))->IsUndefined());
-
- // Failing access check to property get results in undefined.
- CHECK(f1->Call(global, 0, NULL)->IsUndefined());
- CHECK(f2->Call(global, 0, NULL)->IsUndefined());
+ CHECK(hidden_global->Get(v8_str("h")).IsEmpty());
- // Failing access check to function call results in exception.
+ // Failing access check results in exception.
+ v8::Local<v8::Value> result = f1->Call(global, 0, NULL);
+ CHECK(result.IsEmpty());
+ CHECK(f1->Call(global, 0, NULL).IsEmpty());
+ CHECK(f2->Call(global, 0, NULL).IsEmpty());
CHECK(g1->Call(global, 0, NULL).IsEmpty());
CHECK(g2->Call(global, 0, NULL).IsEmpty());
}
@@ -20364,20 +20379,20 @@
CHECK(result1->Equals(simple_object->GetPrototype()));
Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
- CHECK(result2->Equals(Undefined(isolate)));
+ CHECK(result2.IsEmpty());
Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
CHECK(result3->Equals(global_object->GetPrototype()));
Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
- CHECK(result4->Equals(Undefined(isolate)));
+ CHECK(result4.IsEmpty());
Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
CHECK(result5->Equals(
object_with_hidden->GetPrototype()->ToObject()->GetPrototype()));
Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
- CHECK(result6->Equals(Undefined(isolate)));
+ CHECK(result6.IsEmpty());
}
@@ -21572,11 +21587,9 @@
LocalContext context1(NULL, global_template);
context1->Global()->Set(v8_str("other"), global0);
- ExpectString("JSON.stringify(other)", "{}");
- ExpectString("JSON.stringify({ 'a' : other, 'b' : ['c'] })",
- "{\"a\":{},\"b\":[\"c\"]}");
- ExpectString("JSON.stringify([other, 'b', 'c'])",
- "[{},\"b\",\"c\"]");
+ CHECK(CompileRun("JSON.stringify(other)").IsEmpty());
+ CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c']
})").IsEmpty());
+ CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty());
v8::Handle<v8::Array> array = v8::Array::New(isolate, 2);
array->Set(0, v8_str("a"));
@@ -21584,9 +21597,9 @@
context1->Global()->Set(v8_str("array"), array);
ExpectString("JSON.stringify(array)", "[\"a\",\"b\"]");
array->TurnOnAccessCheck();
- ExpectString("JSON.stringify(array)", "[]");
- ExpectString("JSON.stringify([array])", "[[]]");
- ExpectString("JSON.stringify({'a' : array})", "{\"a\":[]}");
+ CHECK(CompileRun("JSON.stringify(array)").IsEmpty());
+ CHECK(CompileRun("JSON.stringify([array])").IsEmpty());
+ CHECK(CompileRun("JSON.stringify({'a' : array})").IsEmpty());
}
}
=======================================
--- /branches/bleeding_edge/tools/generate-runtime-tests.py Tue Jul 29
08:09:14 2014 UTC
+++ /branches/bleeding_edge/tools/generate-runtime-tests.py Wed Jul 30
09:31:06 2014 UTC
@@ -51,7 +51,7 @@
EXPECTED_FUZZABLE_COUNT = 336
EXPECTED_CCTEST_COUNT = 8
EXPECTED_UNKNOWN_COUNT = 4
-EXPECTED_BUILTINS_COUNT = 815
+EXPECTED_BUILTINS_COUNT = 816
# Don't call these at all.
--
--
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.