0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2024-11-21 15:04:33 -05:00

feat: Expose the security token API from V8 (#1192)

This commit is contained in:
Giovanny Gutiérrez 2023-03-10 08:31:13 -05:00 committed by GitHub
parent c2ec15f046
commit c58f4c08d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 117 additions and 0 deletions

View file

@ -1719,6 +1719,21 @@ void v8__Context__SetPromiseHooks(v8::Context& self,
ptr_to_local(after_hook), ptr_to_local(resolve_hook));
}
const v8::Value* v8__Context__GetSecurityToken(const v8::Context& self) {
auto value = ptr_to_local(&self)->GetSecurityToken();
return local_to_ptr(value);
}
void v8__Context__SetSecurityToken(v8::Context& self,
const v8::Value* token) {
auto c = ptr_to_local(&self);
c->SetSecurityToken(ptr_to_local(token));
}
void v8__Context__UseDefaultSecurityToken(v8::Context& self) {
ptr_to_local(&self)->UseDefaultSecurityToken();
}
const v8::Context* v8__Context__FromSnapshot(v8::Isolate* isolate,
size_t context_snapshot_index) {
v8::MaybeLocal<v8::Context> maybe_local =

View file

@ -40,6 +40,14 @@ extern "C" {
isolate: *mut Isolate,
context_snapshot_index: usize,
) -> *const Context;
pub(super) fn v8__Context__GetSecurityToken(
this: *const Context,
) -> *const Value;
pub(super) fn v8__Context__SetSecurityToken(
this: *const Context,
value: *const Value,
);
pub(super) fn v8__Context__UseDefaultSecurityToken(this: *const Context);
}
impl Context {
@ -320,6 +328,29 @@ impl Context {
})
}
}
#[inline(always)]
pub fn get_security_token<'s>(
&self,
scope: &mut HandleScope<'s, ()>,
) -> Local<'s, Value> {
unsafe { scope.cast_local(|_| v8__Context__GetSecurityToken(self)) }
.unwrap()
}
#[inline(always)]
pub fn set_security_token(&self, token: Local<Value>) {
unsafe {
v8__Context__SetSecurityToken(self, &*token);
}
}
#[inline(always)]
pub fn use_default_security_token(&self) {
unsafe {
v8__Context__UseDefaultSecurityToken(self);
}
}
}
struct ContextAnnex {

View file

@ -3386,6 +3386,77 @@ fn context_promise_hooks_partial() {
}
}
#[test]
fn security_token() {
let _setup_guard = setup::parallel_test();
let isolate = &mut v8::Isolate::new(Default::default());
{
let scope = &mut v8::HandleScope::new(isolate);
let context = v8::Context::new(scope);
let scope = &mut v8::ContextScope::new(scope, context);
// Define a variable in the parent context
let global = {
let global = context.global(scope);
let variable_key = v8::String::new(scope, "variable").unwrap();
let variable_value = v8::String::new(scope, "value").unwrap();
global.set(scope, variable_key.into(), variable_value.into());
v8::Global::new(scope, global)
};
// This code will try to access the variable defined in the parent context
let source = r#"
if (variable !== 'value') {
throw new Error('Expected variable to be value');
}
"#;
let templ = v8::ObjectTemplate::new(scope);
let global = v8::Local::new(scope, global);
templ.set_named_property_handler(
v8::NamedPropertyHandlerConfiguration::new()
.getter(
|scope: &mut v8::HandleScope,
key: v8::Local<v8::Name>,
args: v8::PropertyCallbackArguments,
mut rv: v8::ReturnValue| {
let obj = v8::Local::<v8::Object>::try_from(args.data()).unwrap();
if let Some(val) = obj.get(scope, key.into()) {
rv.set(val);
}
},
)
.data(global.into()),
);
// Creates a child context
{
let security_token = context.get_security_token(scope);
let child_context = v8::Context::new_from_template(scope, templ);
// Without the security context, the variable can not be shared
child_context.set_security_token(security_token);
let child_scope = &mut v8::ContextScope::new(scope, child_context);
let try_catch = &mut v8::TryCatch::new(child_scope);
let result = eval(try_catch, source);
assert!(!try_catch.has_caught());
assert!(result.unwrap().is_undefined());
}
// Runs the same code but without the security token, it should fail
{
let child_context = v8::Context::new_from_template(scope, templ);
let child_scope = &mut v8::ContextScope::new(scope, child_context);
let try_catch = &mut v8::TryCatch::new(child_scope);
let result = eval(try_catch, source);
assert!(try_catch.has_caught());
let exc = try_catch.exception().unwrap();
let exc = exc.to_string(try_catch).unwrap();
let exc = exc.to_rust_string_lossy(try_catch);
assert!(exc.contains("no access"));
assert!(result.is_none());
}
}
}
#[test]
fn allow_atomics_wait() {
let _setup_guard = setup::parallel_test();