Skip to content

Commit

Permalink
Always pass InRealm to GlobalScope::from_context to avoid getting nul…
Browse files Browse the repository at this point in the history
…l global
  • Loading branch information
CYBAI committed Feb 16, 2020
1 parent 795dab7 commit 403ffcf
Show file tree
Hide file tree
Showing 16 changed files with 79 additions and 61 deletions.
9 changes: 3 additions & 6 deletions components/script/dom/bindings/callback.rs
Expand Up @@ -13,9 +13,9 @@ use crate::dom::bindings::settings_stack::{AutoEntryScript, AutoIncumbentScript}
use crate::dom::bindings::utils::AsCCharPtrPtr;
use crate::dom::globalscope::GlobalScope;
use crate::dom::window::Window;
use crate::realms::{enter_realm, InRealm};
use crate::script_runtime::JSContext;
use js::jsapi::Heap;
use js::jsapi::JSAutoRealm;
use js::jsapi::{AddRawValueRoot, IsCallable, JSObject};
use js::jsapi::{EnterRealm, LeaveRealm, Realm, RemoveRawValueRoot};
use js::jsval::{JSVal, ObjectValue, UndefinedValue};
Expand Down Expand Up @@ -270,11 +270,8 @@ impl Drop for CallSetup {
unsafe {
LeaveRealm(*self.cx, self.old_realm);
if self.handling == ExceptionHandling::Report {
let _ac = JSAutoRealm::new(
*self.cx,
self.exception_global.reflector().get_jsobject().get(),
);
report_pending_exception(*self.cx, true);
let ar = enter_realm(&*self.exception_global);
report_pending_exception(*self.cx, true, InRealm::Entered(&ar));
}
drop(self.incumbent_script.take());
drop(self.entry_script.take().unwrap());
Expand Down
2 changes: 1 addition & 1 deletion components/script/dom/bindings/codegen/Bindings.conf
Expand Up @@ -57,7 +57,7 @@ DOMInterfaces = {
},

'Window': {
'inRealms': ['Fetch'],
'inRealms': ['Fetch', 'Opener'],
},

'WorkerGlobalScope': {
Expand Down
5 changes: 3 additions & 2 deletions components/script/dom/bindings/error.rs
Expand Up @@ -14,6 +14,7 @@ use crate::dom::bindings::conversions::{
use crate::dom::bindings::str::USVString;
use crate::dom::domexception::{DOMErrorName, DOMException};
use crate::dom::globalscope::GlobalScope;
use crate::realms::InRealm;
use crate::script_runtime::JSContext as SafeJSContext;
#[cfg(feature = "js_backtrace")]
use backtrace::Backtrace;
Expand Down Expand Up @@ -231,7 +232,7 @@ impl ErrorInfo {
///
/// The `dispatch_event` argument is temporary and non-standard; passing false
/// prevents dispatching the `error` event.
pub unsafe fn report_pending_exception(cx: *mut JSContext, dispatch_event: bool) {
pub unsafe fn report_pending_exception(cx: *mut JSContext, dispatch_event: bool, realm: InRealm) {
if !JS_IsExceptionPending(cx) {
return;
}
Expand Down Expand Up @@ -285,7 +286,7 @@ pub unsafe fn report_pending_exception(cx: *mut JSContext, dispatch_event: bool)
}

if dispatch_event {
GlobalScope::from_context(cx).report_an_error(error_info, value.handle());
GlobalScope::from_context(cx, realm).report_an_error(error_info, value.handle());
}
}

Expand Down
11 changes: 7 additions & 4 deletions components/script/dom/bindings/structuredclone.rs
Expand Up @@ -14,7 +14,7 @@ use crate::dom::bindings::transferable::Transferable;
use crate::dom::blob::Blob;
use crate::dom::globalscope::GlobalScope;
use crate::dom::messageport::MessagePort;
use crate::realms::enter_realm;
use crate::realms::{enter_realm, AlreadyInRealm, InRealm};
use crate::script_runtime::JSContext as SafeJSContext;
use js::glue::CopyJSStructuredCloneData;
use js::glue::DeleteJSAutoStructuredCloneBuffer;
Expand Down Expand Up @@ -129,8 +129,9 @@ unsafe extern "C" fn read_callback(
"tag should be higher than StructuredCloneTags::Min"
);
if tag == StructuredCloneTags::DomBlob as u32 {
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
return read_blob(
&GlobalScope::from_context(cx),
&GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof)),
r,
&mut *(closure as *mut StructuredDataHolder),
);
Expand All @@ -145,8 +146,9 @@ unsafe extern "C" fn write_callback(
closure: *mut raw::c_void,
) -> bool {
if let Ok(blob) = root_from_object::<Blob>(*obj, cx) {
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
return write_blob(
&GlobalScope::from_context(cx),
&GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof)),
blob,
w,
&mut *(closure as *mut StructuredDataHolder),
Expand All @@ -166,7 +168,8 @@ unsafe extern "C" fn read_transfer_callback(
) -> bool {
if tag == StructuredCloneTags::MessagePort as u32 {
let mut sc_holder = &mut *(closure as *mut StructuredDataHolder);
let owner = GlobalScope::from_context(cx);
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
let owner = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof));
if let Ok(_) = <MessagePort as Transferable>::transfer_receive(
&owner,
&mut sc_holder,
Expand Down
7 changes: 3 additions & 4 deletions components/script/dom/create.rs
Expand Up @@ -81,9 +81,9 @@ use crate::dom::htmlulistelement::HTMLUListElement;
use crate::dom::htmlunknownelement::HTMLUnknownElement;
use crate::dom::htmlvideoelement::HTMLVideoElement;
use crate::dom::svgsvgelement::SVGSVGElement;
use crate::realms::{enter_realm, InRealm};
use crate::script_thread::ScriptThread;
use html5ever::{LocalName, Prefix, QualName};
use js::jsapi::JSAutoRealm;
use servo_config::pref;

fn create_svg_element(
Expand Down Expand Up @@ -157,10 +157,9 @@ fn create_html_element(

// Step 6.1.1
unsafe {
let _ac =
JSAutoRealm::new(*cx, global.reflector().get_jsobject().get());
let ar = enter_realm(&*global);
throw_dom_exception(cx, &global, error);
report_pending_exception(*cx, true);
report_pending_exception(*cx, true, InRealm::Entered(&ar));
}

// Step 6.1.2
Expand Down
5 changes: 3 additions & 2 deletions components/script/dom/customelementregistry.rs
Expand Up @@ -31,7 +31,7 @@ use crate::dom::node::{document_from_node, window_from_node, Node, ShadowIncludi
use crate::dom::promise::Promise;
use crate::dom::window::Window;
use crate::microtask::Microtask;
use crate::realms::InRealm;
use crate::realms::{enter_realm, InRealm};
use crate::script_runtime::JSContext;
use crate::script_thread::ScriptThread;
use dom_struct::dom_struct;
Expand Down Expand Up @@ -652,8 +652,9 @@ pub fn upgrade_element(definition: Rc<CustomElementDefinition>, element: &Elemen
let global = GlobalScope::current().expect("No current global");
let cx = global.get_cx();
unsafe {
let ar = enter_realm(&*global);
throw_dom_exception(cx, &global, error);
report_pending_exception(*cx, true);
report_pending_exception(*cx, true, InRealm::Entered(&ar));
}

return;
Expand Down
8 changes: 5 additions & 3 deletions components/script/dom/dedicatedworkerglobalscope.rs
Expand Up @@ -26,7 +26,7 @@ use crate::dom::messageevent::MessageEvent;
use crate::dom::worker::{TrustedWorkerAddress, Worker};
use crate::dom::workerglobalscope::WorkerGlobalScope;
use crate::fetch::load_whole_resource;
use crate::realms::enter_realm;
use crate::realms::{enter_realm, AlreadyInRealm, InRealm};
use crate::script_runtime::ScriptThreadEventCategory::WorkerEvent;
use crate::script_runtime::{
new_child_runtime, CommonScriptMsg, JSContext as SafeJSContext, Runtime, ScriptChan, ScriptPort,
Expand Down Expand Up @@ -555,8 +555,10 @@ impl DedicatedWorkerGlobalScope {

#[allow(unsafe_code)]
unsafe extern "C" fn interrupt_callback(cx: *mut JSContext) -> bool {
let worker = DomRoot::downcast::<WorkerGlobalScope>(GlobalScope::from_context(cx))
.expect("global is not a worker scope");
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
let global = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof));
let worker =
DomRoot::downcast::<WorkerGlobalScope>(global).expect("global is not a worker scope");
assert!(worker.is::<DedicatedWorkerGlobalScope>());

// A false response causes the script to terminate
Expand Down
8 changes: 4 additions & 4 deletions components/script/dom/eventtarget.rs
Expand Up @@ -34,10 +34,10 @@ use crate::dom::node::document_from_node;
use crate::dom::virtualmethods::VirtualMethods;
use crate::dom::window::Window;
use crate::dom::workerglobalscope::WorkerGlobalScope;
use crate::realms::enter_realm;
use crate::realms::{enter_realm, InRealm};
use dom_struct::dom_struct;
use fnv::FnvHasher;
use js::jsapi::{JSAutoRealm, JSFunction, JS_GetFunctionObject, SourceText};
use js::jsapi::{JSFunction, JS_GetFunctionObject, SourceText};
use js::rust::wrappers::CompileFunction;
use js::rust::{AutoObjectVectorWrapper, CompileOptionsWrapper};
use libc::c_char;
Expand Down Expand Up @@ -552,9 +552,9 @@ impl EventTarget {
if !rv || handler.get().is_null() {
// Step 3.7
unsafe {
let _ac = JSAutoRealm::new(*cx, self.reflector().get_jsobject().get());
let ar = enter_realm(&*self);
// FIXME(#13152): dispatch error event.
report_pending_exception(*cx, false);
report_pending_exception(*cx, false, InRealm::Entered(&ar));
}
return None;
}
Expand Down
13 changes: 7 additions & 6 deletions components/script/dom/globalscope.rs
Expand Up @@ -38,7 +38,7 @@ use crate::dom::window::Window;
use crate::dom::workerglobalscope::WorkerGlobalScope;
use crate::dom::workletglobalscope::WorkletGlobalScope;
use crate::microtask::{Microtask, MicrotaskQueue, UserMicrotask};
use crate::realms::enter_realm;
use crate::realms::{enter_realm, InRealm};
use crate::script_module::ModuleTree;
use crate::script_runtime::{CommonScriptMsg, JSContext as SafeJSContext, ScriptChan, ScriptPort};
use crate::script_thread::{MainThreadScriptChan, ScriptThread};
Expand All @@ -61,10 +61,10 @@ use dom_struct::dom_struct;
use ipc_channel::ipc::{self, IpcSender};
use ipc_channel::router::ROUTER;
use js::glue::{IsWrapper, UnwrapObjectDynamic};
use js::jsapi::JSContext;
use js::jsapi::JSObject;
use js::jsapi::{CurrentGlobalOrNull, GetNonCCWObjectGlobal};
use js::jsapi::{HandleObject, Heap};
use js::jsapi::{JSAutoRealm, JSContext};
use js::jsval::{JSVal, UndefinedValue};
use js::panic::maybe_resume_unwind;
use js::rust::wrappers::EvaluateUtf8;
Expand Down Expand Up @@ -1449,8 +1449,9 @@ impl GlobalScope {

/// Returns the global scope for the given JSContext
#[allow(unsafe_code)]
pub unsafe fn from_context(cx: *mut JSContext) -> DomRoot<Self> {
pub unsafe fn from_context(cx: *mut JSContext, _realm: InRealm) -> DomRoot<Self> {
let global = CurrentGlobalOrNull(cx);
assert!(!global.is_null());
global_scope_from_global(global, cx)
}

Expand Down Expand Up @@ -1846,10 +1847,10 @@ impl GlobalScope {
self.time_profiler_chan().clone(),
|| {
let cx = self.get_cx();
let globalhandle = self.reflector().get_jsobject();
let filename = CString::new(filename).unwrap();

let _ac = JSAutoRealm::new(*cx, globalhandle.get());
let ar = enter_realm(&*self);

let _aes = AutoEntryScript::new(self);
let options = CompileOptionsWrapper::new(*cx, filename.as_ptr(), line_number);

Expand All @@ -1866,7 +1867,7 @@ impl GlobalScope {

if !result {
debug!("error evaluating Dom string");
unsafe { report_pending_exception(*cx, true) };
unsafe { report_pending_exception(*cx, true, InRealm::Entered(&ar)) };
}

maybe_resume_unwind();
Expand Down
8 changes: 5 additions & 3 deletions components/script/dom/serviceworkerglobalscope.rs
Expand Up @@ -22,7 +22,7 @@ use crate::dom::messageevent::MessageEvent;
use crate::dom::worker::TrustedWorkerAddress;
use crate::dom::workerglobalscope::WorkerGlobalScope;
use crate::fetch::load_whole_resource;
use crate::realms::enter_realm;
use crate::realms::{enter_realm, AlreadyInRealm, InRealm};
use crate::script_runtime::{
new_rt_and_cx, CommonScriptMsg, JSContext as SafeJSContext, Runtime, ScriptChan,
};
Expand Down Expand Up @@ -447,8 +447,10 @@ impl ServiceWorkerGlobalScope {

#[allow(unsafe_code)]
unsafe extern "C" fn interrupt_callback(cx: *mut JSContext) -> bool {
let worker = DomRoot::downcast::<WorkerGlobalScope>(GlobalScope::from_context(cx))
.expect("global is not a worker scope");
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
let global = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof));
let worker =
DomRoot::downcast::<WorkerGlobalScope>(global).expect("global is not a worker scope");
assert!(worker.is::<ServiceWorkerGlobalScope>());

// A false response causes the script to terminate
Expand Down
7 changes: 5 additions & 2 deletions components/script/dom/testbinding.rs
Expand Up @@ -48,7 +48,7 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise;
use crate::dom::promisenativehandler::{Callback, PromiseNativeHandler};
use crate::dom::url::URL;
use crate::realms::InRealm;
use crate::realms::{AlreadyInRealm, InRealm};
use crate::script_runtime::JSContext as SafeJSContext;
use crate::timers::OneshotTimerCallback;
use dom_struct::dom_struct;
Expand Down Expand Up @@ -1015,7 +1015,10 @@ impl TestBindingMethods for TestBinding {
impl Callback for SimpleHandler {
#[allow(unsafe_code)]
fn callback(&self, cx: *mut JSContext, v: HandleValue) {
let global = unsafe { GlobalScope::from_context(cx) };
let global = unsafe {
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof))
};
let _ = self.handler.Call_(&*global, v, ExceptionHandling::Report);
}
}
Expand Down
4 changes: 2 additions & 2 deletions components/script/dom/window.rs
Expand Up @@ -673,7 +673,7 @@ impl WindowMethods for Window {
}

// https://html.spec.whatwg.org/multipage/#dom-opener
fn Opener(&self, cx: JSContext) -> JSVal {
fn Opener(&self, cx: JSContext, in_realm_proof: InRealm) -> JSVal {
// Step 1, Let current be this Window object's browsing context.
let current = match self.window_proxy.get() {
Some(proxy) => proxy,
Expand All @@ -688,7 +688,7 @@ impl WindowMethods for Window {
return NullValue();
}
// Step 3 to 5.
current.opener(*cx)
current.opener(*cx, in_realm_proof)
}

#[allow(unsafe_code)]
Expand Down
29 changes: 18 additions & 11 deletions components/script/dom/windowproxy.rs
Expand Up @@ -17,7 +17,7 @@ use crate::dom::document::Document;
use crate::dom::element::Element;
use crate::dom::globalscope::GlobalScope;
use crate::dom::window::Window;
use crate::realms::enter_realm;
use crate::realms::{enter_realm, AlreadyInRealm, InRealm};
use crate::script_runtime::JSContext as SafeJSContext;
use crate::script_thread::ScriptThread;
use dom_struct::dom_struct;
Expand Down Expand Up @@ -370,7 +370,7 @@ impl WindowProxy {

#[allow(unsafe_code)]
// https://html.spec.whatwg.org/multipage/#dom-opener
pub fn opener(&self, cx: *mut JSContext) -> JSVal {
pub fn opener(&self, cx: *mut JSContext, in_realm_proof: InRealm) -> JSVal {
if self.disowned.get() {
return NullValue();
}
Expand All @@ -387,7 +387,8 @@ impl WindowProxy {
opener_id,
) {
Some(opener_top_id) => {
let global_to_clone_from = unsafe { GlobalScope::from_context(cx) };
let global_to_clone_from =
unsafe { GlobalScope::from_context(cx, in_realm_proof) };
WindowProxy::new_dissimilar_origin(
&*global_to_clone_from,
opener_id,
Expand Down Expand Up @@ -982,10 +983,11 @@ pub fn new_window_proxy_handler() -> WindowProxyHandler {
// defined in the DissimilarOriginWindow IDL.

#[allow(unsafe_code)]
unsafe fn throw_security_error(cx: *mut JSContext) -> bool {
unsafe fn throw_security_error(cx: *mut JSContext, realm: InRealm) -> bool {
if !JS_IsExceptionPending(cx) {
let global = GlobalScope::from_context(cx);
throw_dom_exception(SafeJSContext::from_ptr(cx), &*global, Error::Security);
let safe_context = SafeJSContext::from_ptr(cx);
let global = GlobalScope::from_context(cx, realm);
throw_dom_exception(safe_context, &*global, Error::Security);
}
false
}
Expand All @@ -1006,7 +1008,8 @@ unsafe extern "C" fn has_xorigin(
*bp = true;
true
} else {
throw_security_error(cx)
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
throw_security_error(cx, InRealm::Already(&in_realm_proof))
}
}

Expand All @@ -1032,7 +1035,8 @@ unsafe extern "C" fn set_xorigin(
_: RawHandleValue,
_: *mut ObjectOpResult,
) -> bool {
throw_security_error(cx)
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
throw_security_error(cx, InRealm::Already(&in_realm_proof))
}

#[allow(unsafe_code)]
Expand All @@ -1042,7 +1046,8 @@ unsafe extern "C" fn delete_xorigin(
_: RawHandleId,
_: *mut ObjectOpResult,
) -> bool {
throw_security_error(cx)
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
throw_security_error(cx, InRealm::Already(&in_realm_proof))
}

#[allow(unsafe_code, non_snake_case)]
Expand All @@ -1065,7 +1070,8 @@ unsafe extern "C" fn defineProperty_xorigin(
_: RawHandle<PropertyDescriptor>,
_: *mut ObjectOpResult,
) -> bool {
throw_security_error(cx)
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
throw_security_error(cx, InRealm::Already(&in_realm_proof))
}

#[allow(unsafe_code, non_snake_case)]
Expand All @@ -1074,7 +1080,8 @@ unsafe extern "C" fn preventExtensions_xorigin(
_: RawHandleObject,
_: *mut ObjectOpResult,
) -> bool {
throw_security_error(cx)
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
throw_security_error(cx, InRealm::Already(&in_realm_proof))
}

static XORIGIN_PROXY_HANDLER: ProxyTraps = ProxyTraps {
Expand Down

0 comments on commit 403ffcf

Please sign in to comment.