mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-28 04:35:33 +00:00
Merge inbound to central, a=merge
MozReview-Commit-ID: AhUhSIjf0BX
This commit is contained in:
commit
5f00a2d1ab
@ -383,8 +383,6 @@
|
||||
@RESPATH@/browser/components/devtools-startup.js
|
||||
@RESPATH@/browser/components/aboutdebugging-registration.js
|
||||
@RESPATH@/browser/components/aboutdebugging.manifest
|
||||
@RESPATH@/browser/components/webideCli.js
|
||||
@RESPATH@/browser/components/webideComponents.manifest
|
||||
@RESPATH@/browser/components/Experiments.manifest
|
||||
@RESPATH@/browser/components/ExperimentsService.js
|
||||
@RESPATH@/browser/components/browser-newtab.xpt
|
||||
|
@ -1,10 +0,0 @@
|
||||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'webideCli.js',
|
||||
'webideComponents.manifest',
|
||||
]
|
@ -1,58 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm");
|
||||
|
||||
/**
|
||||
* Handles --webide command line option.
|
||||
*/
|
||||
|
||||
function webideCli() { }
|
||||
|
||||
webideCli.prototype = {
|
||||
handle: function (cmdLine) {
|
||||
if (!cmdLine.handleFlag("webide", false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If --webide is used remotely, we don't want to open
|
||||
// a new tab.
|
||||
//
|
||||
// If --webide is used for a new Firefox instance, we
|
||||
// want to open webide only.
|
||||
cmdLine.preventDefault = true;
|
||||
|
||||
let win = Services.wm.getMostRecentWindow("devtools:webide");
|
||||
if (win) {
|
||||
win.focus();
|
||||
} else {
|
||||
win = Services.ww.openWindow(null,
|
||||
"chrome://webide/content/",
|
||||
"webide",
|
||||
"chrome,centerscreen,resizable,dialog=no",
|
||||
null);
|
||||
}
|
||||
|
||||
if (cmdLine.state == Ci.nsICommandLine.STATE_INITIAL_LAUNCH) {
|
||||
// If this is a new Firefox instance, and because we will only start
|
||||
// webide, we need to notify "sessionstore-windows-restored" to trigger
|
||||
// addons registration (for simulators and adb helper).
|
||||
Services.obs.notifyObservers(null, "sessionstore-windows-restored");
|
||||
}
|
||||
},
|
||||
|
||||
helpInfo: "",
|
||||
|
||||
classID: Components.ID("{79b7b44e-de5e-4e4c-b7a2-044003c615d9}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsICommandLineHandler]),
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([webideCli]);
|
@ -1,4 +0,0 @@
|
||||
# webide components
|
||||
component {79b7b44e-de5e-4e4c-b7a2-044003c615d9} webideCli.js
|
||||
contract @mozilla.org/browser/webide-clh;1 {79b7b44e-de5e-4e4c-b7a2-044003c615d9}
|
||||
category command-line-handler a-webide @mozilla.org/browser/webide-clh;1
|
@ -6,7 +6,6 @@
|
||||
|
||||
DIRS += [
|
||||
'content',
|
||||
'components',
|
||||
'modules',
|
||||
'themes',
|
||||
]
|
||||
|
@ -197,7 +197,8 @@ Link::LinkState() const
|
||||
|
||||
// If we have not yet registered for notifications and need to,
|
||||
// due to our href changing, register now!
|
||||
if (!mRegistered && mNeedsRegistration && element->IsInComposedDoc()) {
|
||||
if (!mRegistered && mNeedsRegistration && element->IsInComposedDoc() &&
|
||||
!HasPendingLinkUpdate()) {
|
||||
// Only try and register once.
|
||||
self->mNeedsRegistration = false;
|
||||
|
||||
|
@ -126,7 +126,7 @@ public:
|
||||
void TryDNSPrefetchPreconnectOrPrefetchOrPrerender();
|
||||
void CancelPrefetch();
|
||||
|
||||
bool HasPendingLinkUpdate() { return mHasPendingLinkUpdate; }
|
||||
bool HasPendingLinkUpdate() const { return mHasPendingLinkUpdate; }
|
||||
void SetHasPendingLinkUpdate() { mHasPendingLinkUpdate = true; }
|
||||
void ClearHasPendingLinkUpdate() { mHasPendingLinkUpdate = false; }
|
||||
|
||||
|
@ -245,6 +245,9 @@ public:
|
||||
|
||||
RefPtr<WebSocketEventService> mService;
|
||||
|
||||
// For dispatching runnables to main thread.
|
||||
nsCOMPtr<nsIEventTarget> mMainThreadEventTarget;
|
||||
|
||||
private:
|
||||
~WebSocketImpl()
|
||||
{
|
||||
@ -1872,6 +1875,10 @@ WebSocketImpl::InitializeConnection(nsIPrincipal* aPrincipal)
|
||||
|
||||
mChannel = wsChannel;
|
||||
|
||||
if (mIsMainThread && doc) {
|
||||
mMainThreadEventTarget = doc->EventTargetFor(TaskCategory::Other);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2844,9 +2851,12 @@ NS_IMETHODIMP
|
||||
WebSocketImpl::Dispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aFlags)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> event_ref(aEvent);
|
||||
// If the target is the main-thread we can just dispatch the runnable.
|
||||
// If the target is the main-thread, we should try to dispatch the runnable
|
||||
// to a labeled event target.
|
||||
if (mIsMainThread) {
|
||||
return NS_DispatchToMainThread(event_ref.forget());
|
||||
return mMainThreadEventTarget
|
||||
? mMainThreadEventTarget->Dispatch(event_ref.forget())
|
||||
: GetMainThreadEventTarget()->Dispatch(event_ref.forget());
|
||||
}
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
@ -11,7 +11,7 @@
|
||||
}
|
||||
</script>
|
||||
<body onload="loadHandler();">
|
||||
<iframe src="data:text/html,<input>"></iframe>
|
||||
<iframe srcdoc="<input>"></iframe>
|
||||
<input></input>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -11,6 +11,6 @@
|
||||
}
|
||||
</script>
|
||||
<body>
|
||||
<iframe onload="frameLoadHandler();" src="data:text/html,<input autofocus>"></iframe>
|
||||
<iframe onload="frameLoadHandler();" srcdoc="<input autofocus>"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -9,6 +9,6 @@
|
||||
document.documentElement.className = "";
|
||||
}
|
||||
</script>
|
||||
<iframe id=frame onload="loadFrame()" src="data:text/html,<body><span lang='en'>text</span></body>" marginwidth="100px" marginheight="100px" width=300px height=300px></iframe>
|
||||
<iframe id=frame onload="loadFrame()" srcdoc="<body><span lang='en'>text</span></body>" marginwidth="100px" marginheight="100px" width=300px height=300px></iframe>
|
||||
</body>
|
||||
</html>
|
@ -11,6 +11,6 @@
|
||||
document.documentElement.className = "";
|
||||
}
|
||||
</script>
|
||||
<iframe id=frame onload="loadFrame()" src="data:text/html,<body lang='en'>text</body>" marginwidth="100px" marginheight="100px" width=300px height=300px></iframe>
|
||||
<iframe id=frame onload="loadFrame()" srcdoc="<body lang='en'>text</body>" marginwidth="100px" marginheight="100px" width=300px height=300px></iframe>
|
||||
</body>
|
||||
</html>
|
@ -43,7 +43,7 @@ async protocol PWebAuthnTransaction {
|
||||
async RequestSign(WebAuthnTransactionInfo aTransactionInfo);
|
||||
async RequestCancel();
|
||||
child:
|
||||
async ConfirmRegister(uint8_t[] RegBuffer, uint8_t[] SigBuffer);
|
||||
async ConfirmRegister(uint8_t[] RegBuffer);
|
||||
async ConfirmSign(uint8_t[] CredentialID, uint8_t[] ReplyBuffer);
|
||||
async Cancel(nsresult Error);
|
||||
};
|
||||
|
@ -40,8 +40,7 @@ RefPtr<ResultPromise>
|
||||
U2FHIDTokenManager::Register(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
|
||||
const nsTArray<uint8_t>& aApplication,
|
||||
const nsTArray<uint8_t>& aChallenge,
|
||||
/* out */ nsTArray<uint8_t>& aRegistration,
|
||||
/* out */ nsTArray<uint8_t>& aSignature)
|
||||
/* out */ nsTArray<uint8_t>& aRegistration)
|
||||
{
|
||||
return ResultPromise::CreateAndReject(NS_ERROR_NOT_IMPLEMENTED, __func__);
|
||||
}
|
||||
|
@ -26,8 +26,7 @@ public:
|
||||
Register(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
|
||||
const nsTArray<uint8_t>& aApplication,
|
||||
const nsTArray<uint8_t>& aChallenge,
|
||||
/* out */ nsTArray<uint8_t>& aRegistration,
|
||||
/* out */ nsTArray<uint8_t>& aSignature) override;
|
||||
/* out */ nsTArray<uint8_t>& aRegistration) override;
|
||||
|
||||
virtual RefPtr<ResultPromise>
|
||||
Sign(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
|
||||
|
@ -637,8 +637,7 @@ RefPtr<ResultPromise>
|
||||
U2FSoftTokenManager::Register(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
|
||||
const nsTArray<uint8_t>& aApplication,
|
||||
const nsTArray<uint8_t>& aChallenge,
|
||||
/* out */ nsTArray<uint8_t>& aRegistration,
|
||||
/* out */ nsTArray<uint8_t>& aSignature)
|
||||
/* out */ nsTArray<uint8_t>& aRegistration)
|
||||
{
|
||||
nsNSSShutDownPreventionLock locker;
|
||||
if (NS_WARN_IF(isAlreadyShutDown())) {
|
||||
|
@ -29,8 +29,7 @@ public:
|
||||
Register(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
|
||||
const nsTArray<uint8_t>& aApplication,
|
||||
const nsTArray<uint8_t>& aChallenge,
|
||||
/* out */ nsTArray<uint8_t>& aRegistration,
|
||||
/* out */ nsTArray<uint8_t>& aSignature) override;
|
||||
/* out */ nsTArray<uint8_t>& aRegistration) override;
|
||||
|
||||
virtual RefPtr<ResultPromise>
|
||||
Sign(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
|
||||
|
@ -252,18 +252,16 @@ U2FTokenManager::Register(WebAuthnTransactionParent* aTransactionParent,
|
||||
}
|
||||
|
||||
nsTArray<uint8_t> reg;
|
||||
nsTArray<uint8_t> sig;
|
||||
mResultPromise = mTokenManagerImpl->Register(aTransactionInfo.Descriptors(),
|
||||
aTransactionInfo.RpIdHash(),
|
||||
aTransactionInfo.ClientDataHash(),
|
||||
reg,
|
||||
sig);
|
||||
reg);
|
||||
|
||||
mResultPromise->Then(GetCurrentThreadSerialEventTarget(), __func__,
|
||||
[tid, reg, sig](nsresult rv) {
|
||||
[tid, reg](nsresult rv) {
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
U2FTokenManager* mgr = U2FTokenManager::Get();
|
||||
mgr->MaybeConfirmRegister(tid, reg, sig);
|
||||
mgr->MaybeConfirmRegister(tid, reg);
|
||||
},
|
||||
[tid](nsresult rv) {
|
||||
MOZ_ASSERT(NS_FAILED(rv));
|
||||
@ -274,14 +272,13 @@ U2FTokenManager::Register(WebAuthnTransactionParent* aTransactionParent,
|
||||
|
||||
void
|
||||
U2FTokenManager::MaybeConfirmRegister(uint64_t aTransactionId,
|
||||
const nsTArray<uint8_t>& aRegister,
|
||||
const nsTArray<uint8_t>& aSignature)
|
||||
const nsTArray<uint8_t>& aRegister)
|
||||
{
|
||||
if (mTransactionId != aTransactionId) {
|
||||
return;
|
||||
}
|
||||
|
||||
Unused << mTransactionParent->SendConfirmRegister(aRegister, aSignature);
|
||||
Unused << mTransactionParent->SendConfirmRegister(aRegister);
|
||||
ClearTransaction();
|
||||
}
|
||||
|
||||
|
@ -52,8 +52,7 @@ private:
|
||||
void MaybeAbortTransaction(uint64_t aTransactionId,
|
||||
const nsresult& aError);
|
||||
void MaybeConfirmRegister(uint64_t aTransactionId,
|
||||
const nsTArray<uint8_t>& aRegister,
|
||||
const nsTArray<uint8_t>& aSignature);
|
||||
const nsTArray<uint8_t>& aRegister);
|
||||
void MaybeConfirmSign(uint64_t aTransactionId,
|
||||
const nsTArray<uint8_t>& aKeyHandle,
|
||||
const nsTArray<uint8_t>& aSignature);
|
||||
|
@ -30,8 +30,7 @@ public:
|
||||
Register(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
|
||||
const nsTArray<uint8_t>& aApplication,
|
||||
const nsTArray<uint8_t>& aChallenge,
|
||||
/* out */ nsTArray<uint8_t>& aRegistration,
|
||||
/* out */ nsTArray<uint8_t>& aSignature) = 0;
|
||||
/* out */ nsTArray<uint8_t>& aRegistration) = 0;
|
||||
|
||||
virtual RefPtr<ResultPromise>
|
||||
Sign(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
|
||||
|
@ -610,8 +610,7 @@ WebAuthnManager::GetAssertion(nsPIDOMWindowInner* aParent,
|
||||
}
|
||||
|
||||
void
|
||||
WebAuthnManager::FinishMakeCredential(nsTArray<uint8_t>& aRegBuffer,
|
||||
nsTArray<uint8_t>& aSigBuffer)
|
||||
WebAuthnManager::FinishMakeCredential(nsTArray<uint8_t>& aRegBuffer)
|
||||
{
|
||||
MOZ_ASSERT(mTransactionPromise);
|
||||
MOZ_ASSERT(mInfo.isSome());
|
||||
@ -635,12 +634,6 @@ WebAuthnManager::FinishMakeCredential(nsTArray<uint8_t>& aRegBuffer,
|
||||
return;
|
||||
}
|
||||
|
||||
CryptoBuffer signatureData;
|
||||
if (NS_WARN_IF(!signatureData.Assign(aSigBuffer.Elements(), aSigBuffer.Length()))) {
|
||||
Cancel(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
CryptoBuffer clientDataBuf;
|
||||
if (!clientDataBuf.Assign(mClientData.ref())) {
|
||||
Cancel(NS_ERROR_OUT_OF_MEMORY);
|
||||
@ -655,7 +648,7 @@ WebAuthnManager::FinishMakeCredential(nsTArray<uint8_t>& aRegBuffer,
|
||||
|
||||
CryptoBuffer authenticatorDataBuf;
|
||||
rv = U2FAssembleAuthenticatorData(authenticatorDataBuf, rpIdHashBuf,
|
||||
signatureData);
|
||||
signatureBuf);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
Cancel(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
|
@ -62,8 +62,7 @@ public:
|
||||
static WebAuthnManager* Get();
|
||||
|
||||
void
|
||||
FinishMakeCredential(nsTArray<uint8_t>& aRegBuffer,
|
||||
nsTArray<uint8_t>& aSigBuffer);
|
||||
FinishMakeCredential(nsTArray<uint8_t>& aRegBuffer);
|
||||
|
||||
void
|
||||
FinishGetAssertion(nsTArray<uint8_t>& aCredentialId,
|
||||
|
@ -19,12 +19,11 @@ WebAuthnTransactionChild::WebAuthnTransactionChild()
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
WebAuthnTransactionChild::RecvConfirmRegister(nsTArray<uint8_t>&& aRegBuffer,
|
||||
nsTArray<uint8_t>&& aSigBuffer)
|
||||
WebAuthnTransactionChild::RecvConfirmRegister(nsTArray<uint8_t>&& aRegBuffer)
|
||||
{
|
||||
RefPtr<WebAuthnManager> mgr = WebAuthnManager::Get();
|
||||
MOZ_ASSERT(mgr);
|
||||
mgr->FinishMakeCredential(aRegBuffer, aSigBuffer);
|
||||
mgr->FinishMakeCredential(aRegBuffer);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,7 @@ class WebAuthnTransactionChild final : public PWebAuthnTransactionChild
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(WebAuthnTransactionChild);
|
||||
WebAuthnTransactionChild();
|
||||
mozilla::ipc::IPCResult RecvConfirmRegister(nsTArray<uint8_t>&& aRegBuffer,
|
||||
nsTArray<uint8_t>&& aSigBuffer) override;
|
||||
mozilla::ipc::IPCResult RecvConfirmRegister(nsTArray<uint8_t>&& aRegBuffer) override;
|
||||
mozilla::ipc::IPCResult RecvConfirmSign(nsTArray<uint8_t>&& aCredentialId,
|
||||
nsTArray<uint8_t>&& aBuffer) override;
|
||||
mozilla::ipc::IPCResult RecvCancel(const nsresult& aError) override;
|
||||
|
@ -16,7 +16,7 @@
|
||||
<body>
|
||||
<p id="text">normal text</p>
|
||||
<iframe id="editor" onload="doTest();"
|
||||
src="data:text/html,<body>editable text</body>"></iframe>
|
||||
srcdoc="<body>editable text</body>"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
<body>
|
||||
<p id="text">normal text</p>
|
||||
<iframe id="editor" onload="doTest();"
|
||||
src="data:text/html,<script>document.designMode='on';</script><body>editable text</body>"></iframe>
|
||||
srcdoc="<script>document.designMode='on';</script><body>editable text</body>"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
<p id="text">normal text</p>
|
||||
<div>content editable</div>
|
||||
<iframe id="editor" onload="doTest();"
|
||||
src="data:text/html,<body>editable text</body>"></iframe>
|
||||
srcdoc="<body>editable text</body>"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
<p>normal text</p>
|
||||
<div id="editor1" contenteditable>content editable</div>
|
||||
<iframe id="editor2" onload="doTest();"
|
||||
src="data:text/html,<script>document.designMode='on';</script><body>editable text</body>"></iframe>
|
||||
srcdoc="<script>document.designMode='on';</script><body>editable text</body>"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<body>
|
||||
<iframe src="data:text/html,<body><div></div></body>"></iframe>
|
||||
<iframe srcdoc="<body><div></div></body>"></iframe>
|
||||
<script type="text/javascript">
|
||||
onload = function() {
|
||||
var i = document.querySelector("iframe");
|
||||
|
@ -2,7 +2,7 @@
|
||||
<html>
|
||||
<body>
|
||||
<div style="position: absolute">
|
||||
<iframe src="data:text/html,<body contenteditable>foo</body>"></iframe>
|
||||
<iframe srcdoc="<body contenteditable>foo</body>"></iframe>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
onload = function() {
|
||||
|
@ -2,7 +2,7 @@
|
||||
<html>
|
||||
<body>
|
||||
<div>
|
||||
<iframe src="data:text/html,<body contenteditable>foo</body>"></iframe>
|
||||
<iframe srcdoc="<body contenteditable>foo</body>"></iframe>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
onload = function() {
|
||||
|
@ -37,6 +37,10 @@ public:
|
||||
|
||||
bool ComputeResizeFilter(ResizeMethod aResizeMethod, int32_t aSrcSize, int32_t aDstSize);
|
||||
|
||||
static inline size_t PadBytesForSIMD(size_t aBytes) {
|
||||
return (aBytes + 31) & ~31;
|
||||
}
|
||||
|
||||
private:
|
||||
UniquePtr<SkConvolutionFilter1D> mFilter;
|
||||
};
|
||||
|
@ -105,8 +105,8 @@ Downscaler::BeginFrame(const nsIntSize& aOriginalSize,
|
||||
}
|
||||
|
||||
// Allocate the buffer, which contains scanlines of the original image.
|
||||
// pad by 15 to handle overreads by the simd code
|
||||
size_t bufferLen = mOriginalSize.width * sizeof(uint32_t) + 15;
|
||||
// pad to handle overreads by the simd code
|
||||
size_t bufferLen = gfx::ConvolutionFilter::PadBytesForSIMD(mOriginalSize.width * sizeof(uint32_t));
|
||||
mRowBuffer.reset(new (fallible) uint8_t[bufferLen]);
|
||||
if (MOZ_UNLIKELY(!mRowBuffer)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
@ -125,8 +125,8 @@ Downscaler::BeginFrame(const nsIntSize& aOriginalSize,
|
||||
}
|
||||
|
||||
bool anyAllocationFailed = false;
|
||||
// pad by 15 to handle overreads by the simd code
|
||||
const int rowSize = mTargetSize.width * sizeof(uint32_t) + 15;
|
||||
// pad to handle overreads by the simd code
|
||||
const size_t rowSize = gfx::ConvolutionFilter::PadBytesForSIMD(mTargetSize.width * sizeof(uint32_t));
|
||||
for (int32_t i = 0; i < mWindowCapacity; ++i) {
|
||||
mWindow[i] = new (fallible) uint8_t[rowSize];
|
||||
anyAllocationFailed = anyAllocationFailed || mWindow[i] == nullptr;
|
||||
|
@ -177,7 +177,7 @@ public:
|
||||
// either valid or nullptr. That in turn ensures that ReleaseWindow() can
|
||||
// clean up correctly.
|
||||
bool anyAllocationFailed = false;
|
||||
const uint32_t windowRowSizeInBytes = PaddedWidthInBytes(outputSize.width);
|
||||
const size_t windowRowSizeInBytes = PaddedWidthInBytes(outputSize.width);
|
||||
for (int32_t i = 0; i < mWindowCapacity; ++i) {
|
||||
mWindow[i] = new (fallible) uint8_t[windowRowSizeInBytes];
|
||||
anyAllocationFailed = anyAllocationFailed || mWindow[i] == nullptr;
|
||||
@ -261,11 +261,11 @@ protected:
|
||||
private:
|
||||
uint8_t* GetRowPointer() const { return mRowBuffer.get(); }
|
||||
|
||||
static uint32_t PaddedWidthInBytes(uint32_t aLogicalWidth)
|
||||
static size_t PaddedWidthInBytes(size_t aLogicalWidth)
|
||||
{
|
||||
// Convert from width in BGRA/BGRX pixels to width in bytes, padding by 15
|
||||
// Convert from width in BGRA/BGRX pixels to width in bytes, padding
|
||||
// to handle overreads by the SIMD code inside Skia.
|
||||
return aLogicalWidth * sizeof(uint32_t) + 15;
|
||||
return gfx::ConvolutionFilter::PadBytesForSIMD(aLogicalWidth * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
void DownscaleInputRow()
|
||||
|
16
image/test/crashtests/1375842-1.html
Normal file
16
image/test/crashtests/1375842-1.html
Normal file
@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<style>
|
||||
textarea {
|
||||
border: red;
|
||||
transform: rotate(-0.01rad);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<textarea></textarea>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -25,6 +25,7 @@ load 1242778-1.png
|
||||
load 1249576-1.png
|
||||
load 1253362-1.html
|
||||
load 1355898-1.html
|
||||
load 1375842-1.html
|
||||
load colormap-range.gif
|
||||
HTTP load delayedframe.sjs # A 3-frame animated GIF with an inordinate delay between the second and third frame
|
||||
|
||||
|
@ -795,9 +795,9 @@ ScheduleGC(JSContext* cx, unsigned argc, Value* vp)
|
||||
|
||||
if (args.length() == 0) {
|
||||
/* Fetch next zeal trigger only. */
|
||||
} else if (args[0].isInt32()) {
|
||||
} else if (args[0].isNumber()) {
|
||||
/* Schedule a GC to happen after |arg| allocations. */
|
||||
JS_ScheduleGC(cx, args[0].toInt32());
|
||||
JS_ScheduleGC(cx, std::max(int(args[0].toNumber()), 0));
|
||||
} else if (args[0].isObject()) {
|
||||
/* Ensure that |zone| is collected during the next GC. */
|
||||
Zone* zone = UncheckedUnwrap(&args[0].toObject())->zone();
|
||||
@ -813,7 +813,7 @@ ScheduleGC(JSContext* cx, unsigned argc, Value* vp)
|
||||
PrepareZoneForGC(zone);
|
||||
} else {
|
||||
RootedObject callee(cx, &args.callee());
|
||||
ReportUsageErrorASCII(cx, callee, "Bad argument - expecting integer, object or string");
|
||||
ReportUsageErrorASCII(cx, callee, "Bad argument - expecting number, object or string");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,12 @@ class ChunkPool
|
||||
|
||||
public:
|
||||
ChunkPool() : head_(nullptr), count_(0) {}
|
||||
~ChunkPool() {
|
||||
// TODO: We should be able to assert that the chunk pool is empty but
|
||||
// this causes XPCShell test failures on Windows 2012. See bug 1379232.
|
||||
}
|
||||
|
||||
bool empty() const { return !head_; }
|
||||
size_t count() const { return count_; }
|
||||
|
||||
Chunk* head() { MOZ_ASSERT(head_); return head_; }
|
||||
|
@ -882,23 +882,15 @@ Statistics::endGC()
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_SCC_SWEEP_TOTAL_MS, t(sccTotal));
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_SCC_SWEEP_MAX_PAUSE_MS, t(sccLongest));
|
||||
|
||||
if (!aborted) {
|
||||
TimeDuration total, longest;
|
||||
gcDuration(&total, &longest);
|
||||
TimeDuration total, longest;
|
||||
gcDuration(&total, &longest);
|
||||
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_MS, t(total));
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_MAX_PAUSE_MS, t(longest));
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_MAX_PAUSE_MS_2, t(longest));
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_MS, t(total));
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_MAX_PAUSE_MS, t(longest));
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_MAX_PAUSE_MS_2, t(longest));
|
||||
|
||||
const double mmu50 = computeMMU(TimeDuration::FromMilliseconds(50));
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_MMU_50, mmu50 * 100);
|
||||
}
|
||||
|
||||
if (fp)
|
||||
printStats();
|
||||
|
||||
// Clear the OOM flag.
|
||||
aborted = false;
|
||||
const double mmu50 = computeMMU(TimeDuration::FromMilliseconds(50));
|
||||
runtime->addTelemetry(JS_TELEMETRY_GC_MMU_50, mmu50 * 100);
|
||||
thresholdTriggered = false;
|
||||
}
|
||||
|
||||
@ -994,8 +986,13 @@ Statistics::endSlice()
|
||||
}
|
||||
|
||||
bool last = !runtime->gc.isIncrementalGCInProgress();
|
||||
if (last)
|
||||
endGC();
|
||||
if (last) {
|
||||
if (fp)
|
||||
printStats();
|
||||
|
||||
if (!aborted)
|
||||
endGC();
|
||||
}
|
||||
|
||||
if (enableProfiling_ && !aborted && slices_.back().duration() >= profileThreshold_)
|
||||
printSliceProfile();
|
||||
@ -1025,6 +1022,8 @@ Statistics::endSlice()
|
||||
phaseStartTimes[Phase::MUTATOR] = mutatorStartTime;
|
||||
phaseTimes[Phase::MUTATOR] = mutatorTime;
|
||||
}
|
||||
|
||||
aborted = false;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1132,8 +1131,18 @@ Statistics::recordPhaseBegin(Phase phase)
|
||||
MOZ_ASSERT(phases[phase].parent == current);
|
||||
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
if (current != Phase::NONE)
|
||||
|
||||
if (current != Phase::NONE) {
|
||||
#ifdef ANDROID
|
||||
// Sadly this happens sometimes.
|
||||
if (now < phaseStartTimes[currentPhase()]) {
|
||||
now = phaseStartTimes[currentPhase()];
|
||||
aborted = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
MOZ_RELEASE_ASSERT(now >= phaseStartTimes[currentPhase()]);
|
||||
}
|
||||
|
||||
phaseStack.infallibleAppend(phase);
|
||||
phaseStartTimes[phase] = now;
|
||||
@ -1147,6 +1156,15 @@ Statistics::recordPhaseEnd(Phase phase)
|
||||
MOZ_ASSERT(phaseStartTimes[phase]);
|
||||
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
|
||||
#ifdef ANDROID
|
||||
// Sadly this happens sometimes.
|
||||
if (now < phaseStartTimes[phase]) {
|
||||
now = phaseStartTimes[phase];
|
||||
aborted = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
MOZ_RELEASE_ASSERT(now >= phaseStartTimes[phase]);
|
||||
|
||||
if (phase == Phase::MUTATOR)
|
||||
|
@ -334,8 +334,8 @@ struct Statistics
|
||||
JS::GCNurseryCollectionCallback nurseryCollectionCallback;
|
||||
|
||||
/*
|
||||
* True if we saw an OOM while allocating slices. The statistics for this
|
||||
* GC will be invalid.
|
||||
* True if we saw an OOM while allocating slices or we saw an impossible
|
||||
* timestamp. The statistics for this GC will be invalid.
|
||||
*/
|
||||
bool aborted;
|
||||
|
||||
|
@ -65,10 +65,11 @@ using namespace js::jit;
|
||||
* The tempN registers are free to use for computations.
|
||||
*/
|
||||
|
||||
NativeRegExpMacroAssembler::NativeRegExpMacroAssembler(JSContext* cx, LifoAlloc* alloc, RegExpShared* shared,
|
||||
Mode mode, int registers_to_save)
|
||||
: RegExpMacroAssembler(cx, *alloc, shared, registers_to_save),
|
||||
cx(cx), mode_(mode)
|
||||
NativeRegExpMacroAssembler::NativeRegExpMacroAssembler(JSContext* cx, LifoAlloc* alloc,
|
||||
Mode mode, int registers_to_save,
|
||||
RegExpShared::JitCodeTables& tables)
|
||||
: RegExpMacroAssembler(cx, *alloc, registers_to_save),
|
||||
tables(tables), cx(cx), mode_(mode)
|
||||
{
|
||||
// Find physical registers for each compiler register.
|
||||
AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
|
||||
@ -931,11 +932,11 @@ NativeRegExpMacroAssembler::CheckCharacterNotInRange(char16_t from, char16_t to,
|
||||
}
|
||||
|
||||
void
|
||||
NativeRegExpMacroAssembler::CheckBitInTable(uint8_t* table, Label* on_bit_set)
|
||||
NativeRegExpMacroAssembler::CheckBitInTable(RegExpShared::JitCodeTable table, Label* on_bit_set)
|
||||
{
|
||||
JitSpew(SPEW_PREFIX "CheckBitInTable");
|
||||
|
||||
masm.movePtr(ImmPtr(table), temp0);
|
||||
masm.movePtr(ImmPtr(table.get()), temp0);
|
||||
|
||||
// kTableMask is currently 127, so we need to mask even if the input is
|
||||
// Latin1. V8 has the same issue.
|
||||
@ -946,6 +947,13 @@ NativeRegExpMacroAssembler::CheckBitInTable(uint8_t* table, Label* on_bit_set)
|
||||
|
||||
masm.load8ZeroExtend(BaseIndex(temp0, temp1, TimesOne), temp0);
|
||||
masm.branchTest32(Assembler::NonZero, temp0, temp0, BranchOrBacktrack(on_bit_set));
|
||||
|
||||
// Transfer ownership of |table| to the |tables| Vector.
|
||||
{
|
||||
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||
if (!tables.append(Move(table)))
|
||||
oomUnsafe.crash("RegExp table append");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -88,8 +88,8 @@ class MOZ_STACK_CLASS NativeRegExpMacroAssembler final : public RegExpMacroAssem
|
||||
// Type of input string to generate code for.
|
||||
enum Mode { LATIN1 = 1, CHAR16 = 2 };
|
||||
|
||||
NativeRegExpMacroAssembler(JSContext* cx, LifoAlloc* alloc, RegExpShared* shared,
|
||||
Mode mode, int registers_to_save);
|
||||
NativeRegExpMacroAssembler(JSContext* cx, LifoAlloc* alloc, Mode mode, int registers_to_save,
|
||||
RegExpShared::JitCodeTables& tables);
|
||||
|
||||
// Inherited virtual methods.
|
||||
RegExpCode GenerateCode(JSContext* cx, bool match_only);
|
||||
@ -116,7 +116,7 @@ class MOZ_STACK_CLASS NativeRegExpMacroAssembler final : public RegExpMacroAssem
|
||||
jit::Label* on_in_range);
|
||||
void CheckCharacterNotInRange(char16_t from, char16_t to,
|
||||
jit::Label* on_not_in_range);
|
||||
void CheckBitInTable(uint8_t* table, jit::Label* on_bit_set);
|
||||
void CheckBitInTable(RegExpShared::JitCodeTable table, jit::Label* on_bit_set);
|
||||
void CheckPosition(int cp_offset, jit::Label* on_outside_input);
|
||||
void JumpOrBacktrack(jit::Label* to);
|
||||
bool CheckSpecialCharacterClass(char16_t type, jit::Label* on_no_match);
|
||||
@ -173,6 +173,7 @@ class MOZ_STACK_CLASS NativeRegExpMacroAssembler final : public RegExpMacroAssem
|
||||
|
||||
private:
|
||||
jit::MacroAssembler masm;
|
||||
RegExpShared::JitCodeTables& tables;
|
||||
|
||||
JSContext* cx;
|
||||
Mode mode_;
|
||||
|
@ -1734,7 +1734,7 @@ RegExpCode
|
||||
irregexp::CompilePattern(JSContext* cx, HandleRegExpShared shared, RegExpCompileData* data,
|
||||
HandleLinearString sample, bool is_global, bool ignore_case,
|
||||
bool is_latin1, bool match_only, bool force_bytecode, bool sticky,
|
||||
bool unicode)
|
||||
bool unicode, RegExpShared::JitCodeTables& tables)
|
||||
{
|
||||
if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) {
|
||||
JS_ReportErrorASCII(cx, "regexp too big");
|
||||
@ -1829,10 +1829,10 @@ irregexp::CompilePattern(JSContext* cx, HandleRegExpShared shared, RegExpCompile
|
||||
: NativeRegExpMacroAssembler::CHAR16;
|
||||
|
||||
ctx.emplace(cx, (jit::TempAllocator*) nullptr);
|
||||
native_assembler.emplace(cx, &alloc, shared, mode, (data->capture_count + 1) * 2);
|
||||
native_assembler.emplace(cx, &alloc, mode, (data->capture_count + 1) * 2, tables);
|
||||
assembler = native_assembler.ptr();
|
||||
} else {
|
||||
interpreted_assembler.emplace(cx, &alloc, shared, (data->capture_count + 1) * 2);
|
||||
interpreted_assembler.emplace(cx, &alloc, (data->capture_count + 1) * 2);
|
||||
assembler = interpreted_assembler.ptr();
|
||||
}
|
||||
|
||||
@ -2513,21 +2513,21 @@ BoyerMooreLookahead::EmitSkipInstructions(RegExpMacroAssembler* masm)
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t* boolean_skip_table;
|
||||
RegExpShared::JitCodeTable boolean_skip_table;
|
||||
{
|
||||
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||
boolean_skip_table = static_cast<uint8_t*>(js_malloc(kSize));
|
||||
if (!boolean_skip_table || !masm->shared->addTable(boolean_skip_table))
|
||||
boolean_skip_table.reset(static_cast<uint8_t*>(js_malloc(kSize)));
|
||||
if (!boolean_skip_table)
|
||||
oomUnsafe.crash("Table malloc");
|
||||
}
|
||||
|
||||
int skip_distance = GetSkipTable(min_lookahead, max_lookahead, boolean_skip_table);
|
||||
int skip_distance = GetSkipTable(min_lookahead, max_lookahead, boolean_skip_table.get());
|
||||
MOZ_ASSERT(skip_distance != 0);
|
||||
|
||||
jit::Label cont, again;
|
||||
masm->Bind(&again);
|
||||
masm->LoadCurrentCharacter(max_lookahead, &cont, true);
|
||||
masm->CheckBitInTable(boolean_skip_table, &cont);
|
||||
masm->CheckBitInTable(Move(boolean_skip_table), &cont);
|
||||
masm->AdvanceCurrentPosition(skip_distance);
|
||||
masm->JumpOrBacktrack(&again);
|
||||
masm->Bind(&cont);
|
||||
@ -3308,18 +3308,18 @@ EmitUseLookupTable(RegExpMacroAssembler* masm,
|
||||
}
|
||||
|
||||
// TODO(erikcorry): Cache these.
|
||||
uint8_t* ba;
|
||||
RegExpShared::JitCodeTable ba;
|
||||
{
|
||||
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||
ba = static_cast<uint8_t*>(js_malloc(kSize));
|
||||
if (!ba || !masm->shared->addTable(ba))
|
||||
ba.reset(static_cast<uint8_t*>(js_malloc(kSize)));
|
||||
if (!ba)
|
||||
oomUnsafe.crash("Table malloc");
|
||||
}
|
||||
|
||||
for (int i = 0; i < kSize; i++)
|
||||
ba[i] = templ[i];
|
||||
|
||||
masm->CheckBitInTable(ba, on_bit_set);
|
||||
masm->CheckBitInTable(Move(ba), on_bit_set);
|
||||
if (on_bit_clear != fall_through)
|
||||
masm->JumpOrBacktrack(on_bit_clear);
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ RegExpCode
|
||||
CompilePattern(JSContext* cx, HandleRegExpShared shared, RegExpCompileData* data,
|
||||
HandleLinearString sample, bool is_global, bool ignore_case,
|
||||
bool is_latin1, bool match_only, bool force_bytecode, bool sticky,
|
||||
bool unicode);
|
||||
bool unicode, RegExpShared::JitCodeTables& tables);
|
||||
|
||||
// Note: this may return RegExpRunStatus_Error if an interrupt was requested
|
||||
// while the code was executing.
|
||||
|
@ -98,9 +98,8 @@ irregexp::CaseInsensitiveCompareUCStrings(const char16_t* substring1,
|
||||
size_t byteLength);
|
||||
|
||||
InterpretedRegExpMacroAssembler::InterpretedRegExpMacroAssembler(JSContext* cx, LifoAlloc* alloc,
|
||||
RegExpShared* shared,
|
||||
size_t numSavedRegisters)
|
||||
: RegExpMacroAssembler(cx, *alloc, shared, numSavedRegisters),
|
||||
: RegExpMacroAssembler(cx, *alloc, numSavedRegisters),
|
||||
pc_(0),
|
||||
advance_current_start_(0),
|
||||
advance_current_offset_(0),
|
||||
@ -313,7 +312,8 @@ InterpretedRegExpMacroAssembler::CheckCharacterNotInRange(char16_t from, char16_
|
||||
}
|
||||
|
||||
void
|
||||
InterpretedRegExpMacroAssembler::CheckBitInTable(uint8_t* table, jit::Label* on_bit_set)
|
||||
InterpretedRegExpMacroAssembler::CheckBitInTable(RegExpShared::JitCodeTable table,
|
||||
jit::Label* on_bit_set)
|
||||
{
|
||||
static const int kBitsPerByte = 8;
|
||||
|
||||
|
@ -41,14 +41,12 @@ namespace irregexp {
|
||||
class MOZ_STACK_CLASS RegExpMacroAssembler
|
||||
{
|
||||
public:
|
||||
RegExpMacroAssembler(JSContext* cx, LifoAlloc& alloc, RegExpShared* shared,
|
||||
size_t numSavedRegisters)
|
||||
RegExpMacroAssembler(JSContext* cx, LifoAlloc& alloc, size_t numSavedRegisters)
|
||||
: slow_safe_compiler_(false),
|
||||
global_mode_(NOT_GLOBAL),
|
||||
alloc_(alloc),
|
||||
num_registers_(numSavedRegisters),
|
||||
num_saved_registers_(numSavedRegisters),
|
||||
shared(cx, shared)
|
||||
num_saved_registers_(numSavedRegisters)
|
||||
{}
|
||||
|
||||
enum StackCheckFlag {
|
||||
@ -138,7 +136,7 @@ class MOZ_STACK_CLASS RegExpMacroAssembler
|
||||
|
||||
// The current character (modulus the kTableSize) is looked up in the byte
|
||||
// array, and if the found byte is non-zero, we jump to the on_bit_set label.
|
||||
virtual void CheckBitInTable(uint8_t* table, jit::Label* on_bit_set) = 0;
|
||||
virtual void CheckBitInTable(RegExpShared::JitCodeTable table, jit::Label* on_bit_set) = 0;
|
||||
|
||||
// Checks whether the given offset from the current position is before
|
||||
// the end of the string. May overwrite the current character.
|
||||
@ -214,9 +212,6 @@ class MOZ_STACK_CLASS RegExpMacroAssembler
|
||||
if (num_registers_ <= reg)
|
||||
num_registers_ = reg + 1;
|
||||
}
|
||||
|
||||
public:
|
||||
RootedRegExpShared shared;
|
||||
};
|
||||
|
||||
template <typename CharT>
|
||||
@ -231,8 +226,7 @@ CaseInsensitiveCompareUCStrings(const CharT* substring1, const CharT* substring2
|
||||
class MOZ_STACK_CLASS InterpretedRegExpMacroAssembler final : public RegExpMacroAssembler
|
||||
{
|
||||
public:
|
||||
InterpretedRegExpMacroAssembler(JSContext* cx, LifoAlloc* alloc, RegExpShared* shared,
|
||||
size_t numSavedRegisters);
|
||||
InterpretedRegExpMacroAssembler(JSContext* cx, LifoAlloc* alloc, size_t numSavedRegisters);
|
||||
~InterpretedRegExpMacroAssembler();
|
||||
|
||||
// Inherited virtual methods.
|
||||
@ -258,7 +252,7 @@ class MOZ_STACK_CLASS InterpretedRegExpMacroAssembler final : public RegExpMacro
|
||||
jit::Label* on_in_range);
|
||||
void CheckCharacterNotInRange(char16_t from, char16_t to,
|
||||
jit::Label* on_not_in_range);
|
||||
void CheckBitInTable(uint8_t* table, jit::Label* on_bit_set);
|
||||
void CheckBitInTable(RegExpShared::JitCodeTable table, jit::Label* on_bit_set);
|
||||
void JumpOrBacktrack(jit::Label* to);
|
||||
void Fail();
|
||||
void IfRegisterGE(int reg, int comparand, jit::Label* if_ge);
|
||||
|
@ -0,0 +1,17 @@
|
||||
var g = newGlobal();
|
||||
var w = g.eval("() => {}");
|
||||
var v = g.eval("Array");
|
||||
|
||||
try {
|
||||
Reflect.construct(Array, [], w);
|
||||
assertEq(true, false, "Expected exception above");
|
||||
} catch (e) {
|
||||
assertEq(e.constructor, TypeError);
|
||||
}
|
||||
|
||||
try {
|
||||
Reflect.construct(v, [], w);
|
||||
assertEq(true, false, "Expected exception above");
|
||||
} catch (e) {
|
||||
assertEq(e.constructor, TypeError);
|
||||
}
|
@ -328,7 +328,7 @@ DoTypeUpdateFallback(JSContext* cx, BaselineFrame* frame, ICUpdatedStub* stub, H
|
||||
AddTypePropertyId(cx, group, maybeSingleton, id, value);
|
||||
}
|
||||
|
||||
if (MOZ_UNLIKELY(!stub->addUpdateStubForValue(cx, script, obj, id, value))) {
|
||||
if (MOZ_UNLIKELY(!stub->addUpdateStubForValue(cx, script, obj, group, id, value))) {
|
||||
// The calling JIT code assumes this function is infallible (for
|
||||
// instance we may reallocate dynamic slots before calling this),
|
||||
// so ignore OOMs if we failed to attach a stub.
|
||||
|
@ -2637,20 +2637,22 @@ ICTypeMonitor_AnyValue::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
|
||||
bool
|
||||
ICUpdatedStub::addUpdateStubForValue(JSContext* cx, HandleScript outerScript, HandleObject obj,
|
||||
HandleId id, HandleValue val)
|
||||
HandleObjectGroup group, HandleId id, HandleValue val)
|
||||
{
|
||||
EnsureTrackPropertyTypes(cx, obj, id);
|
||||
|
||||
// Make sure that undefined values are explicitly included in the property
|
||||
// types for an object if generating a stub to write an undefined value.
|
||||
if (val.isUndefined() && CanHaveEmptyPropertyTypesForOwnProperty(obj))
|
||||
if (val.isUndefined() && CanHaveEmptyPropertyTypesForOwnProperty(obj)) {
|
||||
MOZ_ASSERT(obj->group() == group);
|
||||
AddTypePropertyId(cx, obj, id, val);
|
||||
}
|
||||
|
||||
bool unknown = false, unknownObject = false;
|
||||
if (obj->group()->unknownProperties()) {
|
||||
if (group->unknownProperties()) {
|
||||
unknown = unknownObject = true;
|
||||
} else {
|
||||
if (HeapTypeSet* types = obj->group()->maybeGetProperty(id)) {
|
||||
if (HeapTypeSet* types = group->maybeGetProperty(id)) {
|
||||
unknown = types->unknown();
|
||||
unknownObject = types->unknownObject();
|
||||
} else {
|
||||
|
@ -939,7 +939,7 @@ class ICUpdatedStub : public ICStub
|
||||
MOZ_MUST_USE bool initUpdatingChain(JSContext* cx, ICStubSpace* space);
|
||||
|
||||
MOZ_MUST_USE bool addUpdateStubForValue(JSContext* cx, HandleScript script, HandleObject obj,
|
||||
HandleId id, HandleValue val);
|
||||
HandleObjectGroup group, HandleId id, HandleValue val);
|
||||
|
||||
void addOptimizedUpdateStub(ICStub* stub) {
|
||||
if (firstUpdateStub_->isTypeUpdate_Fallback()) {
|
||||
|
@ -35,6 +35,12 @@ BEGIN_TEST(testGCFinalizeCallback)
|
||||
CHECK(checkFinalizeStatus());
|
||||
CHECK(checkFinalizeIsZoneGC(false));
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
// Bug 1377593 - the below tests want to control how many zones are GC'ing,
|
||||
// and some zeal modes will convert them into all-zones GCs.
|
||||
JS_SetGCZeal(cx, 0, 0);
|
||||
#endif
|
||||
|
||||
JS::RootedObject global1(cx, createTestGlobal());
|
||||
JS::RootedObject global2(cx, createTestGlobal());
|
||||
JS::RootedObject global3(cx, createTestGlobal());
|
||||
|
@ -1193,10 +1193,10 @@ GCRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes)
|
||||
void
|
||||
GCRuntime::finish()
|
||||
{
|
||||
/* Wait for the nursery sweeping to end. */
|
||||
for (ZoneGroupsIter group(rt); !group.done(); group.next()) {
|
||||
if (group->nursery().isEnabled())
|
||||
group->nursery().waitBackgroundFreeEnd();
|
||||
/* Wait for nursery background free to end and disable it to release memory. */
|
||||
if (nursery().isEnabled()) {
|
||||
nursery().waitBackgroundFreeEnd();
|
||||
nursery().disable();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -178,11 +178,6 @@ IsMarkingTrace(JSTracer* trc)
|
||||
void
|
||||
RegExpObject::trace(JSTracer* trc)
|
||||
{
|
||||
// When marking the object normally we have the option of unlinking the
|
||||
// object from its RegExpShared so that the RegExpShared may be collected.
|
||||
if (IsMarkingTrace(trc) && !zone()->isPreservingCode())
|
||||
sharedRef() = nullptr;
|
||||
|
||||
TraceNullableEdge(trc, &sharedRef(), "RegExpObject shared");
|
||||
}
|
||||
|
||||
@ -966,6 +961,9 @@ RegExpShared::discardJitCode()
|
||||
{
|
||||
for (auto& comp : compilationArray)
|
||||
comp.jitCode = nullptr;
|
||||
|
||||
// We can also purge the tables used by JIT code.
|
||||
tables.clearAndFree();
|
||||
}
|
||||
|
||||
void
|
||||
@ -973,8 +971,6 @@ RegExpShared::finalize(FreeOp* fop)
|
||||
{
|
||||
for (auto& comp : compilationArray)
|
||||
js_free(comp.byteCode);
|
||||
for (size_t i = 0; i < tables.length(); i++)
|
||||
js_free(tables[i]);
|
||||
tables.~JitCodeTables();
|
||||
}
|
||||
|
||||
@ -1012,6 +1008,7 @@ RegExpShared::compile(JSContext* cx, MutableHandleRegExpShared re, HandleAtom pa
|
||||
|
||||
re->parenCount = data.capture_count;
|
||||
|
||||
JitCodeTables tables;
|
||||
irregexp::RegExpCode code = irregexp::CompilePattern(cx, re, &data, input,
|
||||
false /* global() */,
|
||||
re->ignoreCase(),
|
||||
@ -1019,7 +1016,8 @@ RegExpShared::compile(JSContext* cx, MutableHandleRegExpShared re, HandleAtom pa
|
||||
mode == MatchOnly,
|
||||
force == ForceByteCode,
|
||||
re->sticky(),
|
||||
re->unicode());
|
||||
re->unicode(),
|
||||
tables);
|
||||
if (code.empty())
|
||||
return false;
|
||||
|
||||
@ -1027,10 +1025,20 @@ RegExpShared::compile(JSContext* cx, MutableHandleRegExpShared re, HandleAtom pa
|
||||
MOZ_ASSERT_IF(force == ForceByteCode, code.byteCode);
|
||||
|
||||
RegExpCompilation& compilation = re->compilation(mode, input->hasLatin1Chars());
|
||||
if (code.jitCode)
|
||||
if (code.jitCode) {
|
||||
// First copy the tables. GC can purge the tables if the RegExpShared
|
||||
// has no JIT code, so it's important to do this right before setting
|
||||
// compilation.jitCode (to ensure no purging happens between adding the
|
||||
// tables and setting the JIT code).
|
||||
for (size_t i = 0; i < tables.length(); i++) {
|
||||
if (!re->addTable(Move(tables[i])))
|
||||
return false;
|
||||
}
|
||||
compilation.jitCode = code.jitCode;
|
||||
else if (code.byteCode)
|
||||
} else if (code.byteCode) {
|
||||
MOZ_ASSERT(tables.empty(), "RegExpInterpreter does not use data tables");
|
||||
compilation.byteCode = code.byteCode;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1186,7 +1194,7 @@ RegExpShared::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
|
||||
|
||||
n += tables.sizeOfExcludingThis(mallocSizeOf);
|
||||
for (size_t i = 0; i < tables.length(); i++)
|
||||
n += mallocSizeOf(tables[i]);
|
||||
n += mallocSizeOf(tables[i].get());
|
||||
|
||||
return n;
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ class RegExpObject : public NativeObject
|
||||
|
||||
void setShared(RegExpShared& shared) {
|
||||
MOZ_ASSERT(!hasShared());
|
||||
sharedRef() = &shared;
|
||||
sharedRef().init(&shared);
|
||||
}
|
||||
|
||||
static void trace(JSTracer* trc, JSObject* obj);
|
||||
@ -178,9 +178,9 @@ class RegExpObject : public NativeObject
|
||||
static MOZ_MUST_USE bool createShared(JSContext* cx, Handle<RegExpObject*> regexp,
|
||||
MutableHandleRegExpShared shared);
|
||||
|
||||
ReadBarriered<RegExpShared*>& sharedRef() {
|
||||
PreBarriered<RegExpShared*>& sharedRef() {
|
||||
auto& ref = NativeObject::privateRef(PRIVATE_SLOT);
|
||||
return reinterpret_cast<ReadBarriered<RegExpShared*>&>(ref);
|
||||
return reinterpret_cast<PreBarriered<RegExpShared*>&>(ref);
|
||||
}
|
||||
|
||||
/* Call setShared in preference to setPrivate. */
|
||||
|
@ -96,6 +96,9 @@ class RegExpShared : public gc::TenuredCell
|
||||
ForceByteCode
|
||||
};
|
||||
|
||||
using JitCodeTable = UniquePtr<uint8_t[], JS::FreePolicy>;
|
||||
using JitCodeTables = Vector<JitCodeTable, 0, SystemAllocPolicy>;
|
||||
|
||||
private:
|
||||
friend class RegExpStatics;
|
||||
friend class RegExpZone;
|
||||
@ -130,7 +133,6 @@ class RegExpShared : public gc::TenuredCell
|
||||
}
|
||||
|
||||
// Tables referenced by JIT code.
|
||||
using JitCodeTables = Vector<uint8_t*, 0, SystemAllocPolicy>;
|
||||
JitCodeTables tables;
|
||||
|
||||
/* Internal functions. */
|
||||
@ -163,8 +165,8 @@ class RegExpShared : public gc::TenuredCell
|
||||
MatchPairs* matches, size_t* endIndex);
|
||||
|
||||
// Register a table with this RegExpShared, and take ownership.
|
||||
bool addTable(uint8_t* table) {
|
||||
return tables.append(table);
|
||||
bool addTable(JitCodeTable table) {
|
||||
return tables.append(Move(table));
|
||||
}
|
||||
|
||||
/* Accessors */
|
||||
|
@ -185,7 +185,22 @@ static bool
|
||||
intrinsic_IsConstructor(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
args.rval().setBoolean(IsConstructor(args[0]));
|
||||
MOZ_ASSERT(args.length() == 1);
|
||||
|
||||
RootedValue val(cx, args[0]);
|
||||
if (!IsConstructor(val)) {
|
||||
args.rval().setBoolean(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
RootedObject obj(cx, &val.toObject());
|
||||
if (!IsWrapper(obj)) {
|
||||
args.rval().setBoolean(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
obj = UncheckedUnwrap(obj);
|
||||
args.rval().setBoolean(obj && obj->isConstructor());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -160,8 +160,10 @@ JSDependentString::new_(JSContext* cx, JSLinearString* baseArg, size_t start,
|
||||
* entirely, however, due to how ropes are flattened.
|
||||
*/
|
||||
if (baseArg->isDependent()) {
|
||||
start += baseArg->asDependent().baseOffset();
|
||||
baseArg = baseArg->asDependent().base();
|
||||
if (mozilla::Maybe<size_t> offset = baseArg->asDependent().baseOffset()) {
|
||||
start += *offset;
|
||||
baseArg = baseArg->asDependent().base();
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(start + length <= baseArg->length());
|
||||
|
@ -719,7 +719,9 @@ JSDependentString::dumpRepresentation(FILE* fp, int indent) const
|
||||
dumpRepresentationHeader(fp, indent, "JSDependentString");
|
||||
indent += 2;
|
||||
|
||||
fprintf(fp, "%*soffset: %" PRIuSIZE "\n", indent, "", baseOffset());
|
||||
if (mozilla::Maybe<size_t> offset = baseOffset())
|
||||
fprintf(fp, "%*soffset: %" PRIuSIZE "\n", indent, "", *offset);
|
||||
|
||||
fprintf(fp, "%*sbase: ", indent, "");
|
||||
base()->dumpRepresentation(fp, indent);
|
||||
}
|
||||
|
@ -724,16 +724,18 @@ class JSDependentString : public JSLinearString
|
||||
JSDependentString& asDependent() const = delete;
|
||||
|
||||
/* The offset of this string's chars in base->chars(). */
|
||||
size_t baseOffset() const {
|
||||
MOZ_ALWAYS_INLINE mozilla::Maybe<size_t> baseOffset() const {
|
||||
MOZ_ASSERT(JSString::isDependent());
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
if (MOZ_UNLIKELY(base()->isUndepended()))
|
||||
return mozilla::Nothing();
|
||||
size_t offset;
|
||||
if (hasTwoByteChars())
|
||||
offset = twoByteChars(nogc) - base()->twoByteChars(nogc);
|
||||
else
|
||||
offset = latin1Chars(nogc) - base()->latin1Chars(nogc);
|
||||
MOZ_ASSERT(offset < base()->length());
|
||||
return offset;
|
||||
return mozilla::Some(offset);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -2540,7 +2540,7 @@ SizeComputationInput::InitOffsets(WritingMode aWM,
|
||||
const nsMargin* aPadding,
|
||||
const nsStyleDisplay* aDisplay)
|
||||
{
|
||||
DISPLAY_INIT_OFFSETS(mFrame, this, aPercentBasis, aBorder, aPadding);
|
||||
DISPLAY_INIT_OFFSETS(mFrame, this, aPercentBasis, aWM, aBorder, aPadding);
|
||||
|
||||
// Since we are in reflow, we don't need to store these properties anymore
|
||||
// unless they are dependent on width, in which case we store the new value.
|
||||
|
@ -247,6 +247,7 @@ public:
|
||||
nsIFrame* aFrame,
|
||||
SizeComputationInput* aState,
|
||||
const mozilla::LogicalSize& aPercentBasis,
|
||||
WritingMode aCBWritingMode,
|
||||
const nsMargin* aBorder,
|
||||
const nsMargin* aPadding);
|
||||
static void DisplayInitOffsetsExit(nsIFrame* aFrame,
|
||||
|
@ -10918,8 +10918,9 @@ DR_init_constraints_cookie::~DR_init_constraints_cookie()
|
||||
|
||||
DR_init_offsets_cookie::DR_init_offsets_cookie(
|
||||
nsIFrame* aFrame,
|
||||
SizeComputationInput* aState,
|
||||
SizeComputationInput* aState,
|
||||
const LogicalSize& aPercentBasis,
|
||||
WritingMode aCBWritingMode,
|
||||
const nsMargin* aMargin,
|
||||
const nsMargin* aPadding)
|
||||
: mFrame(aFrame)
|
||||
@ -10927,8 +10928,9 @@ DR_init_offsets_cookie::DR_init_offsets_cookie(
|
||||
{
|
||||
MOZ_COUNT_CTOR(DR_init_offsets_cookie);
|
||||
mValue = SizeComputationInput::DisplayInitOffsetsEnter(mFrame, mState,
|
||||
aPercentBasis,
|
||||
aMargin, aPadding);
|
||||
aPercentBasis,
|
||||
aCBWritingMode,
|
||||
aMargin, aPadding);
|
||||
}
|
||||
|
||||
DR_init_offsets_cookie::~DR_init_offsets_cookie()
|
||||
@ -11878,6 +11880,7 @@ ReflowInput::DisplayInitConstraintsExit(nsIFrame* aFrame,
|
||||
SizeComputationInput::DisplayInitOffsetsEnter(nsIFrame* aFrame,
|
||||
SizeComputationInput* aState,
|
||||
const LogicalSize& aPercentBasis,
|
||||
WritingMode aCBWritingMode,
|
||||
const nsMargin* aBorder,
|
||||
const nsMargin* aPadding)
|
||||
{
|
||||
@ -11894,9 +11897,10 @@ SizeComputationInput::DisplayInitOffsetsEnter(nsIFrame* aFrame,
|
||||
|
||||
char horizPctBasisStr[16];
|
||||
char vertPctBasisStr[16];
|
||||
WritingMode wm = aState->GetWritingMode();
|
||||
DR_state->PrettyUC(aPercentBasis.ISize(wm), horizPctBasisStr, 16);
|
||||
DR_state->PrettyUC(aPercentBasis.BSize(wm), vertPctBasisStr, 16);
|
||||
DR_state->PrettyUC(aPercentBasis.ISize(aCBWritingMode),
|
||||
horizPctBasisStr, 16);
|
||||
DR_state->PrettyUC(aPercentBasis.BSize(aCBWritingMode),
|
||||
vertPctBasisStr, 16);
|
||||
printf("InitOffsets pct_basis=%s,%s", horizPctBasisStr, vertPctBasisStr);
|
||||
|
||||
DR_state->PrintMargin("b", aBorder);
|
||||
|
@ -865,6 +865,7 @@ public:
|
||||
struct DR_init_offsets_cookie {
|
||||
DR_init_offsets_cookie(nsIFrame* aFrame, mozilla::SizeComputationInput* aState,
|
||||
const mozilla::LogicalSize& aPercentBasis,
|
||||
mozilla::WritingMode aCBWritingMode,
|
||||
const nsMargin* aBorder,
|
||||
const nsMargin* aPadding);
|
||||
~DR_init_offsets_cookie();
|
||||
@ -903,8 +904,10 @@ public:
|
||||
dr_bdr, dr_pad) \
|
||||
DR_init_constraints_cookie dr_cookie(dr_frame, dr_state, dr_cbw, dr_cbh, \
|
||||
dr_bdr, dr_pad)
|
||||
#define DISPLAY_INIT_OFFSETS(dr_frame, dr_state, dr_pb, dr_bdr, dr_pad) \
|
||||
DR_init_offsets_cookie dr_cookie(dr_frame, dr_state, dr_pb, dr_bdr, dr_pad)
|
||||
#define DISPLAY_INIT_OFFSETS(dr_frame, dr_state, dr_pb, dr_cbwm, dr_bdr, \
|
||||
dr_pad) \
|
||||
DR_init_offsets_cookie dr_cookie(dr_frame, dr_state, dr_pb, dr_cbwm, \
|
||||
dr_bdr, dr_pad)
|
||||
#define DISPLAY_INIT_TYPE(dr_frame, dr_result) \
|
||||
DR_init_type_cookie dr_cookie(dr_frame, dr_result)
|
||||
|
||||
@ -921,7 +924,8 @@ public:
|
||||
#define DISPLAY_INIT_CONSTRAINTS(dr_frame, dr_state, dr_cbw, dr_cbh, \
|
||||
dr_bdr, dr_pad) \
|
||||
PR_BEGIN_MACRO PR_END_MACRO
|
||||
#define DISPLAY_INIT_OFFSETS(dr_frame, dr_state, dr_pb, dr_bdr, dr_pad) \
|
||||
#define DISPLAY_INIT_OFFSETS(dr_frame, dr_state, dr_pb, dr_cbwm, dr_bdr, \
|
||||
dr_pad) \
|
||||
PR_BEGIN_MACRO PR_END_MACRO
|
||||
#define DISPLAY_INIT_TYPE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<iframe id="foo" src="data:text/html,<body bgcolor='lime'>PASS</body>"></iframe>
|
||||
<iframe id="foo" srcdoc="<body bgcolor='lime'>PASS</body>"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<body>
|
||||
<iframe id="foo" src="data:text/html,<body bgcolor='red'>FAIL</body>"></iframe>
|
||||
<iframe id="foo" srcdoc="<body bgcolor='red'>FAIL</body>"></iframe>
|
||||
<script type="text/javascript">
|
||||
// Globals
|
||||
var foo = document.getElementById('foo');
|
||||
|
@ -13,6 +13,9 @@
|
||||
#include "SandboxFilter.h"
|
||||
#include "SandboxInternal.h"
|
||||
#include "SandboxLogging.h"
|
||||
#ifdef MOZ_GMP_SANDBOX
|
||||
#include "SandboxOpenedFiles.h"
|
||||
#endif
|
||||
#include "SandboxReporterClient.h"
|
||||
#include "SandboxUtil.h"
|
||||
|
||||
@ -34,9 +37,12 @@
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "mozilla/Array.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/Range.h"
|
||||
#include "mozilla/SandboxInfo.h"
|
||||
#include "mozilla/Span.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "sandbox/linux/bpf_dsl/codegen.h"
|
||||
@ -82,13 +88,6 @@ static bool gSandboxCrashOnError = false;
|
||||
// This is initialized by SandboxSetCrashFunc().
|
||||
SandboxCrashFunc gSandboxCrashFunc;
|
||||
|
||||
#ifdef MOZ_GMP_SANDBOX
|
||||
// For media plugins, we can start the sandbox before we dlopen the
|
||||
// module, so we have to pre-open the file and simulate the sandboxed
|
||||
// open().
|
||||
static SandboxOpenedFile gMediaPluginFile;
|
||||
#endif
|
||||
|
||||
static Maybe<SandboxReporterClient> gSandboxReporterClient;
|
||||
static UniquePtr<SandboxChroot> gChrootHelper;
|
||||
static void (*gChromiumSigSysHandler)(int, siginfo_t*, void*);
|
||||
@ -713,26 +712,32 @@ SetContentProcessSandbox(int aBrokerFd, std::vector<int>& aSyscallWhitelist)
|
||||
void
|
||||
SetMediaPluginSandbox(const char *aFilePath)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(aFilePath != nullptr);
|
||||
if (!SandboxInfo::Get().Test(SandboxInfo::kEnabledForMedia)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gSandboxReporterClient.emplace(SandboxReport::ProcType::MEDIA_PLUGIN);
|
||||
|
||||
MOZ_ASSERT(!gMediaPluginFile.mPath);
|
||||
if (aFilePath) {
|
||||
gMediaPluginFile.mPath = strdup(aFilePath);
|
||||
gMediaPluginFile.mFd = open(aFilePath, O_RDONLY | O_CLOEXEC);
|
||||
if (gMediaPluginFile.mFd == -1) {
|
||||
SANDBOX_LOG_ERROR("failed to open plugin file %s: %s",
|
||||
aFilePath, strerror(errno));
|
||||
MOZ_CRASH();
|
||||
}
|
||||
} else {
|
||||
gMediaPluginFile.mFd = -1;
|
||||
SandboxOpenedFile plugin(aFilePath);
|
||||
if (!plugin.IsOpen()) {
|
||||
SANDBOX_LOG_ERROR("failed to open plugin file %s: %s",
|
||||
aFilePath, strerror(errno));
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
auto files = new SandboxOpenedFiles();
|
||||
files->Add(Move(plugin));
|
||||
files->Add("/dev/urandom", true);
|
||||
files->Add("/sys/devices/system/cpu/cpu0/tsc_freq_khz");
|
||||
files->Add("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq");
|
||||
files->Add("/proc/cpuinfo"); // Info also available via CPUID instruction.
|
||||
#ifdef __i386__
|
||||
files->Add("/proc/self/auxv"); // Info also in process's address space.
|
||||
#endif
|
||||
|
||||
// Finally, start the sandbox.
|
||||
SetCurrentProcessSandbox(GetMediaSandboxPolicy(&gMediaPluginFile));
|
||||
SetCurrentProcessSandbox(GetMediaSandboxPolicy(files));
|
||||
}
|
||||
#endif // MOZ_GMP_SANDBOX
|
||||
|
||||
|
@ -11,6 +11,10 @@
|
||||
#include "SandboxInfo.h"
|
||||
#include "SandboxInternal.h"
|
||||
#include "SandboxLogging.h"
|
||||
#ifdef MOZ_GMP_SANDBOX
|
||||
#include "SandboxOpenedFiles.h"
|
||||
#endif
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
#include <errno.h>
|
||||
@ -23,6 +27,7 @@
|
||||
#include <sys/mman.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
@ -893,7 +898,7 @@ class GMPSandboxPolicy : public SandboxPolicyCommon {
|
||||
static intptr_t OpenTrap(const sandbox::arch_seccomp_data& aArgs,
|
||||
void* aux)
|
||||
{
|
||||
auto plugin = static_cast<SandboxOpenedFile*>(aux);
|
||||
const auto files = static_cast<const SandboxOpenedFiles*>(aux);
|
||||
const char* path;
|
||||
int flags;
|
||||
|
||||
@ -914,20 +919,15 @@ class GMPSandboxPolicy : public SandboxPolicyCommon {
|
||||
MOZ_CRASH("unexpected syscall number");
|
||||
}
|
||||
|
||||
if (strcmp(path, plugin->mPath) != 0) {
|
||||
SANDBOX_LOG_ERROR("attempt to open file %s (flags=0%o) which is not the"
|
||||
" media plugin %s", path, flags, plugin->mPath);
|
||||
return -EPERM;
|
||||
}
|
||||
if ((flags & O_ACCMODE) != O_RDONLY) {
|
||||
SANDBOX_LOG_ERROR("non-read-only open of file %s attempted (flags=0%o)",
|
||||
path, flags);
|
||||
return -EPERM;
|
||||
return -EROFS;
|
||||
}
|
||||
int fd = plugin->mFd.exchange(-1);
|
||||
int fd = files->GetDesc(path);
|
||||
if (fd < 0) {
|
||||
SANDBOX_LOG_ERROR("multiple opens of media plugin file unimplemented");
|
||||
return -ENOSYS;
|
||||
// SandboxOpenedFile::GetDesc already logged about this, if appropriate.
|
||||
return -ENOENT;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
@ -949,14 +949,40 @@ class GMPSandboxPolicy : public SandboxPolicyCommon {
|
||||
return BlockedSyscallTrap(aArgs, nullptr);
|
||||
}
|
||||
|
||||
SandboxOpenedFile* mPlugin;
|
||||
public:
|
||||
explicit GMPSandboxPolicy(SandboxOpenedFile* aPlugin)
|
||||
: mPlugin(aPlugin)
|
||||
static intptr_t UnameTrap(const sandbox::arch_seccomp_data& aArgs,
|
||||
void* aux)
|
||||
{
|
||||
MOZ_ASSERT(aPlugin->mPath[0] == '/', "plugin path should be absolute");
|
||||
const auto buf = reinterpret_cast<struct utsname*>(aArgs.args[0]);
|
||||
PodZero(buf);
|
||||
// The real uname() increases fingerprinting risk for no benefit.
|
||||
// This is close enough.
|
||||
strcpy(buf->sysname, "Linux");
|
||||
strcpy(buf->version, "3");
|
||||
return 0;
|
||||
};
|
||||
|
||||
static intptr_t FcntlTrap(const sandbox::arch_seccomp_data& aArgs,
|
||||
void* aux)
|
||||
{
|
||||
const auto cmd = static_cast<int>(aArgs.args[1]);
|
||||
switch (cmd) {
|
||||
// This process can't exec, so the actual close-on-exec flag
|
||||
// doesn't matter; have it always read as true and ignore writes.
|
||||
case F_GETFD:
|
||||
return O_CLOEXEC;
|
||||
case F_SETFD:
|
||||
return 0;
|
||||
default:
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
const SandboxOpenedFiles* mFiles;
|
||||
public:
|
||||
explicit GMPSandboxPolicy(const SandboxOpenedFiles* aFiles)
|
||||
: mFiles(aFiles)
|
||||
{ }
|
||||
|
||||
~GMPSandboxPolicy() override = default;
|
||||
|
||||
ResultExpr EvaluateSyscall(int sysno) const override {
|
||||
@ -966,7 +992,7 @@ public:
|
||||
case __NR_open:
|
||||
#endif
|
||||
case __NR_openat:
|
||||
return Trap(OpenTrap, mPlugin);
|
||||
return Trap(OpenTrap, mFiles);
|
||||
|
||||
// ipc::Shmem
|
||||
case __NR_mprotect:
|
||||
@ -999,6 +1025,15 @@ public:
|
||||
case __NR_times:
|
||||
return Allow();
|
||||
|
||||
// Bug 1372428
|
||||
case __NR_uname:
|
||||
return Trap(UnameTrap, nullptr);
|
||||
CASES_FOR_fcntl:
|
||||
return Trap(FcntlTrap, nullptr);
|
||||
|
||||
case __NR_dup:
|
||||
return Allow();
|
||||
|
||||
default:
|
||||
return SandboxPolicyCommon::EvaluateSyscall(sysno);
|
||||
}
|
||||
@ -1006,11 +1041,11 @@ public:
|
||||
};
|
||||
|
||||
UniquePtr<sandbox::bpf_dsl::Policy>
|
||||
GetMediaSandboxPolicy(SandboxOpenedFile* aPlugin)
|
||||
GetMediaSandboxPolicy(const SandboxOpenedFiles* aFiles)
|
||||
{
|
||||
return UniquePtr<sandbox::bpf_dsl::Policy>(new GMPSandboxPolicy(aPlugin));
|
||||
return UniquePtr<sandbox::bpf_dsl::Policy>(new GMPSandboxPolicy(aFiles));
|
||||
}
|
||||
|
||||
#endif // MOZ_GMP_SANDBOX
|
||||
|
||||
}
|
||||
} // namespace mozilla
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Range.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
namespace sandbox {
|
||||
@ -27,12 +28,10 @@ UniquePtr<sandbox::bpf_dsl::Policy> GetContentSandboxPolicy(SandboxBrokerClient*
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_GMP_SANDBOX
|
||||
struct SandboxOpenedFile {
|
||||
const char *mPath;
|
||||
Atomic<int> mFd;
|
||||
};
|
||||
class SandboxOpenedFiles;
|
||||
|
||||
UniquePtr<sandbox::bpf_dsl::Policy> GetMediaSandboxPolicy(SandboxOpenedFile* aPlugin);
|
||||
// The SandboxOpenedFiles object must live until the process exits.
|
||||
UniquePtr<sandbox::bpf_dsl::Policy> GetMediaSandboxPolicy(const SandboxOpenedFiles* aFiles);
|
||||
#endif
|
||||
|
||||
} // namespace mozilla
|
||||
|
79
security/sandbox/linux/SandboxOpenedFiles.cpp
Normal file
79
security/sandbox/linux/SandboxOpenedFiles.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "SandboxOpenedFiles.h"
|
||||
|
||||
#include "mozilla/Move.h"
|
||||
#include "SandboxLogging.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// The default move constructor almost works, but Atomic isn't
|
||||
// move-constructable and the fd needs some special handling.
|
||||
SandboxOpenedFile::SandboxOpenedFile(SandboxOpenedFile&& aMoved)
|
||||
: mPath(Move(aMoved.mPath))
|
||||
, mMaybeFd(aMoved.TakeDesc())
|
||||
, mDup(aMoved.mDup)
|
||||
, mExpectError(aMoved.mExpectError)
|
||||
{ }
|
||||
|
||||
SandboxOpenedFile::SandboxOpenedFile(const char* aPath, bool aDup)
|
||||
: mPath(aPath), mDup(aDup), mExpectError(false)
|
||||
{
|
||||
MOZ_ASSERT(aPath[0] == '/', "path should be absolute");
|
||||
|
||||
int fd = open(aPath, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
mExpectError = true;
|
||||
}
|
||||
mMaybeFd = fd;
|
||||
}
|
||||
|
||||
int
|
||||
SandboxOpenedFile::GetDesc() const
|
||||
{
|
||||
int fd = -1;
|
||||
if (mDup) {
|
||||
fd = mMaybeFd;
|
||||
if (fd >= 0) {
|
||||
fd = dup(fd);
|
||||
if (fd < 0) {
|
||||
SANDBOX_LOG_ERROR("dup: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fd = TakeDesc();
|
||||
}
|
||||
if (fd < 0 && !mExpectError) {
|
||||
SANDBOX_LOG_ERROR("unexpected multiple open of file %s", Path());
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
SandboxOpenedFile::~SandboxOpenedFile()
|
||||
{
|
||||
int fd = TakeDesc();
|
||||
if (fd >= 0) {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SandboxOpenedFiles::GetDesc(const char* aPath) const
|
||||
{
|
||||
for (const auto& file : mFiles) {
|
||||
if (strcmp(file.Path(), aPath) == 0) {
|
||||
return file.GetDesc();
|
||||
}
|
||||
}
|
||||
SANDBOX_LOG_ERROR("attempt to open unexpected file %s", aPath);
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
89
security/sandbox/linux/SandboxOpenedFiles.h
Normal file
89
security/sandbox/linux/SandboxOpenedFiles.h
Normal file
@ -0,0 +1,89 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_SandboxOpenedFiles_h
|
||||
#define mozilla_SandboxOpenedFiles_h
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Range.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
// The use of C++ standard library containers here should be safe; the
|
||||
// standard (section container.requirements.dataraces) requires that
|
||||
// using const methods/pointers not introduce data races (e.g., from
|
||||
// interior mutability or global state).
|
||||
//
|
||||
// Reentrancy isn't guaranteed, and the library could use async signal
|
||||
// unsafe mutexes for "read-only" operations, but I'm assuming that that's
|
||||
// not the case at least for simple containers like string and vector.
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// This class represents a file that's been pre-opened for a media
|
||||
// plugin. It can be move-constructed but not copied.
|
||||
class SandboxOpenedFile final {
|
||||
public:
|
||||
// This constructor opens the named file and saves the descriptor.
|
||||
// If the open fails, IsOpen() will return false and GetDesc() will
|
||||
// quietly return -1. If aDup is true, GetDesc() will return a
|
||||
// dup() of the descriptor every time it's called; otherwise, the
|
||||
// first call will return the descriptor and any further calls will
|
||||
// log an error message and return -1.
|
||||
explicit SandboxOpenedFile(const char* aPath, bool aDup = false);
|
||||
|
||||
// Simulates opening the pre-opened file; see the constructor's
|
||||
// comment for details. Does not set errno on error, but may modify
|
||||
// it as a side-effect. Thread-safe and intended to be async signal safe.
|
||||
int GetDesc() const;
|
||||
|
||||
const char* Path() const { return mPath.c_str(); }
|
||||
|
||||
bool IsOpen() const { return mMaybeFd >= 0; }
|
||||
|
||||
~SandboxOpenedFile();
|
||||
|
||||
MOZ_IMPLICIT SandboxOpenedFile(SandboxOpenedFile&& aMoved);
|
||||
|
||||
private:
|
||||
std::string mPath;
|
||||
mutable Atomic<int> mMaybeFd;
|
||||
bool mDup;
|
||||
bool mExpectError;
|
||||
|
||||
int TakeDesc() const { return mMaybeFd.exchange(-1); }
|
||||
};
|
||||
|
||||
// This class represents a collection of files to be used to handle
|
||||
// open() calls from the media plugin (and the dynamic loader).
|
||||
// Because the seccomp-bpf policy exists until the process exits, this
|
||||
// object must not be destroyed after the syscall filter is installed.
|
||||
class SandboxOpenedFiles {
|
||||
public:
|
||||
SandboxOpenedFiles() = default;
|
||||
|
||||
template<typename... Args>
|
||||
void Add(Args&&... aArgs) {
|
||||
mFiles.emplace_back(Forward<Args>(aArgs)...);
|
||||
}
|
||||
|
||||
int GetDesc(const char* aPath) const;
|
||||
|
||||
private:
|
||||
std::vector<SandboxOpenedFile> mFiles;
|
||||
|
||||
// We could allow destroying instances of this class that aren't
|
||||
// used with seccomp-bpf (e.g., for unit testing) by having the
|
||||
// destructor check a flag set by the syscall policy and crash,
|
||||
// but let's not write that code until we actually need it.
|
||||
~SandboxOpenedFiles() = delete;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_SandboxOpenedFiles_h
|
@ -72,6 +72,11 @@ SOURCES += [
|
||||
'SandboxUtil.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_GMP_SANDBOX']:
|
||||
SOURCES += [
|
||||
'SandboxOpenedFiles.cpp',
|
||||
]
|
||||
|
||||
# This copy of SafeSPrintf doesn't need to avoid the Chromium logging
|
||||
# dependency like the one in libxul does, but this way the behavior is
|
||||
# consistent. See also the comment in SandboxLogging.h.
|
||||
|
@ -288,8 +288,7 @@ Service::~Service()
|
||||
if (rc != SQLITE_OK)
|
||||
NS_WARNING("sqlite3 did not shutdown cleanly.");
|
||||
|
||||
DebugOnly<bool> shutdownObserved = !sXPConnect;
|
||||
NS_ASSERTION(shutdownObserved, "Shutdown was not observed!");
|
||||
shutdown(); // To release sXPConnect.
|
||||
|
||||
gService = nullptr;
|
||||
delete mSqliteVFS;
|
||||
|
@ -235508,15 +235508,15 @@
|
||||
"testharness"
|
||||
],
|
||||
"workers/semantics/navigation/001-1.html": [
|
||||
"2f0df288870e99e80de02fe4a09c9cac141d4559",
|
||||
"4dac7306512b047e8239c7f5c10e6b8ed83b9212",
|
||||
"support"
|
||||
],
|
||||
"workers/semantics/navigation/001.html": [
|
||||
"4a744751f35cbc67ec87ea76e22947a5f66959e9",
|
||||
"fd9870c19b051c1580b4b7b366ea5ce71541b5dc",
|
||||
"testharness"
|
||||
],
|
||||
"workers/semantics/navigation/002.html": [
|
||||
"e28d7129aa2aa8fabe3641bea8f60ecd70335fa9",
|
||||
"bc96fc2e64a3ffe6a71c314d7a65ed9a89cf440f",
|
||||
"testharness"
|
||||
],
|
||||
"workers/semantics/reporting-errors/001.html": [
|
||||
|
@ -16,7 +16,7 @@ onload = function() {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<a href='data:text/html,<title>foo</title><script>onload=function(){parent.after_load()}</script>'>link</a>
|
||||
<a href='data:text/html,<title>foo</title><script>onload=function(){window.parent.postMessage({title: window.document.title}, "*")}</script>'>link</a>
|
||||
<!--
|
||||
*/
|
||||
//-->
|
||||
|
@ -20,15 +20,17 @@ onload = function() {
|
||||
var start_test = function() {
|
||||
window[0].document.links[0].click();
|
||||
};
|
||||
var after_load = function() {
|
||||
var after_load = function(event) {
|
||||
history.back();
|
||||
newDate = new Date();
|
||||
setTimeout(function() {
|
||||
assert_greater_than(Number(date), Number(newDate));
|
||||
assert_equals(window[0].document.title, '001-1');
|
||||
window.removeEventListener("message", after_load);
|
||||
done();
|
||||
}, 2000);
|
||||
};
|
||||
window.addEventListener("message", after_load);
|
||||
</script>
|
||||
<!--
|
||||
*/
|
||||
|
@ -21,14 +21,16 @@ onload = t.step_func(function() {
|
||||
var start_test = t.step_func(function() {
|
||||
window[0].document.links[0].click();
|
||||
});
|
||||
var after_load = t.step_func(function() {
|
||||
var after_load = t.step_func(function(event) {
|
||||
newDate = new Date();
|
||||
setTimeout(this.step_func(function() {
|
||||
assert_less_than(Number(date), Number(newDate));
|
||||
assert_equals(window[0].document.title, 'foo');
|
||||
assert_equals(event.data.title, 'foo');
|
||||
window.removeEventListener("message", after_load);
|
||||
this.done();
|
||||
}), 500);
|
||||
});
|
||||
window.addEventListener("message", after_load);
|
||||
</script>
|
||||
<!--
|
||||
*/
|
||||
|
@ -10071,6 +10071,7 @@
|
||||
"description": "The amount of time spent in a specific performance tool view, keyed by view name (waterfall, js-calltree, js-flamegraph, etc)."
|
||||
},
|
||||
"DEVTOOLS_JAVASCRIPT_ERROR_DISPLAYED": {
|
||||
"alert_emails": ["nicolas.b.pierron@mozilla.com"],
|
||||
"record_in_processes": ["main", "content"],
|
||||
"bug_numbers": [1255133, 1378449],
|
||||
"expires_in_version": "never",
|
||||
|
@ -148,6 +148,7 @@ label.findbar-find-fast:-moz-lwtheme,
|
||||
|
||||
.findbar-textbox:-moz-locale-dir(rtl) {
|
||||
border-radius: 0 10000px 10000px 0;
|
||||
background-position-x: calc(100% - 5px);
|
||||
}
|
||||
|
||||
@media (-moz-mac-yosemite-theme) {
|
||||
|
Loading…
Reference in New Issue
Block a user