Bug 1666419: Assert IsSafeToRunScript. r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D91391
This commit is contained in:
Christoph Kerschbaumer 2020-09-28 06:29:44 +00:00
Родитель f27594d62e
Коммит 359ca7017e
10 изменённых файлов: 90 добавлений и 0 удалений

Просмотреть файл

@ -9161,6 +9161,7 @@ nsresult nsContentUtils::NewXULOrHTMLElement(
return NS_ERROR_FAILURE;
}
AutoAllowLegacyScriptExecution exemption;
AutoEntryScript aes(global, "create custom elements");
JSContext* cx = aes.cx();
ErrorResult rv;

Просмотреть файл

@ -268,6 +268,7 @@ CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
return;
}
AutoAllowLegacyScriptExecution exemption;
mAutoEntryScript.emplace(globalObject, aExecutionReason, mIsMainThread);
mAutoEntryScript->SetWebIDLCallerPrincipal(webIDLCallerPrincipal);
nsIGlobalObject* incumbent = aCallback->IncumbentGlobalOrNull();

Просмотреть файл

@ -101,6 +101,8 @@ void DocumentL10n::TriggerInitialTranslation() {
return;
}
AutoAllowLegacyScriptExecution exemption;
nsTArray<RefPtr<Promise>> promises;
ErrorResult rv;
@ -190,6 +192,8 @@ already_AddRefed<Promise> DocumentL10n::TranslateDocument(ErrorResult& aRv) {
// back to top->bottom one.
nonProtoElements.Reverse();
AutoAllowLegacyScriptExecution exemption;
nsTArray<RefPtr<Promise>> promises;
// 2.1.2. If we're not loading from cache, push the elements that

Просмотреть файл

@ -692,6 +692,8 @@ static bool doInvoke(NPObject* npobj, NPIdentifier method,
return false;
}
AutoAllowLegacyScriptExecution exemption;
// We're about to run script via JS_CallFunctionValue, so we need an
// AutoEntryScript. NPAPI plugins are Gecko-specific and not in any spec.
dom::AutoEntryScript aes(globalObject, "NPAPI doInvoke");

Просмотреть файл

@ -174,6 +174,7 @@ class Promise : public SupportsWeakPtr {
// Mark a settled promise as already handled so that rejections will not
// be reported as unhandled.
void SetSettledPromiseIsHandled() {
AutoAllowLegacyScriptExecution exemption;
AutoEntryScript aes(mGlobal, "Set settled promise handled");
JSContext* cx = aes.cx();
JS::RootedObject promiseObj(cx, mPromiseObj);
@ -315,6 +316,7 @@ class Promise : public SupportsWeakPtr {
void MaybeSomething(T&& aArgument, MaybeFunc aFunc) {
MOZ_ASSERT(PromiseObj()); // It was preserved!
AutoAllowLegacyScriptExecution exemption;
AutoEntryScript aes(mGlobal, "Promise resolution or rejection");
JSContext* cx = aes.cx();

Просмотреть файл

@ -546,6 +546,9 @@ nsresult ScriptLoader::CreateModuleScript(ModuleLoadRequest* aRequest) {
}
nsAutoMicroTask mt;
AutoAllowLegacyScriptExecution exemption;
AutoEntryScript aes(globalObject, "CompileModule", true);
bool oldProcessingScriptTag = context->GetProcessingScriptTag();
@ -3223,6 +3226,7 @@ void ScriptLoader::GiveUpBytecodeEncoding() {
// removal of all request from the current list and these large buffers would
// be removed at the same time as the source object.
nsCOMPtr<nsIScriptGlobalObject> globalObject = GetScriptGlobalObject();
AutoAllowLegacyScriptExecution exemption;
Maybe<AutoEntryScript> aes;
if (globalObject) {

Просмотреть файл

@ -32,6 +32,25 @@ namespace dom {
static MOZ_THREAD_LOCAL(ScriptSettingsStackEntry*) sScriptSettingsTLS;
// Assert if it's not safe to run script. The helper class
// AutoAllowLegacyScriptExecution allows to allow-list
// legacy cases where it's actually not safe to run script.
#ifdef DEBUG
static void AssertIfNotSafeToRunScript() {
// if it's safe to run script, then there is nothing to do here.
if (nsContentUtils::IsSafeToRunScript()) {
return;
}
// auto allowing legacy script execution is fine for now.
if (AutoAllowLegacyScriptExecution::IsAllowed()) {
return;
}
MOZ_ASSERT(false, "is it safe to run script?");
}
#endif
class ScriptSettingsStack {
public:
static ScriptSettingsStackEntry* Top() { return sScriptSettingsTLS.get(); }
@ -598,6 +617,9 @@ AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject,
MOZ_ASSERT(aGlobalObject);
if (aIsMainThread) {
#ifdef DEBUG
AssertIfNotSafeToRunScript();
#endif
if (gRunToCompletionListeners > 0) {
mDocShellEntryMonitor.emplace(cx(), aReason);
}
@ -751,4 +773,35 @@ void AutoSlowOperation::CheckForInterrupt() {
}
}
AutoAllowLegacyScriptExecution::AutoAllowLegacyScriptExecution() {
#ifdef DEBUG
// no need to do that dance if we are off the main thread,
// because we only assert if we are on the main thread!
if (!NS_IsMainThread()) {
return;
}
sAutoAllowLegacyScriptExecution++;
#endif
}
AutoAllowLegacyScriptExecution::~AutoAllowLegacyScriptExecution() {
#ifdef DEBUG
// no need to do that dance if we are off the main thread,
// because we only assert if we are on the main thread!
if (!NS_IsMainThread()) {
return;
}
sAutoAllowLegacyScriptExecution--;
MOZ_ASSERT(sAutoAllowLegacyScriptExecution >= 0,
"how can the stack guard produce a value less than 0?");
#endif
}
int AutoAllowLegacyScriptExecution::sAutoAllowLegacyScriptExecution = 0;
/*static*/
bool AutoAllowLegacyScriptExecution::IsAllowed() {
return sAutoAllowLegacyScriptExecution > 0;
}
} // namespace mozilla

Просмотреть файл

@ -494,6 +494,22 @@ class MOZ_RAII AutoDisableJSInterruptCallback {
bool mOld;
};
/**
* A helper class which allows to allow-list legacy callers executing script
* in the AutoEntryScript constructor. The goal is to remove these exceptions
* one by one. Do not add a new one without review from a DOM peer.
*/
class MOZ_RAII AutoAllowLegacyScriptExecution {
public:
AutoAllowLegacyScriptExecution();
~AutoAllowLegacyScriptExecution();
static bool IsAllowed();
private:
static int sAutoAllowLegacyScriptExecution;
};
} // namespace mozilla
#endif // mozilla_dom_ScriptSettings_h

Просмотреть файл

@ -823,6 +823,7 @@ nsresult mozJSComponentLoader::ObjectForLocation(
aTableScript.set(script);
{ // Scope for AutoEntryScript
AutoAllowLegacyScriptExecution exemption;
// We're going to run script via JS_ExecuteScript, so we need an
// AutoEntryScript. This is Gecko-specific and not in any spec.

Просмотреть файл

@ -332,6 +332,9 @@ nsresult nsXPCWrappedJS::DelegatedQueryInterface(REFNSIID aIID,
nsIGlobalObject* nativeGlobal = NativeGlobal(js::UncheckedUnwrap(obj));
NS_ENSURE_TRUE(nativeGlobal, NS_ERROR_FAILURE);
NS_ENSURE_TRUE(nativeGlobal->HasJSGlobal(), NS_ERROR_FAILURE);
AutoAllowLegacyScriptExecution exemption;
AutoEntryScript aes(nativeGlobal, "XPCWrappedJS QueryInterface",
/* aIsMainThread = */ true);
XPCCallContext ccx(aes.cx());
@ -772,6 +775,9 @@ nsXPCWrappedJS::CallMethod(uint16_t methodIndex, const nsXPTMethodInfo* info,
// definitely will be when we turn off XPConnect for the web.
RootedObject obj(RootingCx(), GetJSObject());
nsIGlobalObject* nativeGlobal = NativeGlobal(js::UncheckedUnwrap(obj));
AutoAllowLegacyScriptExecution exemption;
AutoEntryScript aes(nativeGlobal, "XPCWrappedJS method call",
/* aIsMainThread = */ true);
XPCCallContext ccx(aes.cx());