mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1122238 part 3. Drop all the DOMException-cloning and sanitization gunk we added in bug 1107592 and bug 1107953 and bug 1117242 . r=bholley
This commit is contained in:
parent
6db6b887fb
commit
f22da41d9f
@ -723,31 +723,5 @@ DOMException::Create(nsresult aRv)
|
||||
return inst.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
DOMException::Sanitize(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aSanitizedValue)
|
||||
{
|
||||
nsRefPtr<DOMException> retval = this;
|
||||
if (mLocation && !mLocation->CallerSubsumes(aCx)) {
|
||||
nsString message;
|
||||
GetMessageMoz(message);
|
||||
nsString name;
|
||||
GetName(name);
|
||||
retval = new dom::DOMException(nsresult(Result()),
|
||||
NS_ConvertUTF16toUTF8(message),
|
||||
NS_ConvertUTF16toUTF8(name),
|
||||
Code());
|
||||
// Now it's possible that the stack on retval still starts with
|
||||
// stuff aCx is not supposed to touch; it depends on what's on the
|
||||
// stack right this second. Walk past all of that.
|
||||
nsCOMPtr<nsIStackFrame> stack;
|
||||
nsresult rv = retval->mLocation->GetSanitized(aCx, getter_AddRefs(stack));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
retval->mLocation.swap(stack);
|
||||
}
|
||||
|
||||
return ToJSValue(aCx, retval, aSanitizedValue);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -156,15 +156,6 @@ public:
|
||||
static already_AddRefed<DOMException>
|
||||
Create(nsresult aRv);
|
||||
|
||||
// Sanitize() is a workaround for the fact that DOMExceptions can leak stack
|
||||
// information for the first stackframe to callers that should not have access
|
||||
// to it. To prevent this, we check whether aCx subsumes our first stackframe
|
||||
// and if not hand out a JS::Value for a clone of ourselves. Otherwise we
|
||||
// hand out a JS::Value for ourselves.
|
||||
//
|
||||
// If the return value is false, an exception was thrown on aCx.
|
||||
bool Sanitize(JSContext* aCx, JS::MutableHandle<JS::Value> aSanitizedValue);
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~DOMException() {}
|
||||
|
@ -250,26 +250,6 @@ ErrorResult::ReportJSExceptionFromJSImplementation(JSContext* aCx)
|
||||
nsresult rv =
|
||||
UNWRAP_OBJECT(DOMException, &mJSException.toObject(), domException);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// We may have to create a new DOMException object, because the one we
|
||||
// have has a stack that includes the chrome code that threw it, and in
|
||||
// particular has the wrong file/line/column information.
|
||||
JS::Rooted<JS::Value> reflector(aCx);
|
||||
if (!domException->Sanitize(aCx, &reflector)) {
|
||||
// Well, that threw _an_ exception. Let's forget ours. We can just
|
||||
// unroot and not change the value, since mJSException is completely
|
||||
// ignored if mResult is not NS_ERROR_DOM_JS_EXCEPTION and we plan to
|
||||
// change mResult to a different value.
|
||||
js::RemoveRawValueRoot(aCx, &mJSException);
|
||||
|
||||
// We no longer have a useful exception but we do want to signal that an
|
||||
// error occured.
|
||||
mResult = NS_ERROR_FAILURE;
|
||||
|
||||
// But do make sure to not ReportJSException here, since we don't have one.
|
||||
return;
|
||||
}
|
||||
|
||||
mJSException = reflector;
|
||||
ReportJSException(aCx);
|
||||
return;
|
||||
}
|
||||
@ -308,17 +288,6 @@ ErrorResult::StealJSException(JSContext* cx,
|
||||
value.set(mJSException);
|
||||
js::RemoveRawValueRoot(cx, &mJSException);
|
||||
mResult = NS_OK;
|
||||
|
||||
if (value.isObject()) {
|
||||
// If it's a DOMException we may need to sanitize it.
|
||||
dom::DOMException* domException;
|
||||
nsresult rv =
|
||||
UNWRAP_OBJECT(DOMException, &value.toObject(), domException);
|
||||
if (NS_SUCCEEDED(rv) && !domException->Sanitize(cx, value)) {
|
||||
JS_GetPendingException(cx, value);
|
||||
JS_ClearPendingException(cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -107,8 +107,7 @@ public:
|
||||
|
||||
// StealJSException steals the JS Exception from the object. This method must
|
||||
// be called only if IsJSException() returns true. This method also resets the
|
||||
// ErrorCode() to NS_OK. The value will be ensured to be sanitized wrt to the
|
||||
// current compartment of cx if it happens to be a DOMException.
|
||||
// ErrorCode() to NS_OK.
|
||||
void StealJSException(JSContext* cx, JS::MutableHandle<JS::Value> value);
|
||||
|
||||
void MOZ_ALWAYS_INLINE MightThrowJSException()
|
||||
|
@ -307,9 +307,6 @@ public:
|
||||
NS_IMETHOD GetName(nsAString& aFunction) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetCaller(nsIStackFrame** aCaller) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetFormattedStack(nsAString& aStack) MOZ_OVERRIDE;
|
||||
virtual bool CallerSubsumes(JSContext* aCx) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetSanitized(JSContext* aCx,
|
||||
nsIStackFrame** aSanitized) MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
virtual bool IsJSFrame() const MOZ_OVERRIDE {
|
||||
@ -581,35 +578,6 @@ NS_IMETHODIMP StackFrame::GetSourceLine(nsACString& aSourceLine)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [noscript] readonly attribute nsIStackFrame sanitized */
|
||||
NS_IMETHODIMP StackFrame::GetSanitized(JSContext*, nsIStackFrame** aSanitized)
|
||||
{
|
||||
NS_ADDREF(*aSanitized = this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [noscript] readonly attribute nsIStackFrame sanitized */
|
||||
NS_IMETHODIMP JSStackFrame::GetSanitized(JSContext* aCx, nsIStackFrame** aSanitized)
|
||||
{
|
||||
// NB: Do _not_ enter the compartment of the SavedFrame object here, because
|
||||
// we are checking against the caller's compartment's principals in
|
||||
// GetFirstSubsumedSavedFrame.
|
||||
|
||||
JS::RootedObject savedFrame(aCx, mStack);
|
||||
JS::ExposeObjectToActiveJS(mStack);
|
||||
|
||||
savedFrame = js::GetFirstSubsumedSavedFrame(aCx, savedFrame);
|
||||
nsCOMPtr<nsIStackFrame> stackFrame;
|
||||
if (savedFrame) {
|
||||
stackFrame = new JSStackFrame(savedFrame);
|
||||
} else {
|
||||
stackFrame = new StackFrame();
|
||||
}
|
||||
|
||||
stackFrame.forget(aSanitized);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute nsIStackFrame caller; */
|
||||
NS_IMETHODIMP JSStackFrame::GetCaller(nsIStackFrame** aCaller)
|
||||
{
|
||||
@ -731,37 +699,6 @@ NS_IMETHODIMP StackFrame::ToString(nsACString& _retval)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* virtual */ bool
|
||||
StackFrame::CallerSubsumes(JSContext* aCx)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/* virtual */ bool
|
||||
JSStackFrame::CallerSubsumes(JSContext* aCx)
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!mStack) {
|
||||
// No problem here, there's no data to leak.
|
||||
return true;
|
||||
}
|
||||
|
||||
nsIPrincipal* callerPrincipal = nsContentUtils::SubjectPrincipal();
|
||||
|
||||
JS::Rooted<JSObject*> unwrappedStack(aCx, js::CheckedUnwrap(mStack));
|
||||
if (!unwrappedStack) {
|
||||
// We can't leak data here either.
|
||||
return true;
|
||||
}
|
||||
|
||||
nsIPrincipal* stackPrincipal =
|
||||
nsJSPrincipals::get(js::GetSavedFramePrincipals(unwrappedStack));
|
||||
return callerPrincipal->SubsumesConsideringDomain(stackPrincipal);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsIStackFrame>
|
||||
JSStackFrame::CreateStack(JSContext* aCx, int32_t aMaxDepth)
|
||||
{
|
||||
|
@ -212,11 +212,6 @@ protected:
|
||||
if (rv.Failed()) {
|
||||
JS::Rooted<JS::Value> exn(cx);
|
||||
if (rv.IsJSException()) {
|
||||
// Enter the compartment of mPromise before stealing the JS exception,
|
||||
// since the StealJSException call will use the current compartment for
|
||||
// a security check that determines how much of the stack we're allowed
|
||||
// to see and we'll be exposing that stack to consumers of mPromise.
|
||||
JSAutoCompartment ac(cx, mPromise->GlobalJSObject());
|
||||
rv.StealJSException(cx, &exn);
|
||||
} else {
|
||||
// Convert the ErrorResult to a JS exception object that we can reject
|
||||
@ -610,14 +605,7 @@ Promise::CallInitFunction(const GlobalObject& aGlobal,
|
||||
|
||||
if (aRv.IsJSException()) {
|
||||
JS::Rooted<JS::Value> value(cx);
|
||||
{ // scope for ac
|
||||
// Enter the compartment of our global before stealing the JS exception,
|
||||
// since the StealJSException call will use the current compartment for
|
||||
// a security check that determines how much of the stack we're allowed
|
||||
// to see, and we'll be exposing that stack to consumers of this promise.
|
||||
JSAutoCompartment ac(cx, GlobalJSObject());
|
||||
aRv.StealJSException(cx, &value);
|
||||
}
|
||||
aRv.StealJSException(cx, &value);
|
||||
|
||||
// we want the same behavior as this JS implementation:
|
||||
// function Promise(arg) { try { arg(a, b); } catch (e) { this.reject(e); }}
|
||||
|
@ -214,15 +214,7 @@ WrapperPromiseCallback::Call(JSContext* aCx,
|
||||
if (rv.Failed()) {
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
if (rv.IsJSException()) {
|
||||
{ // scope for ac
|
||||
// Enter the compartment of mNextPromise before stealing the JS
|
||||
// exception, since the StealJSException call will use the current
|
||||
// compartment for a security check that determines how much of the
|
||||
// stack we're allowed to see and we'll be exposing that stack to
|
||||
// consumers of mPromise.
|
||||
JSAutoCompartment ac(aCx, mNextPromise->GlobalJSObject());
|
||||
rv.StealJSException(aCx, &value);
|
||||
}
|
||||
rv.StealJSException(aCx, &value);
|
||||
|
||||
if (!JS_WrapValue(aCx, &value)) {
|
||||
NS_WARNING("Failed to wrap value into the right compartment.");
|
||||
|
@ -10,9 +10,7 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[ptr] native JSContext(JSContext);
|
||||
|
||||
[scriptable, uuid(4ed5cd87-401a-425a-8d8d-c28fbc1e88b2)]
|
||||
[scriptable, uuid(8272a3d5-2a94-40c0-8ab6-be76583a0221)]
|
||||
interface nsIStackFrame : nsISupports
|
||||
{
|
||||
// see nsIProgrammingLanguage for list of language consts
|
||||
@ -26,20 +24,12 @@ interface nsIStackFrame : nsISupports
|
||||
readonly attribute AUTF8String sourceLine;
|
||||
readonly attribute nsIStackFrame caller;
|
||||
|
||||
// Returns the first frame whose principals are subsumed by the caller's
|
||||
// principals.
|
||||
[noscript, implicit_jscontext] readonly attribute nsIStackFrame sanitized;
|
||||
|
||||
// Returns a formatted stack string that looks like the sort of
|
||||
// string that would be returned by .stack on JS Error objects.
|
||||
// Only works on JS-language stack frames.
|
||||
readonly attribute AString formattedStack;
|
||||
|
||||
AUTF8String toString();
|
||||
|
||||
// Return whether this stack frame can be accessed by the caller. This is
|
||||
// safe to call on non-main threads, but will always report "yes" there.
|
||||
[noscript, notxpcom, nostdcall] boolean callerSubsumes(in JSContext aCx);
|
||||
};
|
||||
|
||||
[scriptable, uuid(1caf1461-be1d-4b79-a552-5292b6bf3c35)]
|
||||
|
Loading…
Reference in New Issue
Block a user