Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always pass InRealm to GlobalScope::from_context to avoid getting a null global #25369

Merged
merged 1 commit into from Feb 19, 2020
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -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};
@@ -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());
@@ -57,7 +57,7 @@ DOMInterfaces = {
},

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

'WorkerGlobalScope': {
@@ -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;
@@ -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;
}
@@ -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());
}
}

@@ -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;
@@ -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),
);
@@ -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),
@@ -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,
@@ -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(
@@ -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
@@ -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;
@@ -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;
@@ -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,
@@ -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
@@ -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;
@@ -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;
}
@@ -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};
@@ -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;
@@ -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)
}

@@ -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);

@@ -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();
@@ -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,
};
@@ -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
@@ -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;
@@ -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);
}
}
@@ -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,
@@ -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)]
@@ -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;
@@ -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();
}
@@ -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,
@@ -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
}
@@ -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))
}
}

@@ -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)]
@@ -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)]
@@ -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)]
@@ -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 {
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.