diff --git a/CLOBBER b/CLOBBER index b6b994231197..d5e3cbb951d5 100644 --- a/CLOBBER +++ b/CLOBBER @@ -22,4 +22,4 @@ # changes to stick? As of bug 928195, this shouldn't be necessary! Please # don't change CLOBBER for WebIDL changes any more. -Bug 897735 requires a clobber due to mass mochitest bustage otherwise +Updates to NSS seem to require a clobber due bug 959928. diff --git a/caps/idl/moz.build b/caps/idl/moz.build index d9f7b944621b..94881279d1ae 100644 --- a/caps/idl/moz.build +++ b/caps/idl/moz.build @@ -8,7 +8,6 @@ XPIDL_SOURCES += [ 'nsIDomainPolicy.idl', 'nsIPrincipal.idl', 'nsIScriptSecurityManager.idl', - 'nsISecurityCheckedComponent.idl', ] XPIDL_MODULE = 'caps' diff --git a/caps/idl/nsISecurityCheckedComponent.idl b/caps/idl/nsISecurityCheckedComponent.idl deleted file mode 100644 index 319c133fa843..000000000000 --- a/caps/idl/nsISecurityCheckedComponent.idl +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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/. */ - -/* - * Interface checked by caps to determine the capability needed to - * call methods on a component from potentially untrusted code. - * - * See also foo, which advertises whether untrusted code can get - * services and create instances. -*/ - -#include "nsISupports.idl" - -/** - * Each method of this interface should return a string representing the - * script capability needed to perform the operation on the target component. - * - * Return values of 'allAccess' or 'noAccess' unconditionally allow or deny - * access to the operation. - */ -[scriptable, uuid(0dad9e8c-a12d-4dcb-9a6f-7d09839356e1)] -interface nsISecurityCheckedComponent : nsISupports { - string canCreateWrapper(in nsIIDPtr iid); - string canCallMethod(in nsIIDPtr iid, in wstring methodName); - string canGetProperty(in nsIIDPtr iid, in wstring propertyName); - string canSetProperty(in nsIIDPtr iid, in wstring propertyName); -}; - -// could put %{ block here containing macro'ed implementations of this -// interface for component developers' convenience. diff --git a/caps/include/nsScriptSecurityManager.h b/caps/include/nsScriptSecurityManager.h index ae240abda60e..395d58b70c03 100644 --- a/caps/include/nsScriptSecurityManager.h +++ b/caps/include/nsScriptSecurityManager.h @@ -162,43 +162,6 @@ private: nsIPrincipal* GetSubjectPrincipal(JSContext* cx, nsresult* rv); - /** - * Check capability levels for an |aObj| that implements - * nsISecurityCheckedComponent. - * - * NB: This function also checks to see if aObj is a plugin and the user - * has set the "security.xpconnect.plugin.unrestricted" pref to allow - * anybody to script plugin objects from anywhere. - * - * @param cx The context we're running on. - * NB: If null, "sameOrigin" does not have any effect. - * @param aObj The nsISupports representation of the object in question - * object, possibly null. - * @param aJSObject The JSObject representation of the object in question - * if |cx| is non-null and |aObjectSecurityLevel| is - * "sameOrigin". If null will be calculated from aObj (if - * non-null) if and only if aObj is an XPCWrappedJS. The - * rationale behind this is that if we're creating a JS - * wrapper for an XPCWrappedJS, this object definitely - * expects to be exposed to JS. - * @param aSubjectPrincipal The nominal subject principal used when - * aObjectSecurityLevel is "sameOrigin". If null, - * this is calculated if it's needed. - * @param aObjectSecurityLevel Can be one of three values: - * - allAccess: Allow access no matter what. - * - noAccess: Deny access no matter what. - * - sameOrigin: If |cx| is null, behave like noAccess. - * Otherwise, possibly compute a subject - * and object principal and return true if - * and only if the subject has greater than - * or equal privileges to the object. - */ - nsresult - CheckXPCPermissions(JSContext* cx, - nsISupports* aObj, JSObject* aJSObject, - nsIPrincipal* aSubjectPrincipal, - const char* aObjectSecurityLevel); - nsresult Init(); diff --git a/caps/src/nsScriptSecurityManager.cpp b/caps/src/nsScriptSecurityManager.cpp index bfc66002a4df..a1ffb50c2b76 100644 --- a/caps/src/nsScriptSecurityManager.cpp +++ b/caps/src/nsScriptSecurityManager.cpp @@ -44,7 +44,6 @@ #include "nsIPrompt.h" #include "nsIWindowWatcher.h" #include "nsIConsoleService.h" -#include "nsISecurityCheckedComponent.h" #include "nsIJSRuntimeService.h" #include "nsIObserverService.h" #include "nsIContent.h" @@ -608,160 +607,123 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(uint32_t aAction, return rv; } - //--See if the object advertises a non-default level of access - // using nsISecurityCheckedComponent - nsCOMPtr checkedComponent = - do_QueryInterface(aObj); - nsXPIDLCString objectSecurityLevel; - if (checkedComponent) + if (SubjectIsPrivileged()) { - nsCOMPtr wrapper; - nsCOMPtr interfaceInfo; - const nsIID* objIID = nullptr; - rv = aCallContext->GetCalleeWrapper(getter_AddRefs(wrapper)); - if (NS_SUCCEEDED(rv) && wrapper) - rv = wrapper->FindInterfaceWithMember(property, getter_AddRefs(interfaceInfo)); - if (NS_SUCCEEDED(rv) && interfaceInfo) - rv = interfaceInfo->GetIIDShared(&objIID); - if (NS_SUCCEEDED(rv) && objIID) - { - switch (aAction) - { - case nsIXPCSecurityManager::ACCESS_GET_PROPERTY: - checkedComponent->CanGetProperty(objIID, - IDToString(cx, property), - getter_Copies(objectSecurityLevel)); - break; - case nsIXPCSecurityManager::ACCESS_SET_PROPERTY: - checkedComponent->CanSetProperty(objIID, - IDToString(cx, property), - getter_Copies(objectSecurityLevel)); - break; - case nsIXPCSecurityManager::ACCESS_CALL_METHOD: - checkedComponent->CanCallMethod(objIID, - IDToString(cx, property), - getter_Copies(objectSecurityLevel)); + return NS_OK; + } + + //-- Security tests failed, access is denied, report error + nsAutoString stringName; + switch(aAction) + { + case nsIXPCSecurityManager::ACCESS_GET_PROPERTY: + stringName.AssignLiteral("GetPropertyDeniedOrigins"); + break; + case nsIXPCSecurityManager::ACCESS_SET_PROPERTY: + stringName.AssignLiteral("SetPropertyDeniedOrigins"); + break; + case nsIXPCSecurityManager::ACCESS_CALL_METHOD: + stringName.AssignLiteral("CallMethodDeniedOrigins"); + } + + // Null out objectPrincipal for now, so we don't leak information about + // it. Whenever we can report different error strings to content and + // the UI we can take this out again. + objectPrincipal = nullptr; + + NS_ConvertUTF8toUTF16 classInfoName(classInfoData.GetName()); + nsAutoCString subjectOrigin; + nsAutoCString subjectDomain; + if (!nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin) { + nsCOMPtr uri, domain; + subjectPrincipal->GetURI(getter_AddRefs(uri)); + if (uri) { // Object principal might be expanded + GetOriginFromURI(uri, subjectOrigin); + } + subjectPrincipal->GetDomain(getter_AddRefs(domain)); + if (domain) { + GetOriginFromURI(domain, subjectDomain); + } + } else { + subjectOrigin.AssignLiteral("the security manager"); + } + NS_ConvertUTF8toUTF16 subjectOriginUnicode(subjectOrigin); + NS_ConvertUTF8toUTF16 subjectDomainUnicode(subjectDomain); + + nsAutoCString objectOrigin; + nsAutoCString objectDomain; + if (!nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin && + objectPrincipal) { + nsCOMPtr uri, domain; + objectPrincipal->GetURI(getter_AddRefs(uri)); + if (uri) { // Object principal might be system + GetOriginFromURI(uri, objectOrigin); + } + objectPrincipal->GetDomain(getter_AddRefs(domain)); + if (domain) { + GetOriginFromURI(domain, objectDomain); + } + } + NS_ConvertUTF8toUTF16 objectOriginUnicode(objectOrigin); + NS_ConvertUTF8toUTF16 objectDomainUnicode(objectDomain); + + nsXPIDLString errorMsg; + const char16_t *formatStrings[] = + { + subjectOriginUnicode.get(), + classInfoName.get(), + IDToString(cx, property), + objectOriginUnicode.get(), + subjectDomainUnicode.get(), + objectDomainUnicode.get() + }; + + uint32_t length = ArrayLength(formatStrings); + + // XXXbz Our localization system is stupid and can't handle not showing + // some strings that get passed in. Which means that we have to get + // our length precisely right: it has to be exactly the number of + // strings our format string wants. This means we'll have to move + // strings in the array as needed, sadly... + if (nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin || + !objectPrincipal) { + stringName.AppendLiteral("OnlySubject"); + length -= 3; + } else { + // default to a length that doesn't include the domains, then + // increase it as needed. + length -= 2; + if (!subjectDomainUnicode.IsEmpty()) { + stringName.AppendLiteral("SubjectDomain"); + length += 1; + } + if (!objectDomainUnicode.IsEmpty()) { + stringName.AppendLiteral("ObjectDomain"); + length += 1; + if (length != ArrayLength(formatStrings)) { + // We have an object domain but not a subject domain. + // Scoot our string over one slot. See the XXX comment + // above for why we need to do this. + formatStrings[length-1] = formatStrings[length]; } } } - rv = CheckXPCPermissions(cx, aObj, jsObject, subjectPrincipal, - objectSecurityLevel); - - if (NS_FAILED(rv)) //-- Security tests failed, access is denied, report error - { - nsAutoString stringName; - switch(aAction) - { - case nsIXPCSecurityManager::ACCESS_GET_PROPERTY: - stringName.AssignLiteral("GetPropertyDeniedOrigins"); - break; - case nsIXPCSecurityManager::ACCESS_SET_PROPERTY: - stringName.AssignLiteral("SetPropertyDeniedOrigins"); - break; - case nsIXPCSecurityManager::ACCESS_CALL_METHOD: - stringName.AssignLiteral("CallMethodDeniedOrigins"); - } - - // Null out objectPrincipal for now, so we don't leak information about - // it. Whenever we can report different error strings to content and - // the UI we can take this out again. - objectPrincipal = nullptr; - - NS_ConvertUTF8toUTF16 className(classInfoData.GetName()); - nsAutoCString subjectOrigin; - nsAutoCString subjectDomain; - if (!nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin) { - nsCOMPtr uri, domain; - subjectPrincipal->GetURI(getter_AddRefs(uri)); - if (uri) { // Object principal might be expanded - GetOriginFromURI(uri, subjectOrigin); - } - subjectPrincipal->GetDomain(getter_AddRefs(domain)); - if (domain) { - GetOriginFromURI(domain, subjectDomain); - } - } else { - subjectOrigin.AssignLiteral("the security manager"); - } - NS_ConvertUTF8toUTF16 subjectOriginUnicode(subjectOrigin); - NS_ConvertUTF8toUTF16 subjectDomainUnicode(subjectDomain); - - nsAutoCString objectOrigin; - nsAutoCString objectDomain; - if (!nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin && - objectPrincipal) { - nsCOMPtr uri, domain; - objectPrincipal->GetURI(getter_AddRefs(uri)); - if (uri) { // Object principal might be system - GetOriginFromURI(uri, objectOrigin); - } - objectPrincipal->GetDomain(getter_AddRefs(domain)); - if (domain) { - GetOriginFromURI(domain, objectDomain); - } - } - NS_ConvertUTF8toUTF16 objectOriginUnicode(objectOrigin); - NS_ConvertUTF8toUTF16 objectDomainUnicode(objectDomain); - - nsXPIDLString errorMsg; - const char16_t *formatStrings[] = - { - subjectOriginUnicode.get(), - className.get(), - IDToString(cx, property), - objectOriginUnicode.get(), - subjectDomainUnicode.get(), - objectDomainUnicode.get() - }; - - uint32_t length = ArrayLength(formatStrings); - - // XXXbz Our localization system is stupid and can't handle not showing - // some strings that get passed in. Which means that we have to get - // our length precisely right: it has to be exactly the number of - // strings our format string wants. This means we'll have to move - // strings in the array as needed, sadly... - if (nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin || - !objectPrincipal) { - stringName.AppendLiteral("OnlySubject"); - length -= 3; - } else { - // default to a length that doesn't include the domains, then - // increase it as needed. - length -= 2; - if (!subjectDomainUnicode.IsEmpty()) { - stringName.AppendLiteral("SubjectDomain"); - length += 1; - } - if (!objectDomainUnicode.IsEmpty()) { - stringName.AppendLiteral("ObjectDomain"); - length += 1; - if (length != ArrayLength(formatStrings)) { - // We have an object domain but not a subject domain. - // Scoot our string over one slot. See the XXX comment - // above for why we need to do this. - formatStrings[length-1] = formatStrings[length]; - } - } - } - - // We need to keep our existing failure rv and not override it - // with a likely success code from the following string bundle - // call in order to throw the correct security exception later. - nsresult rv2 = sStrBundle->FormatStringFromName(stringName.get(), - formatStrings, - length, - getter_Copies(errorMsg)); - if (NS_FAILED(rv2)) { - // Might just be missing the string... Do our best - errorMsg = stringName; - } - - SetPendingException(cx, errorMsg.get()); + + // We need to keep our existing failure rv and not override it + // with a likely success code from the following string bundle + // call in order to throw the correct security exception later. + nsresult rv2 = sStrBundle->FormatStringFromName(stringName.get(), + formatStrings, + length, + getter_Copies(errorMsg)); + if (NS_FAILED(rv2)) { + // Might just be missing the string... Do our best + errorMsg = stringName; } - return rv; + SetPendingException(cx, errorMsg.get()); + return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED; } /* static */ @@ -1532,87 +1494,77 @@ nsScriptSecurityManager::CanCreateWrapper(JSContext *cx, return NS_OK; } - //--See if the object advertises a non-default level of access - // using nsISecurityCheckedComponent - nsCOMPtr checkedComponent = - do_QueryInterface(aObj); - - nsXPIDLCString objectSecurityLevel; - if (checkedComponent) - checkedComponent->CanCreateWrapper((nsIID *)&aIID, getter_Copies(objectSecurityLevel)); - - nsresult rv = CheckXPCPermissions(cx, aObj, nullptr, nullptr, objectSecurityLevel); - if (NS_FAILED(rv)) + if (SubjectIsPrivileged()) { - //-- Access denied, report an error - NS_ConvertUTF8toUTF16 strName("CreateWrapperDenied"); - nsAutoCString origin; - nsresult rv2; - nsIPrincipal* subjectPrincipal = doGetSubjectPrincipal(&rv2); - if (NS_SUCCEEDED(rv2) && subjectPrincipal) { - GetPrincipalDomainOrigin(subjectPrincipal, origin); - } - NS_ConvertUTF8toUTF16 originUnicode(origin); - NS_ConvertUTF8toUTF16 className(objClassInfo.GetName()); - const char16_t* formatStrings[] = { - className.get(), - originUnicode.get() - }; - uint32_t length = ArrayLength(formatStrings); - if (originUnicode.IsEmpty()) { - --length; - } else { - strName.AppendLiteral("ForOrigin"); - } - nsXPIDLString errorMsg; - // We need to keep our existing failure rv and not override it - // with a likely success code from the following string bundle - // call in order to throw the correct security exception later. - rv2 = sStrBundle->FormatStringFromName(strName.get(), - formatStrings, - length, - getter_Copies(errorMsg)); - NS_ENSURE_SUCCESS(rv2, rv2); - - SetPendingException(cx, errorMsg.get()); + return NS_OK; } - return rv; + //-- Access denied, report an error + NS_ConvertUTF8toUTF16 strName("CreateWrapperDenied"); + nsAutoCString origin; + nsresult rv2; + nsIPrincipal* subjectPrincipal = doGetSubjectPrincipal(&rv2); + if (NS_SUCCEEDED(rv2) && subjectPrincipal) { + GetPrincipalDomainOrigin(subjectPrincipal, origin); + } + NS_ConvertUTF8toUTF16 originUnicode(origin); + NS_ConvertUTF8toUTF16 classInfoName(objClassInfo.GetName()); + const char16_t* formatStrings[] = { + classInfoName.get(), + originUnicode.get() + }; + uint32_t length = ArrayLength(formatStrings); + if (originUnicode.IsEmpty()) { + --length; + } else { + strName.AppendLiteral("ForOrigin"); + } + nsXPIDLString errorMsg; + // We need to keep our existing failure rv and not override it + // with a likely success code from the following string bundle + // call in order to throw the correct security exception later. + rv2 = sStrBundle->FormatStringFromName(strName.get(), + formatStrings, + length, + getter_Copies(errorMsg)); + NS_ENSURE_SUCCESS(rv2, rv2); + + SetPendingException(cx, errorMsg.get()); + return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED; } NS_IMETHODIMP nsScriptSecurityManager::CanCreateInstance(JSContext *cx, const nsCID &aCID) { - nsresult rv = CheckXPCPermissions(cx, nullptr, nullptr, nullptr, nullptr); - if (NS_FAILED(rv)) - { - //-- Access denied, report an error - nsAutoCString errorMsg("Permission denied to create instance of class. CID="); - char cidStr[NSID_LENGTH]; - aCID.ToProvidedString(cidStr); - errorMsg.Append(cidStr); - SetPendingException(cx, errorMsg.get()); + if (SubjectIsPrivileged()) { + return NS_OK; } - return rv; + + //-- Access denied, report an error + nsAutoCString errorMsg("Permission denied to create instance of class. CID="); + char cidStr[NSID_LENGTH]; + aCID.ToProvidedString(cidStr); + errorMsg.Append(cidStr); + SetPendingException(cx, errorMsg.get()); + return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED; } NS_IMETHODIMP nsScriptSecurityManager::CanGetService(JSContext *cx, const nsCID &aCID) { - nsresult rv = CheckXPCPermissions(cx, nullptr, nullptr, nullptr, nullptr); - if (NS_FAILED(rv)) - { - //-- Access denied, report an error - nsAutoCString errorMsg("Permission denied to get service. CID="); - char cidStr[NSID_LENGTH]; - aCID.ToProvidedString(cidStr); - errorMsg.Append(cidStr); - SetPendingException(cx, errorMsg.get()); + if (SubjectIsPrivileged()) { + return NS_OK; } - return rv; + //-- Access denied, report an error + nsAutoCString errorMsg("Permission denied to get service. CID="); + char cidStr[NSID_LENGTH]; + aCID.ToProvidedString(cidStr); + errorMsg.Append(cidStr); + SetPendingException(cx, errorMsg.get()); + return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED; } @@ -1630,70 +1582,6 @@ nsScriptSecurityManager::CanAccess(uint32_t aAction, nullptr, aPropertyName); } -nsresult -nsScriptSecurityManager::CheckXPCPermissions(JSContext* cx, - nsISupports* aObj, JSObject* aJSObject, - nsIPrincipal* aSubjectPrincipal, - const char* aObjectSecurityLevel) -{ - MOZ_ASSERT(cx); - JS::RootedObject jsObject(cx, aJSObject); - // Check if the subject is privileged. - if (SubjectIsPrivileged()) - return NS_OK; - - //-- If the object implements nsISecurityCheckedComponent, it has a non-default policy. - if (aObjectSecurityLevel) - { - if (PL_strcasecmp(aObjectSecurityLevel, "allAccess") == 0) - return NS_OK; - if (cx && PL_strcasecmp(aObjectSecurityLevel, "sameOrigin") == 0) - { - nsresult rv; - if (!jsObject) - { - nsCOMPtr xpcwrappedjs = - do_QueryInterface(aObj); - if (xpcwrappedjs) - { - jsObject = xpcwrappedjs->GetJSObject(); - NS_ENSURE_STATE(jsObject); - } - } - - if (!aSubjectPrincipal) - { - // No subject principal passed in. Compute it. - aSubjectPrincipal = GetSubjectPrincipal(cx, &rv); - NS_ENSURE_SUCCESS(rv, rv); - } - if (aSubjectPrincipal && jsObject) - { - nsIPrincipal* objectPrincipal = doGetObjectPrincipal(jsObject); - - // Only do anything if we have both a subject and object - // principal. - if (objectPrincipal) - { - bool subsumes; - rv = aSubjectPrincipal->Subsumes(objectPrincipal, &subsumes); - NS_ENSURE_SUCCESS(rv, rv); - if (subsumes) - return NS_OK; - } - } - } - else if (PL_strcasecmp(aObjectSecurityLevel, "noAccess") != 0) - { - if (SubjectIsPrivileged()) - return NS_OK; - } - } - - //-- Access tests failed - return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED; -} - ///////////////////////////////////////////// // Method implementing nsIChannelEventSink // ///////////////////////////////////////////// diff --git a/content/xul/document/src/nsXULControllers.cpp b/content/xul/document/src/nsXULControllers.cpp index 65b87789a1d1..0da6e3fda7ab 100644 --- a/content/xul/document/src/nsXULControllers.cpp +++ b/content/xul/document/src/nsXULControllers.cpp @@ -83,7 +83,6 @@ DOMCI_DATA(XULControllers, nsXULControllers) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULControllers) NS_INTERFACE_MAP_ENTRY(nsIControllers) - NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIControllers) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XULControllers) NS_INTERFACE_MAP_END @@ -255,53 +254,3 @@ nsXULControllers::GetControllerCount(uint32_t *_retval) return NS_OK; } -// nsISecurityCheckedComponent implementation - -static char* cloneAllAccess() -{ - static const char allAccess[] = "AllAccess"; - return (char*)nsMemory::Clone(allAccess, sizeof(allAccess)); -} - -static char* cloneUniversalXPConnect() -{ - static const char universalXPConnect[] = "UniversalXPConnect"; - return (char*)nsMemory::Clone(universalXPConnect, sizeof(universalXPConnect)); -} - -NS_IMETHODIMP -nsXULControllers::CanCreateWrapper(const nsIID * iid, char **_retval) -{ - *_retval = cloneAllAccess(); - return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY; -} - -NS_IMETHODIMP -nsXULControllers::CanCallMethod(const nsIID * iid, const char16_t *methodName, - char **_retval) -{ - // OK if you're cool enough - *_retval = cloneUniversalXPConnect(); - return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY; -} - -NS_IMETHODIMP -nsXULControllers::CanGetProperty(const nsIID * iid, - const char16_t *propertyName, - char **_retval) -{ - // OK if you're cool enough - *_retval = cloneUniversalXPConnect(); - return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY; -} - - -NS_IMETHODIMP -nsXULControllers::CanSetProperty(const nsIID * iid, - const char16_t *propertyName, - char **_retval) -{ - // OK if you're cool enough - *_retval = cloneUniversalXPConnect(); - return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY; -} diff --git a/content/xul/document/src/nsXULControllers.h b/content/xul/document/src/nsXULControllers.h index e3dd55c1629c..103b4aa9101c 100644 --- a/content/xul/document/src/nsXULControllers.h +++ b/content/xul/document/src/nsXULControllers.h @@ -16,7 +16,6 @@ #include "nsTArray.h" #include "nsWeakPtr.h" #include "nsIControllers.h" -#include "nsISecurityCheckedComponent.h" #include "nsCycleCollectionParticipant.h" /* non-XPCOM class for holding controllers and their IDs */ @@ -46,8 +45,7 @@ public: nsresult NS_NewXULControllers(nsISupports* aOuter, REFNSIID aIID, void** aResult); -class nsXULControllers : public nsIControllers, - public nsISecurityCheckedComponent +class nsXULControllers : public nsIControllers { public: friend nsresult @@ -56,7 +54,6 @@ public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULControllers, nsIControllers) NS_DECL_NSICONTROLLERS - NS_DECL_NSISECURITYCHECKEDCOMPONENT protected: nsXULControllers(); diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 9378073869ea..9f75126139b3 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -721,7 +721,6 @@ static const char js_zeal_frequency_str[] = JS_OPTIONS_DOT_STR "gczeal.frequ #endif static const char js_typeinfer_content_str[] = JS_OPTIONS_DOT_STR "typeinference.content"; static const char js_typeinfer_chrome_str[] = JS_OPTIONS_DOT_STR "typeinference.chrome"; -static const char js_jit_hardening_str[] = JS_OPTIONS_DOT_STR "jit_hardening"; static const char js_memlog_option_str[] = JS_OPTIONS_DOT_STR "mem.log"; static const char js_memnotify_option_str[] = JS_OPTIONS_DOT_STR "mem.notify"; static const char js_asmjs_content_str[] = JS_OPTIONS_DOT_STR "asmjs"; @@ -758,7 +757,6 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data) bool useTypeInference = Preferences::GetBool((chromeWindow || !contentWindow) ? js_typeinfer_chrome_str : js_typeinfer_content_str); - bool useHardening = Preferences::GetBool(js_jit_hardening_str); bool useBaselineJIT = Preferences::GetBool((chromeWindow || !contentWindow) ? js_baselinejit_chrome_str : js_baselinejit_content_str); @@ -776,7 +774,6 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data) xr->GetInSafeMode(&safeMode); if (safeMode) { useTypeInference = false; - useHardening = false; useBaselineJIT = false; useBaselineJITEager = false; useIon = false; @@ -810,9 +807,6 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data) ::JS_SetGlobalJitCompilerOption(context->mContext, JSJITCOMPILER_ION_USECOUNT_TRIGGER, (useIonEager ? 0 : -1)); - JSRuntime *rt = JS_GetRuntime(context->mContext); - JS_SetJitHardening(rt, useHardening); - #ifdef JS_GC_ZEAL int32_t zeal = Preferences::GetInt(js_zeal_option_str, -1); int32_t frequency = Preferences::GetInt(js_zeal_frequency_str, JS_DEFAULT_ZEAL_FREQ); diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 2a18b9669e10..cf27d1d090f4 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -1587,7 +1587,9 @@ class MethodDefiner(PropertyDefiner): selfHostedName = "nullptr"; accessor = m.get("nativeName", m["name"]) if m.get("methodInfo", True): - jitinfo = ("&%s_methodinfo" % accessor) + # Cast this in case the methodInfo is a + # JSTypedMethodJitInfo. + jitinfo = ("reinterpret_cast(&%s_methodinfo)" % accessor) if m.get("allowCrossOriginThis", False): accessor = "genericCrossOriginMethod" else: @@ -6348,6 +6350,23 @@ class CGMemberJITInfo(CGThing): slotStr = toStringBool(hasSlot) returnType = reduce(CGMemberJITInfo.getSingleReturnType, returnTypes, "") + def jitInfoInitializer(isTypedMethod): + typedMethodStr = toStringBool(isTypedMethod) + return ("{\n" + " { %s },\n" + " %s,\n" + " %s,\n" + " JSJitInfo::%s,\n" + " %s, /* returnType. Not relevant for setters. */\n" + " %s, /* isInfallible. False in setters. */\n" + " %s, /* isMovable. Not relevant for setters. */\n" + " %s, /* isInSlot. Only relevant for getters. */\n" + " %s, /* isTypedMethod. Only relevant for methods. */\n" + " %s, /* Reserved slot index, if we're stored in a slot, else 0. */\n" + " JSJitInfo::%s /* aliasSet. Not relevant for setters. */\n" + "}" % (opName, protoID, depth, opType, + returnType, failstr, movablestr, slotStr, + typedMethodStr, slotIndex, aliasSet)) if args is not None: argTypes = "%s_argTypes" % infoName args = [CGMemberJITInfo.getJSArgType(arg.type) for arg in args] @@ -6355,27 +6374,17 @@ class CGMemberJITInfo(CGThing): argTypesDecl = ( "static const JSJitInfo::ArgType %s[] = { %s };\n" % (argTypes, ", ".join(args))) - else: - argTypes = "nullptr" - argTypesDecl = "" + return ("\n" + "%s" + "static const JSTypedMethodJitInfo %s = {\n" + " %s,\n" + " %s\n" + "};\n" % (argTypesDecl, infoName, + jitInfoInitializer(True), argTypes)) + return ("\n" - "%s" - "static const JSJitInfo %s = {\n" - " { %s },\n" - " %s,\n" - " %s,\n" - " JSJitInfo::%s,\n" - " %s, /* isInfallible. False in setters. */\n" - " %s, /* isMovable. Not relevant for setters. */\n" - " JSJitInfo::%s, /* aliasSet. Not relevant for setters. */\n" - " %s, /* hasSlot. Only relevant for getters. */\n" - " %s, /* Reserved slot index, if we're stored in a slot, else 0. */\n" - " %s, /* returnType. Not relevant for setters. */\n" - " %s, /* argTypes. Only relevant for methods */\n" - " nullptr /* parallelNative */\n" - "};\n" % (argTypesDecl, infoName, opName, protoID, depth, - opType, failstr, movablestr, aliasSet, slotStr, - slotIndex, returnType, argTypes)) + "static const JSJitInfo %s = %s;\n" + % (infoName, jitInfoInitializer(False))) def define(self): if self.member.isAttr(): @@ -11497,6 +11506,14 @@ class GlobalGenRoots(): idEnum.append(ifaceChainMacro(1)) + def fieldSizeAssert(amount, jitInfoField, message): + maxFieldValue = "(uint64_t(1) << (sizeof(((JSJitInfo*)nullptr)->%s) * 8))" % jitInfoField + return CGGeneric(declare="static_assert(%s < %s, \"%s\");\n\n" + % (amount, maxFieldValue, message)) + + idEnum.append(fieldSizeAssert("id::_ID_Count", "protoID", + "Too many prototypes!")); + # Wrap all of that in our namespaces. idEnum = CGNamespace.build(['mozilla', 'dom', 'prototypes'], CGWrapper(idEnum, pre='\n')) @@ -11505,8 +11522,11 @@ class GlobalGenRoots(): curr = CGList([idEnum]) # Let things know the maximum length of the prototype chain. - maxMacro = CGGeneric(declare="#define MAX_PROTOTYPE_CHAIN_LENGTH " + str(config.maxProtoChainLength)) + maxMacroName = "MAX_PROTOTYPE_CHAIN_LENGTH" + maxMacro = CGGeneric(declare="#define " + maxMacroName + " " + str(config.maxProtoChainLength)) curr.append(CGWrapper(maxMacro, post='\n\n')) + curr.append(fieldSizeAssert(maxMacroName, "depth", + "Some inheritance chain is too long!")); # Constructor ID enum. constructors = [d.name for d in config.getDescriptors(hasInterfaceObject=True)] diff --git a/dom/interfaces/base/nsIDOMWindow.idl b/dom/interfaces/base/nsIDOMWindow.idl index 3fde2b184f89..e64ad3598026 100644 --- a/dom/interfaces/base/nsIDOMWindow.idl +++ b/dom/interfaces/base/nsIDOMWindow.idl @@ -24,7 +24,7 @@ interface nsIVariant; * @see */ -[scriptable, uuid(b0ebb526-ed69-43c6-8242-b381a1fe79da)] +[scriptable, uuid(f2d1d383-f7b5-46f8-aadf-b69a0ebfb16f)] interface nsIDOMWindow : nsISupports { // the current browsing context @@ -376,9 +376,8 @@ interface nsIDOMWindow : nsISupports readonly attribute nsIDOMCrypto crypto; readonly attribute nsIDOMPkcs11 pkcs11; - // XXX Shouldn't this be in nsIDOMChromeWindow? - /* [replaceable] controllers */ - readonly attribute nsIControllers controllers; + // Note: this is [ChromeOnly] scriptable via WebIDL. + [noscript] readonly attribute nsIControllers controllers; readonly attribute float mozInnerScreenX; readonly attribute float mozInnerScreenY; diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl index b2b2103c8992..cdeca1e6e023 100644 --- a/dom/webidl/Window.webidl +++ b/dom/webidl/Window.webidl @@ -260,7 +260,7 @@ partial interface Window { readonly attribute Pkcs11? pkcs11; // XXX Shouldn't this be in nsIDOMChromeWindow? - [Replaceable, Throws] readonly attribute MozControllers controllers; + [ChromeOnly, Replaceable, Throws] readonly attribute MozControllers controllers; [Throws] readonly attribute float mozInnerScreenX; [Throws] readonly attribute float mozInnerScreenY; diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index de6e3706d738..a9f4aa25188c 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -135,7 +135,6 @@ static_assert(MAX_WORKERS_PER_DOMAIN >= 1, #define PREF_JS_OPTIONS_PREFIX "javascript.options." #define PREF_WORKERS_OPTIONS_PREFIX PREF_WORKERS_PREFIX "options." #define PREF_MEM_OPTIONS_PREFIX "mem." -#define PREF_JIT_HARDENING "jit_hardening" #define PREF_GCZEAL "gcZeal" #if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP)) @@ -297,9 +296,7 @@ LoadJSContextOptions(const char* aPrefName, void* /* aClosure */) PREF_MEM_OPTIONS_PREFIX)) || StringBeginsWith(prefName, NS_LITERAL_CSTRING(PREF_WORKERS_OPTIONS_PREFIX - PREF_MEM_OPTIONS_PREFIX)) || - prefName.EqualsLiteral(PREF_JS_OPTIONS_PREFIX PREF_JIT_HARDENING) || - prefName.EqualsLiteral(PREF_WORKERS_OPTIONS_PREFIX PREF_JIT_HARDENING)) { + PREF_MEM_OPTIONS_PREFIX))) { return; } @@ -574,27 +571,6 @@ LoadJSGCMemoryOptions(const char* aPrefName, void* /* aClosure */) } } -void -LoadJITHardeningOption(const char* /* aPrefName */, void* /* aClosure */) -{ - AssertIsOnMainThread(); - - RuntimeService* rts = RuntimeService::GetService(); - - if (!rts && !gRuntimeServiceDuringInit) { - // May be shutting down, just bail. - return; - } - - bool value = GetWorkerPref(NS_LITERAL_CSTRING(PREF_JIT_HARDENING), false); - - RuntimeService::SetDefaultJITHardening(value); - - if (rts) { - rts->UpdateAllWorkerJITHardening(value); - } -} - void ErrorReporter(JSContext* aCx, const char* aMessage, JSErrorReport* aReport) { @@ -833,8 +809,6 @@ CreateJSContextForWorker(WorkerPrivate* aWorkerPrivate, JSRuntime* aRuntime) aWorkerPrivate->IsChromeWorker() ? settings.chrome.contextOptions : settings.content.contextOptions; - JS_SetJitHardening(aRuntime, settings.jitHardening); - #ifdef JS_GC_ZEAL JS_SetGCZeal(workerCx, settings.gcZeal, settings.gcZealFrequency); #endif @@ -1675,14 +1649,6 @@ RuntimeService::Init() LoadJSGCMemoryOptions, PREF_WORKERS_OPTIONS_PREFIX PREF_MEM_OPTIONS_PREFIX, nullptr)) || - NS_FAILED(Preferences::RegisterCallback( - LoadJITHardeningOption, - PREF_JS_OPTIONS_PREFIX PREF_JIT_HARDENING, - nullptr)) || - NS_FAILED(Preferences::RegisterCallbackAndCall( - LoadJITHardeningOption, - PREF_WORKERS_OPTIONS_PREFIX PREF_JIT_HARDENING, - nullptr)) || #ifdef JS_GC_ZEAL NS_FAILED(Preferences::RegisterCallback( LoadGCZealOptions, @@ -1889,15 +1855,7 @@ RuntimeService::Cleanup() NS_FAILED(Preferences::UnregisterCallback( LoadJSGCMemoryOptions, PREF_WORKERS_OPTIONS_PREFIX PREF_MEM_OPTIONS_PREFIX, - nullptr)) || - NS_FAILED(Preferences::UnregisterCallback( - LoadJITHardeningOption, - PREF_JS_OPTIONS_PREFIX PREF_JIT_HARDENING, - nullptr)) || - NS_FAILED(Preferences::UnregisterCallback( - LoadJITHardeningOption, - PREF_WORKERS_OPTIONS_PREFIX PREF_JIT_HARDENING, - nullptr))) { + nullptr))) { NS_WARNING("Failed to unregister pref callbacks!"); } @@ -2278,12 +2236,6 @@ RuntimeService::UpdateAllWorkerGCZeal() } #endif -void -RuntimeService::UpdateAllWorkerJITHardening(bool aJITHardening) -{ - BROADCAST_ALL_WORKERS(UpdateJITHardening, aJITHardening); -} - void RuntimeService::GarbageCollectAllWorkers(bool aShrinking) { diff --git a/dom/workers/RuntimeService.h b/dom/workers/RuntimeService.h index b019289fd58e..364245381fe1 100644 --- a/dom/workers/RuntimeService.h +++ b/dom/workers/RuntimeService.h @@ -223,16 +223,6 @@ public: UpdateAllWorkerGCZeal(); #endif - static void - SetDefaultJITHardening(bool aJITHardening) - { - AssertIsOnMainThread(); - sDefaultJSSettings.jitHardening = aJITHardening; - } - - void - UpdateAllWorkerJITHardening(bool aJITHardening); - void GarbageCollectAllWorkers(bool aShrinking); diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index d40e28335645..c111eb899743 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -1620,25 +1620,6 @@ private: }; #endif -class UpdateJITHardeningRunnable MOZ_FINAL : public WorkerControlRunnable -{ - bool mJITHardening; - -public: - UpdateJITHardeningRunnable(WorkerPrivate* aWorkerPrivate, bool aJITHardening) - : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount), - mJITHardening(aJITHardening) - { } - -private: - virtual bool - WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) MOZ_OVERRIDE - { - aWorkerPrivate->UpdateJITHardeningInternal(aCx, mJITHardening); - return true; - } -}; - class GarbageCollectRunnable MOZ_FINAL : public WorkerControlRunnable { bool mShrinking; @@ -3006,26 +2987,6 @@ WorkerPrivateParent::UpdateGCZeal(JSContext* aCx, uint8_t aGCZeal, } #endif -template -void -WorkerPrivateParent::UpdateJITHardening(JSContext* aCx, - bool aJITHardening) -{ - AssertIsOnParentThread(); - - { - MutexAutoLock lock(mMutex); - mJSSettings.jitHardening = aJITHardening; - } - - nsRefPtr runnable = - new UpdateJITHardeningRunnable(ParentAsWorkerPrivate(), aJITHardening); - if (!runnable->Dispatch(aCx)) { - NS_WARNING("Failed to update worker jit hardening!"); - JS_ClearPendingException(aCx); - } -} - template void WorkerPrivateParent::GarbageCollect(JSContext* aCx, bool aShrinking) @@ -5621,18 +5582,6 @@ WorkerPrivate::UpdateGCZealInternal(JSContext* aCx, uint8_t aGCZeal, } #endif -void -WorkerPrivate::UpdateJITHardeningInternal(JSContext* aCx, bool aJITHardening) -{ - AssertIsOnWorkerThread(); - - JS_SetJitHardening(JS_GetRuntime(aCx), aJITHardening); - - for (uint32_t index = 0; index < mChildWorkers.Length(); index++) { - mChildWorkers[index]->UpdateJITHardening(aCx, aJITHardening); - } -} - void WorkerPrivate::GarbageCollectInternal(JSContext* aCx, bool aShrinking, bool aCollectChildren) diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h index 1592d992f3b9..bca93dd6ca21 100644 --- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h @@ -384,9 +384,6 @@ public: UpdateGCZeal(JSContext* aCx, uint8_t aGCZeal, uint32_t aFrequency); #endif - void - UpdateJITHardening(JSContext* aCx, bool aJITHardening); - void GarbageCollect(JSContext* aCx, bool aShrinking); @@ -897,9 +894,6 @@ public: UpdateGCZealInternal(JSContext* aCx, uint8_t aGCZeal, uint32_t aFrequency); #endif - void - UpdateJITHardeningInternal(JSContext* aCx, bool aJITHardening); - void GarbageCollectInternal(JSContext* aCx, bool aShrinking, bool aCollectChildren); diff --git a/dom/workers/Workers.h b/dom/workers/Workers.h index 2af5a6e3fb77..cdcbf1ebf7db 100644 --- a/dom/workers/Workers.h +++ b/dom/workers/Workers.h @@ -107,16 +107,15 @@ struct JSSettings JSContentChromeSettings chrome; JSContentChromeSettings content; JSGCSettingsArray gcSettings; - bool jitHardening; + #ifdef JS_GC_ZEAL uint8_t gcZeal; uint32_t gcZealFrequency; #endif JSSettings() - : jitHardening(false) #ifdef JS_GC_ZEAL - , gcZeal(0), gcZealFrequency(0) + : gcZeal(0), gcZealFrequency(0) #endif { for (uint32_t index = 0; index < ArrayLength(gcSettings); index++) { diff --git a/embedding/components/commandhandler/src/nsCommandManager.h b/embedding/components/commandhandler/src/nsCommandManager.h index f7b543fe1a98..4f120e3efb88 100644 --- a/embedding/components/commandhandler/src/nsCommandManager.h +++ b/embedding/components/commandhandler/src/nsCommandManager.h @@ -21,7 +21,6 @@ template class nsCOMArray; class nsCommandManager : public nsICommandManager, public nsPICommandUpdater, - // public nsISecurityCheckedComponent, public nsSupportsWeakReference { diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index 4c14e303dc36..14d14db821f9 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -2601,7 +2601,7 @@ RasterImage::Draw(gfxContext *aContext, // We can only draw with the default decode flags if (mFrameDecodeFlags != DECODE_FLAGS_DEFAULT) { - if (!CanForciblyDiscard()) + if (!CanForciblyDiscard() || mDecoder || mAnim) return NS_ERROR_NOT_AVAILABLE; ForceDiscard(); @@ -2724,7 +2724,7 @@ RasterImage::UnlockImage() NS_IMETHODIMP RasterImage::RequestDiscard() { - if (CanDiscard()) { + if (CanDiscard() && !mDecoder && !mAnim) { ForceDiscard(); } diff --git a/js/src/assembler/jit/ExecutableAllocator.h b/js/src/assembler/jit/ExecutableAllocator.h index 437d4060d07d..6d3d027caaeb 100644 --- a/js/src/assembler/jit/ExecutableAllocator.h +++ b/js/src/assembler/jit/ExecutableAllocator.h @@ -176,21 +176,14 @@ private: } }; -enum AllocationBehavior -{ - AllocationCanRandomize, - AllocationDeterministic -}; - class ExecutableAllocator { typedef void (*DestroyCallback)(void* addr, size_t size); enum ProtectionSetting { Writable, Executable }; DestroyCallback destroyCallback; public: - explicit ExecutableAllocator(AllocationBehavior allocBehavior) - : destroyCallback(NULL), - allocBehavior(allocBehavior) + ExecutableAllocator() + : destroyCallback(NULL) { if (!pageSize) { pageSize = determinePageSize(); @@ -221,7 +214,7 @@ public: for (size_t i = 0; i < m_smallPools.length(); i++) m_smallPools[i]->release(); - m_smallPools.clear(); + m_smallPools.clear(); } // alloc() returns a pointer to some memory, and also (by reference) a @@ -266,10 +259,6 @@ public: this->destroyCallback = destroyCallback; } - void setRandomize(bool enabled) { - allocBehavior = enabled ? AllocationCanRandomize : AllocationDeterministic; - } - private: static size_t pageSize; static size_t largeAllocSize; @@ -502,7 +491,6 @@ private: typedef js::HashSet, js::SystemAllocPolicy> ExecPoolHashSet; ExecPoolHashSet m_pools; // All pools, just for stats purposes. - AllocationBehavior allocBehavior; static size_t determinePageSize(); }; diff --git a/js/src/assembler/jit/ExecutableAllocatorWin.cpp b/js/src/assembler/jit/ExecutableAllocatorWin.cpp index fdd2511f4157..0d28d10d0fc6 100644 --- a/js/src/assembler/jit/ExecutableAllocatorWin.cpp +++ b/js/src/assembler/jit/ExecutableAllocatorWin.cpp @@ -99,7 +99,7 @@ ExecutablePool::Allocation ExecutableAllocator::systemAlloc(size_t n) // Randomization disabled to avoid a performance fault on x64 builds. // See bug 728623. #ifndef JS_CPU_X64 - if (allocBehavior == AllocationCanRandomize && !RandomizeIsBroken()) { + if (!RandomizeIsBroken()) { void *randomAddress = computeRandomAllocationAddress(); allocation = VirtualAlloc(randomAddress, n, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); diff --git a/js/src/builtin/TypedObject.cpp b/js/src/builtin/TypedObject.cpp index eac3c0d66964..dcd8a5b03e52 100644 --- a/js/src/builtin/TypedObject.cpp +++ b/js/src/builtin/TypedObject.cpp @@ -2539,9 +2539,8 @@ js::AttachHandle(ThreadSafeContext *, unsigned argc, Value *vp) return true; } -const JSJitInfo js::AttachHandleJitInfo = - JS_JITINFO_NATIVE_PARALLEL( - JSParallelNativeThreadSafeWrapper); +JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::AttachHandleJitInfo, AttachHandleJitInfo, + js::AttachHandle); bool js::ObjectIsTypeObject(ThreadSafeContext *, unsigned argc, Value *vp) @@ -2553,9 +2552,8 @@ js::ObjectIsTypeObject(ThreadSafeContext *, unsigned argc, Value *vp) return true; } -const JSJitInfo js::ObjectIsTypeObjectJitInfo = - JS_JITINFO_NATIVE_PARALLEL( - JSParallelNativeThreadSafeWrapper); +JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::ObjectIsTypeObjectJitInfo, ObjectIsTypeObjectJitInfo, + js::ObjectIsTypeObject); bool js::ObjectIsTypeRepresentation(ThreadSafeContext *, unsigned argc, Value *vp) @@ -2567,9 +2565,9 @@ js::ObjectIsTypeRepresentation(ThreadSafeContext *, unsigned argc, Value *vp) return true; } -const JSJitInfo js::ObjectIsTypeRepresentationJitInfo = - JS_JITINFO_NATIVE_PARALLEL( - JSParallelNativeThreadSafeWrapper); +JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::ObjectIsTypeRepresentationJitInfo, + ObjectIsTypeRepresentationJitInfo, + js::ObjectIsTypeRepresentation); bool js::ObjectIsTypedHandle(ThreadSafeContext *, unsigned argc, Value *vp) @@ -2581,9 +2579,8 @@ js::ObjectIsTypedHandle(ThreadSafeContext *, unsigned argc, Value *vp) return true; } -const JSJitInfo js::ObjectIsTypedHandleJitInfo = - JS_JITINFO_NATIVE_PARALLEL( - JSParallelNativeThreadSafeWrapper); +JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::ObjectIsTypedHandleJitInfo, ObjectIsTypedHandleJitInfo, + js::ObjectIsTypedHandle); bool js::ObjectIsTypedObject(ThreadSafeContext *, unsigned argc, Value *vp) @@ -2595,9 +2592,8 @@ js::ObjectIsTypedObject(ThreadSafeContext *, unsigned argc, Value *vp) return true; } -const JSJitInfo js::ObjectIsTypedObjectJitInfo = - JS_JITINFO_NATIVE_PARALLEL( - JSParallelNativeThreadSafeWrapper); +JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::ObjectIsTypedObjectJitInfo, ObjectIsTypedObjectJitInfo, + js::ObjectIsTypedObject); bool js::IsAttached(ThreadSafeContext *cx, unsigned argc, Value *vp) @@ -2608,9 +2604,7 @@ js::IsAttached(ThreadSafeContext *cx, unsigned argc, Value *vp) return true; } -const JSJitInfo js::IsAttachedJitInfo = - JS_JITINFO_NATIVE_PARALLEL( - JSParallelNativeThreadSafeWrapper); +JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::IsAttachedJitInfo, IsAttachedJitInfo, js::IsAttached); bool js::ClampToUint8(ThreadSafeContext *, unsigned argc, Value *vp) @@ -2622,9 +2616,8 @@ js::ClampToUint8(ThreadSafeContext *, unsigned argc, Value *vp) return true; } -const JSJitInfo js::ClampToUint8JitInfo = - JS_JITINFO_NATIVE_PARALLEL( - JSParallelNativeThreadSafeWrapper); +JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::ClampToUint8JitInfo, ClampToUint8JitInfo, + js::ClampToUint8); bool js::Memcpy(ThreadSafeContext *, unsigned argc, Value *vp) @@ -2645,9 +2638,7 @@ js::Memcpy(ThreadSafeContext *, unsigned argc, Value *vp) return true; } -const JSJitInfo js::MemcpyJitInfo = - JS_JITINFO_NATIVE_PARALLEL( - JSParallelNativeThreadSafeWrapper); +JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::MemcpyJitInfo, MemcpyJitInfo, js::Memcpy); bool js::GetTypedObjectModule(JSContext *cx, unsigned argc, Value *vp) @@ -2701,10 +2692,8 @@ js::StoreScalar##T::Func(ThreadSafeContext *, unsigned argc, Value *vp) \ return true; \ } \ \ -const JSJitInfo \ -js::StoreScalar##T::JitInfo = \ - JS_JITINFO_NATIVE_PARALLEL( \ - JSParallelNativeThreadSafeWrapper); + JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::StoreScalar##T::JitInfo, StoreScalar##T, \ + js::StoreScalar##T::Func); #define JS_STORE_REFERENCE_CLASS_IMPL(_constant, T, _name) \ bool \ @@ -2727,10 +2716,8 @@ js::StoreReference##T::Func(ThreadSafeContext *, unsigned argc, Value *vp) return true; \ } \ \ -const JSJitInfo \ -js::StoreReference##T::JitInfo = \ - JS_JITINFO_NATIVE_PARALLEL( \ - JSParallelNativeThreadSafeWrapper); + JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::StoreReference##T::JitInfo, StoreReference##T, \ + js::StoreReference##T::Func); #define JS_LOAD_SCALAR_CLASS_IMPL(_constant, T, _name) \ bool \ @@ -2751,10 +2738,8 @@ js::LoadScalar##T::Func(ThreadSafeContext *, unsigned argc, Value *vp) \ return true; \ } \ \ -const JSJitInfo \ -js::LoadScalar##T::JitInfo = \ - JS_JITINFO_NATIVE_PARALLEL( \ - JSParallelNativeThreadSafeWrapper); + JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::LoadScalar##T::JitInfo, LoadScalar##T, \ + js::LoadScalar##T::Func); #define JS_LOAD_REFERENCE_CLASS_IMPL(_constant, T, _name) \ bool \ @@ -2776,10 +2761,8 @@ js::LoadReference##T::Func(ThreadSafeContext *, unsigned argc, Value *vp) \ return true; \ } \ \ -const JSJitInfo \ -js::LoadReference##T::JitInfo = \ - JS_JITINFO_NATIVE_PARALLEL( \ - JSParallelNativeThreadSafeWrapper); + JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::LoadReference##T::JitInfo, LoadReference##T, \ + js::LoadReference##T::Func); // Because the precise syntax for storing values/objects/strings // differs, we abstract it away using specialized variants of the diff --git a/js/src/jit/Ion.cpp b/js/src/jit/Ion.cpp index 34f763eb3814..df05f0887717 100644 --- a/js/src/jit/Ion.cpp +++ b/js/src/jit/Ion.cpp @@ -330,9 +330,7 @@ JitRuntime::createIonAlloc(JSContext *cx) { JS_ASSERT(cx->runtime()->currentThreadOwnsOperationCallbackLock()); - JSC::AllocationBehavior randomize = - cx->runtime()->jitHardening ? JSC::AllocationCanRandomize : JSC::AllocationDeterministic; - ionAlloc_ = js_new(randomize); + ionAlloc_ = js_new(); if (!ionAlloc_) js_ReportOutOfMemory(cx); return ionAlloc_; diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index 81fbb011bd3d..703512798d4f 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -675,11 +675,13 @@ MCallDOMNative::getAliasSet() const // If we don't know anything about the types of our arguments, we have to // assume that type-coercions can have side-effects, so we need to alias // everything. - if (jitInfo->aliasSet != JSJitInfo::AliasDOMSets || !jitInfo->argTypes) + if (jitInfo->aliasSet != JSJitInfo::AliasDOMSets || !jitInfo->isTypedMethodJitInfo()) return AliasSet::Store(AliasSet::Any); uint32_t argIndex = 0; - for (const JSJitInfo::ArgType *argType = jitInfo->argTypes; + const JSTypedMethodJitInfo *methodInfo = + reinterpret_cast(jitInfo); + for (const JSJitInfo::ArgType *argType = methodInfo->argTypes; *argType != JSJitInfo::ArgTypeListEnd; ++argType, ++argIndex) { diff --git a/js/src/js.msg b/js/src/js.msg index 2fd2abe5d4b3..1292439a59c3 100644 --- a/js/src/js.msg +++ b/js/src/js.msg @@ -433,5 +433,5 @@ MSG_DEF(JSMSG_NO_EXPORT_NAME, 378, 0, JSEXN_SYNTAXERR, "missing export MSG_DEF(JSMSG_DECLARATION_AFTER_EXPORT, 379, 0, JSEXN_SYNTAXERR, "missing declaration after 'export' keyword") MSG_DEF(JSMSG_INVALID_PROTOTYPE, 380, 0, JSEXN_TYPEERR, "prototype field is not an object") MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_TO_UNSIZED, 381, 0, JSEXN_TYPEERR, "cannot create a handle to an unsized type") -MSG_DEF(JSMSG_SETPROTOTYPEOF_FAIL, 382, 0, JSEXN_TYPEERR, "[[SetPrototypeOf]] failed") +MSG_DEF(JSMSG_SETPROTOTYPEOF_FAIL, 382, 1, JSEXN_TYPEERR, "[[SetPrototypeOf]] failed on {0}") MSG_DEF(JSMSG_INVALID_ARG_TYPE, 383, 3, JSEXN_TYPEERR, "Invalid type: {0} can't be a{1} {2}") diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 9b43b4532909..703e60682d9b 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -873,12 +873,6 @@ JS::ContextOptionsRef(JSContext *cx) return cx->options(); } -JS_PUBLIC_API(void) -JS_SetJitHardening(JSRuntime *rt, bool enabled) -{ - rt->setJitHardening(!!enabled); -} - JS_PUBLIC_API(const char *) JS_GetImplementationVersion(void) { @@ -2822,7 +2816,7 @@ JS_LookupPropertyWithFlags(JSContext *cx, HandleObject obj, const char *name, un RootedObject obj2(cx); JSAtom *atom = Atomize(cx, name, strlen(name)); if (!atom) - false; + return false; RootedId id(cx, AtomToId(atom)); return JS_LookupPropertyWithFlagsById(cx, obj, id, flags, &obj2, vp); diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 33004c29dcd5..4abb3b7129cf 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1624,9 +1624,6 @@ class JS_PUBLIC_API(AutoSaveContextOptions) { } /* namespace JS */ -extern JS_PUBLIC_API(void) -JS_SetJitHardening(JSRuntime *rt, bool enabled); - extern JS_PUBLIC_API(const char *) JS_GetImplementationVersion(void); diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index a1d0aabe9a0f..4e1cfc4d3186 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -8,6 +8,7 @@ #define jsfriendapi_h #include "mozilla/MemoryReporting.h" +#include "mozilla/TypedEnum.h" #include "jsbytecode.h" #include "jspubtd.h" @@ -1447,11 +1448,11 @@ typedef bool void *specializedThis, const JSJitMethodCallArgs& args); struct JSJitInfo { - enum OpType { + enum OpType MOZ_ENUM_TYPE(uint8_t) { Getter, Setter, Method, - OpType_None + ParallelNative }; enum ArgType { @@ -1475,7 +1476,7 @@ struct JSJitInfo { ArgTypeListEnd = (1 << 31) }; - enum AliasSet { + enum AliasSet MOZ_ENUM_TYPE(uint8_t) { // An enum that describes what this getter/setter/method aliases. This // determines what things can be hoisted past this call, and if this // call is movable what it can be hoisted past. @@ -1493,49 +1494,54 @@ struct JSJitInfo { AliasEverything }; + bool hasParallelNative() const + { + return type == ParallelNative; + } + bool isDOMJitInfo() const { - return type != OpType_None; + return type != ParallelNative; + } + + bool isTypedMethodJitInfo() const + { + return isTypedMethod; } union { JSJitGetterOp getter; JSJitSetterOp setter; JSJitMethodOp method; + /* An alternative native that's safe to call in parallel mode. */ + JSParallelNative parallelNative; }; - uint32_t protoID; - uint32_t depth; - // type not being OpType_None means this is a DOM method. If you + uint16_t protoID; + uint16_t depth; + // type not being ParallelNative means this is a DOM method. If you // change that, come up with a different way of implementing // isDOMJitInfo(). OpType type; - bool isInfallible; /* Is op fallible? False in setters. */ - bool isMovable; /* Is op movable? To be movable the op must not - AliasEverything, but even that might not be - enough (e.g. in cases when it can throw). */ + JSValueType returnType; /* The return type tag. Might be JSVAL_TYPE_UNKNOWN */ + uint16_t isInfallible : 1; /* Is op fallible? False in setters. */ + uint16_t isMovable : 1; /* Is op movable? To be movable the op must + not AliasEverything, but even that might + not be enough (e.g. in cases when it can + throw). */ + // XXXbz should we have a JSValueType for the type of the member? + uint16_t isInSlot : 1; /* True if this is a getter that can get a member + from a slot of the "this" object directly. */ + uint16_t isTypedMethod : 1; /* True if this is an instance of + JSTypedMethodJitInfo. */ + uint16_t slotIndex : 12; /* If isInSlot is true, the index of the slot to + get the value from. Otherwise 0. */ + AliasSet aliasSet; /* The alias set for this op. This is a _minimal_ alias set; in particular for a method it does not include whatever argument conversions might do. That's covered by argTypes and runtime analysis of the actual argument types being passed in. */ - // XXXbz should we have a JSGetterJitInfo subclass or something? - // XXXbz should we have a JSValueType for the type of the member? - bool isInSlot; /* True if this is a getter that can get a member - from a slot of the "this" object directly. */ - size_t slotIndex; /* If isMember is true, the index of the slot to get - the value from. Otherwise 0. */ - JSValueType returnType; /* The return type tag. Might be JSVAL_TYPE_UNKNOWN */ - - const ArgType* const argTypes; /* For a method, a list of sets of types that - the function expects. This can be used, - for example, to figure out when argument - coercions can have side-effects. nullptr - if we have no type information for - arguments. */ - - /* An alternative native that's safe to call in parallel mode. */ - JSParallelNative parallelNative; private: static void staticAsserts() @@ -1549,8 +1555,64 @@ private: } }; -#define JS_JITINFO_NATIVE_PARALLEL(op) \ - {{nullptr},0,0,JSJitInfo::OpType_None,false,false,JSJitInfo::AliasEverything,false,0,JSVAL_TYPE_MISSING,nullptr,op} +struct JSTypedMethodJitInfo +{ + // We use C-style inheritance here, rather than C++ style inheritance + // because not all compilers support brace-initialization for non-aggregate + // classes. Using C++ style inheritance and constructors instead of + // brace-initialization would also force the creation of static + // constructors (on some compilers) when JSJitInfo and JSTypedMethodJitInfo + // structures are declared. Since there can be several thousand of these + // structures present and we want to have roughly equivalent performance + // across a range of compilers, we do things manually. + JSJitInfo base; + + const JSJitInfo::ArgType* const argTypes; /* For a method, a list of sets of + types that the function + expects. This can be used, + for example, to figure out + when argument coercions can + have side-effects. */ +}; + +namespace JS { +namespace detail { + +/* NEVER DEFINED, DON'T USE. For use by JS_CAST_PARALLEL_NATIVE_TO only. */ +inline int CheckIsParallelNative(JSParallelNative parallelNative); + +} // namespace detail +} // namespace JS + +#define JS_CAST_PARALLEL_NATIVE_TO(v, To) \ + (static_cast(sizeof(JS::detail::CheckIsParallelNative(v))), \ + reinterpret_cast(v)) + +/* + * You may ask yourself: why do we define a wrapper around a wrapper here? + * The answer is that some compilers don't understand initializing a union + * as we do below with a construct like: + * + * reinterpret_cast(JSParallelNativeThreadSafeWrapper) + * + * (We need the reinterpret_cast because we must initialize the union with + * a datum of the type of the union's first member.) + * + * Presumably this has something to do with template instantiation. + * Initializing with a normal function pointer seems to work fine. Hence + * the ugliness that you see before you. + */ +#define JS_JITINFO_NATIVE_PARALLEL(infoName, parallelOp) \ + const JSJitInfo infoName = \ + {{JS_CAST_PARALLEL_NATIVE_TO(parallelOp, JSJitGetterOp)},0,0,JSJitInfo::ParallelNative,JSVAL_TYPE_MISSING,false,false,false,false,0,JSJitInfo::AliasEverything} + +#define JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(infoName, wrapperName, serialOp) \ + bool wrapperName##_ParallelNativeThreadSafeWrapper(js::ForkJoinSlice *slice, unsigned argc, \ + JS::Value *vp) \ + { \ + return JSParallelNativeThreadSafeWrapper(slice, argc, vp); \ + } \ + JS_JITINFO_NATIVE_PARALLEL(infoName, wrapperName##_ParallelNativeThreadSafeWrapper) static JS_ALWAYS_INLINE const JSJitInfo * FUNCTION_VALUE_TO_JITINFO(const JS::Value& v) diff --git a/js/src/jsfun.h b/js/src/jsfun.h index bdf1d733f011..502843c2a9e7 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -179,7 +179,7 @@ class JSFunction : public JSObject return isLambda() && displayAtom() && !hasGuessedAtom(); } bool hasParallelNative() const { - return isNative() && jitInfo() && !!jitInfo()->parallelNative; + return isNative() && jitInfo() && jitInfo()->hasParallelNative(); } bool isBuiltinFunctionConstructor(); diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index dfb0b0c0eb3a..ae4026dcd3db 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -429,6 +429,27 @@ JSObject::setProto(JSContext *cx, JS::HandleObject obj, JS::HandleObject proto, return js::Proxy::setPrototypeOf(cx, obj, proto, succeeded); } + /* + * Disallow mutating the [[Prototype]] on ArrayBuffer objects, which + * due to their complicated delegate-object shenanigans can't easily + * have a mutable [[Prototype]]. + */ + if (obj->is()) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL, + "incompatible ArrayBuffer"); + return false; + } + + /* + * Explicityly disallow mutating the [[Prototype]] of Location objects + * for flash-related security reasons. + */ + if (!strcmp(obj->getClass()->name, "Location")) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL, + "incompatible Location object"); + return false; + } + /* ES6 9.1.2 step 5 forbids changing [[Prototype]] if not [[Extensible]]. */ bool extensible; if (!JSObject::isExtensible(cx, obj, &extensible)) diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index 5b33d97b1740..d807ecc5bf2e 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -355,7 +355,8 @@ BaseProxyHandler::setPrototypeOf(JSContext *cx, HandleObject, HandleObject, bool // Disallow sets of protos on proxies with lazy protos, but no hook. // This keeps us away from the footgun of having the first proto set opt // you out of having dynamic protos altogether. - JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL); + JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL, + "incompatible Proxy"); return false; } @@ -3250,15 +3251,12 @@ proxy(JSContext *cx, unsigned argc, jsval *vp) RootedObject handler(cx, NonNullObject(cx, args[1])); if (!handler) return false; - RootedObject proto(cx); - if (!JSObject::getProto(cx, target, &proto)) - return false; RootedValue priv(cx, ObjectValue(*target)); ProxyOptions options; options.setCallable(target->isCallable()); ProxyObject *proxy = ProxyObject::New(cx, &ScriptedDirectProxyHandler::singleton, - priv, TaggedProto(proto), cx->global(), + priv, TaggedProto(TaggedProto::LazyProto), cx->global(), options); if (!proxy) return false; diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index b7a3ff14e9f6..f92623a8a856 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -4834,14 +4834,13 @@ static const JSJitInfo dom_x_getterinfo = { 0, /* protoID */ 0, /* depth */ JSJitInfo::Getter, + JSVAL_TYPE_UNKNOWN, /* returnType */ true, /* isInfallible. False in setters. */ true, /* isMovable */ - JSJitInfo::AliasNone, /* aliasSet */ false, /* isInSlot */ + false, /* isTypedMethod */ 0, /* slotIndex */ - JSVAL_TYPE_UNKNOWN, /* returnType */ - nullptr, /* argTypes */ - nullptr /* parallelNative */ + JSJitInfo::AliasNone /* aliasSet */ }; static const JSJitInfo dom_x_setterinfo = { @@ -4849,14 +4848,13 @@ static const JSJitInfo dom_x_setterinfo = { 0, /* protoID */ 0, /* depth */ JSJitInfo::Setter, + JSVAL_TYPE_UNKNOWN, /* returnType */ false, /* isInfallible. False in setters. */ false, /* isMovable. */ - JSJitInfo::AliasEverything, /* aliasSet */ false, /* isInSlot */ + false, /* isTypedMethod */ 0, /* slotIndex */ - JSVAL_TYPE_UNKNOWN, /* returnType */ - nullptr, /* argTypes */ - nullptr /* parallelNative */ + JSJitInfo::AliasEverything /* aliasSet */ }; static const JSJitInfo doFoo_methodinfo = { @@ -4864,14 +4862,13 @@ static const JSJitInfo doFoo_methodinfo = { 0, /* protoID */ 0, /* depth */ JSJitInfo::Method, + JSVAL_TYPE_UNKNOWN, /* returnType */ false, /* isInfallible. False in setters. */ false, /* isMovable */ - JSJitInfo::AliasEverything, /* aliasSet */ false, /* isInSlot */ + false, /* isTypedMethod */ 0, /* slotIndex */ - JSVAL_TYPE_UNKNOWN, /* returnType */ - nullptr, /* argTypes */ - nullptr /* parallelNative */ + JSJitInfo::AliasEverything /* aliasSet */ }; static const JSPropertySpec dom_props[] = { diff --git a/js/src/tests/ecma_6/Proxy/proxy-__proto__.js b/js/src/tests/ecma_6/Proxy/proxy-__proto__.js new file mode 100644 index 000000000000..f68bea489ba1 --- /dev/null +++ b/js/src/tests/ecma_6/Proxy/proxy-__proto__.js @@ -0,0 +1,59 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'proxy-__proto__.js'; +var BUGNUMBER = 950407; +var summary = "Behavior of __proto__ on ES6 proxies"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var protoDesc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__"); +var protoGetter = protoDesc.get; +var protoSetter = protoDesc.set; + +function testProxy(target, initialProto) +{ + print("Now testing behavior for new Proxy(" + ("" + target) + ", {})"); + + var pobj = new Proxy(target, {}); + + // Check [[Prototype]] before attempted mutation + assertEq(Object.getPrototypeOf(pobj), initialProto); + assertEq(protoGetter.call(pobj), initialProto); + + // Attempt [[Prototype]] mutation + protoSetter.call(pobj, null); + + // Check [[Prototype]] after attempted mutation + assertEq(Object.getPrototypeOf(pobj), null); + assertEq(protoGetter.call(pobj), null); + assertEq(Object.getPrototypeOf(target), null); +} + +// Proxy object with non-null [[Prototype]] +var nonNullProto = { toString: function() { return "non-null prototype"; } }; +var target = Object.create(nonNullProto); +testProxy(target, nonNullProto); + +// Proxy object with null [[Prototype]] +target = Object.create(null); +target.toString = function() { return "null prototype" }; +testProxy(target, null); + +// Proxy function with [[Call]] +var callForCallOnly = function () { }; +callForCallOnly.toString = function() { return "callable target"; }; +testProxy(callForCallOnly, Function.prototype); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/ecma_6/Proxy/regress-bug950407.js b/js/src/tests/ecma_6/Proxy/regress-bug950407.js new file mode 100644 index 000000000000..1a72c27bf78a --- /dev/null +++ b/js/src/tests/ecma_6/Proxy/regress-bug950407.js @@ -0,0 +1,11 @@ +var ab = ArrayBuffer(5); +var p = new Proxy(ab, {}); +var ps = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").set; +var threw = 0; +try { + ps.call(p, {}); +} catch(ex) { + threw = 1; +} + +reportCompare(1, threw, "Setting __proto__ on a proxy to an ArrayBuffer must throw."); diff --git a/js/src/tests/ecma_6/Proxy/shell.js b/js/src/tests/ecma_6/Proxy/shell.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/js/src/vm/ForkJoin.cpp b/js/src/vm/ForkJoin.cpp index a1178cb112a1..3d181f17c36c 100644 --- a/js/src/vm/ForkJoin.cpp +++ b/js/src/vm/ForkJoin.cpp @@ -158,8 +158,8 @@ intrinsic_SetForkJoinTargetRegionPar(ForkJoinSlice *slice, unsigned argc, Value return true; } -const JSJitInfo js::intrinsic_SetForkJoinTargetRegionInfo = - JS_JITINFO_NATIVE_PARALLEL(intrinsic_SetForkJoinTargetRegionPar); +JS_JITINFO_NATIVE_PARALLEL(js::intrinsic_SetForkJoinTargetRegionInfo, + intrinsic_SetForkJoinTargetRegionPar); #endif // !JS_THREADSAFE || !JS_ION @@ -2161,7 +2161,7 @@ intrinsic_SetForkJoinTargetRegionPar(ForkJoinSlice *slice, unsigned argc, Value return true; } -const JSJitInfo js::intrinsic_SetForkJoinTargetRegionInfo = - JS_JITINFO_NATIVE_PARALLEL(intrinsic_SetForkJoinTargetRegionPar); +JS_JITINFO_NATIVE_PARALLEL(js::intrinsic_SetForkJoinTargetRegionInfo, + intrinsic_SetForkJoinTargetRegionPar); #endif // JS_THREADSAFE && JS_ION diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index b62d678e410d..bc4bbf8fbe6f 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -123,17 +123,6 @@ ProtoSetterImpl(JSContext *cx, CallArgs args) Rooted obj(cx, &args.thisv().toObject()); - /* - * Disallow mutating the [[Prototype]] on ArrayBuffer objects, which - * due to their complicated delegate-object shenanigans can't easily - * have a mutable [[Prototype]]. - */ - if (obj->is()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO, - "Object", "__proto__ setter", "ArrayBuffer"); - return false; - } - /* Do nothing if __proto__ isn't being set to an object or null. */ if (args.length() == 0 || !args[0].isObjectOrNull()) { args.rval().setUndefined(); @@ -142,18 +131,12 @@ ProtoSetterImpl(JSContext *cx, CallArgs args) Rooted newProto(cx, args[0].toObjectOrNull()); - unsigned dummy; - RootedId nid(cx, NameToId(cx->names().proto)); - RootedValue v(cx); - if (!CheckAccess(cx, obj, nid, JSAccessMode(JSACC_PROTO | JSACC_WRITE), &v, &dummy)) - return false; - bool success; if (!JSObject::setProto(cx, obj, newProto, &success)) return false; if (!success) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL); + js_ReportValueError(cx, JSMSG_SETPROTOTYPEOF_FAIL, JSDVG_IGNORE_STACK, thisv, js::NullPtr()); return false; } diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp index 90bc567c8871..de3216fc5bc3 100644 --- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -296,7 +296,6 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads) #ifdef DEBUG noGCOrAllocationCheck(0), #endif - jitHardening(false), jitSupportsFloatingPoint(false), ionPcScriptCache(nullptr), threadPool(this), @@ -660,23 +659,13 @@ JSRuntime::triggerOperationCallback(OperationCallbackTrigger trigger) #endif } -void -JSRuntime::setJitHardening(bool enabled) -{ - jitHardening = enabled; - if (execAlloc_) - execAlloc_->setRandomize(enabled); -} - JSC::ExecutableAllocator * JSRuntime::createExecutableAllocator(JSContext *cx) { JS_ASSERT(!execAlloc_); JS_ASSERT(cx->runtime() == this); - JSC::AllocationBehavior randomize = - jitHardening ? JSC::AllocationCanRandomize : JSC::AllocationDeterministic; - execAlloc_ = js_new(randomize); + execAlloc_ = js_new(); if (!execAlloc_) js_ReportOutOfMemory(cx); return execAlloc_; diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h index 80e2b1f96e07..92656f621eea 100644 --- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -1647,8 +1647,6 @@ struct JSRuntime : public JS::shadow::Runtime, size_t noGCOrAllocationCheck; #endif - bool jitHardening; - bool jitSupportsFloatingPoint; // Used to reset stack limit after a signaled interrupt (i.e. ionStackLimit_ = -1) @@ -1767,11 +1765,6 @@ struct JSRuntime : public JS::shadow::Runtime, void triggerOperationCallback(OperationCallbackTrigger trigger); - void setJitHardening(bool enabled); - bool getJitHardening() const { - return jitHardening; - } - void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes *runtime); private: diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index f9676bc54c6d..ba05bef15304 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -266,8 +266,8 @@ intrinsic_Dump(ThreadSafeContext *cx, unsigned argc, Value *vp) return true; } -const JSJitInfo intrinsic_Dump_jitInfo = - JS_JITINFO_NATIVE_PARALLEL(JSParallelNativeThreadSafeWrapper); +JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(intrinsic_Dump_jitInfo, intrinsic_Dump_jitInfo, + intrinsic_Dump); bool intrinsic_ParallelSpew(ThreadSafeContext *cx, unsigned argc, Value *vp) @@ -287,8 +287,8 @@ intrinsic_ParallelSpew(ThreadSafeContext *cx, unsigned argc, Value *vp) return true; } -const JSJitInfo intrinsic_ParallelSpew_jitInfo = - JS_JITINFO_NATIVE_PARALLEL(JSParallelNativeThreadSafeWrapper); +JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(intrinsic_ParallelSpew_jitInfo, intrinsic_ParallelSpew_jitInfo, + intrinsic_ParallelSpew); #endif /* diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index 2df83cdd7805..efb6a50f548b 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -112,7 +112,7 @@ private: NS_IMETHODIMP nsXPCComponents_Interfaces::GetInterfaces(uint32_t *aCount, nsIID * **aArray) { - const uint32_t count = 3; + const uint32_t count = 2; *aCount = count; nsIID **array; *aArray = array = static_cast(nsMemory::Alloc(count * sizeof(nsIID*))); @@ -130,7 +130,6 @@ nsXPCComponents_Interfaces::GetInterfaces(uint32_t *aCount, nsIID * **aArray) PUSH_IID(nsIXPCComponents_Interfaces) PUSH_IID(nsIXPCScriptable) - PUSH_IID(nsISecurityCheckedComponent) #undef PUSH_IID return NS_OK; @@ -361,7 +360,7 @@ private: NS_IMETHODIMP nsXPCComponents_InterfacesByID::GetInterfaces(uint32_t *aCount, nsIID * **aArray) { - const uint32_t count = 3; + const uint32_t count = 2; *aCount = count; nsIID **array; *aArray = array = static_cast(nsMemory::Alloc(count * sizeof(nsIID*))); @@ -379,7 +378,6 @@ nsXPCComponents_InterfacesByID::GetInterfaces(uint32_t *aCount, nsIID * **aArray PUSH_IID(nsIXPCComponents_InterfacesByID) PUSH_IID(nsIXPCScriptable) - PUSH_IID(nsISecurityCheckedComponent) #undef PUSH_IID return NS_OK; diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 1665cbe0ea38..210956a2b9c5 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -77,6 +77,7 @@ const char* const XPCJSRuntime::mStrings[] = { "__iterator__", // IDX_ITERATOR "__exposedProps__", // IDX_EXPOSEDPROPS "eval", // IDX_EVAL + "controllers", // IDX_CONTROLLERS }; /***************************************************************************/ diff --git a/js/xpconnect/src/XPCWrappedJSClass.cpp b/js/xpconnect/src/XPCWrappedJSClass.cpp index 912d8523f3b1..2cd7150cd3ff 100644 --- a/js/xpconnect/src/XPCWrappedJSClass.cpp +++ b/js/xpconnect/src/XPCWrappedJSClass.cpp @@ -492,64 +492,6 @@ GetContextFromObjectOrDefault(nsXPCWrappedJS* wrapper) return stack->GetSafeJSContext(); } -class SameOriginCheckedComponent MOZ_FINAL : public nsISecurityCheckedComponent -{ -public: - SameOriginCheckedComponent(nsXPCWrappedJS* delegate) - : mDelegate(delegate) - {} - - NS_DECL_ISUPPORTS - NS_DECL_NSISECURITYCHECKEDCOMPONENT - -private: - nsRefPtr mDelegate; -}; - -NS_IMPL_ADDREF(SameOriginCheckedComponent) -NS_IMPL_RELEASE(SameOriginCheckedComponent) - -NS_INTERFACE_MAP_BEGIN(SameOriginCheckedComponent) - NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent) -NS_INTERFACE_MAP_END_AGGREGATED(mDelegate) - -NS_IMETHODIMP -SameOriginCheckedComponent::CanCreateWrapper(const nsIID * iid, - char **_retval) -{ - // XXX This doesn't actually work because nsScriptSecurityManager doesn't - // know what to do with "sameOrigin" for canCreateWrapper. - *_retval = NS_strdup("sameOrigin"); - return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY; -} - -NS_IMETHODIMP -SameOriginCheckedComponent::CanCallMethod(const nsIID * iid, - const char16_t *methodName, - char **_retval) -{ - *_retval = NS_strdup("sameOrigin"); - return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY; -} - -NS_IMETHODIMP -SameOriginCheckedComponent::CanGetProperty(const nsIID * iid, - const char16_t *propertyName, - char **_retval) -{ - *_retval = NS_strdup("sameOrigin"); - return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY; -} - -NS_IMETHODIMP -SameOriginCheckedComponent::CanSetProperty(const nsIID * iid, - const char16_t *propertyName, - char **_retval) -{ - *_retval = NS_strdup("sameOrigin"); - return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY; -} - NS_IMETHODIMP nsXPCWrappedJSClass::DelegatedQueryInterface(nsXPCWrappedJS* self, REFNSIID aIID, @@ -626,46 +568,6 @@ nsXPCWrappedJSClass::DelegatedQueryInterface(nsXPCWrappedJS* self, // else we do the more expensive stuff... - // Before calling out, ensure that we're not about to claim to implement - // nsISecurityCheckedComponent for an untrusted object. Doing so causes - // problems. See bug 352882. - // But if this is a content object, then we might be wrapping it for - // content. If our JS object isn't a double-wrapped object (that is, we - // don't have XPCWrappedJS(XPCWrappedNative(some C++ object))), then it - // definitely will not have classinfo (and therefore won't be a DOM - // object). Since content wants to be able to use these objects (directly - // or indirectly, see bug 483672), we implement nsISecurityCheckedComponent - // for them and tell caps that they are also bound by the same origin - // model. - - if (aIID.Equals(NS_GET_IID(nsISecurityCheckedComponent))) { - // XXX This code checks to see if the given object has chrome (also - // known as system) principals. It really wants to do a - // UniversalXPConnect type check. - - *aInstancePtr = nullptr; - - nsXPConnect *xpc = nsXPConnect::XPConnect(); - nsCOMPtr secMan = - do_QueryInterface(xpc->GetDefaultSecurityManager()); - if (!secMan) - return NS_NOINTERFACE; - - RootedObject selfObj(ccx, self->GetJSObject()); - nsCOMPtr objPrin = GetObjectPrincipal(selfObj); - bool isSystem; - nsresult rv = secMan->IsSystemPrincipal(objPrin, &isSystem); - if ((NS_FAILED(rv) || !isSystem) && !IS_WN_REFLECTOR(selfObj)) { - // A content object. - nsRefPtr checked = - new SameOriginCheckedComponent(self); - if (!checked) - return NS_ERROR_OUT_OF_MEMORY; - *aInstancePtr = checked.forget().get(); - return NS_OK; - } - } - // check if the JSObject claims to implement this interface RootedObject jsobj(ccx, CallQueryInterfaceOnJSObject(ccx, self->GetJSObject(), aIID)); diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index 0242fc67ff78..9465c54a2a99 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -149,7 +149,6 @@ #include "nsIPrincipal.h" #include "nsJSPrincipals.h" #include "nsIScriptObjectPrincipal.h" -#include "nsISecurityCheckedComponent.h" #include "xpcObjectHelper.h" #include "nsIThreadInternal.h" @@ -534,6 +533,7 @@ public: IDX_ITERATOR , IDX_EXPOSEDPROPS , IDX_EVAL , + IDX_CONTROLLERS , IDX_TOTAL_COUNT // just a count of the above }; diff --git a/js/xpconnect/tests/mochitest/test_bug912322.html b/js/xpconnect/tests/mochitest/test_bug912322.html index 22fcc9f96c50..c274b6afc465 100644 --- a/js/xpconnect/tests/mochitest/test_bug912322.html +++ b/js/xpconnect/tests/mochitest/test_bug912322.html @@ -18,8 +18,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=912322 ok(f in SpecialPowers.wrap(document), f + " should be available to chrome via Xray"); } - - + // Test window.controllers. + ok(typeof window.controllers, 'undefined', "controllers should not be available to content"); + ok(typeof SpecialPowers.wrap(window).controllers, 'object', "controllers should be available over Xray"); diff --git a/js/xpconnect/wrappers/XrayWrapper.cpp b/js/xpconnect/wrappers/XrayWrapper.cpp index 1cae0b4f9ffe..356b7aa517e8 100644 --- a/js/xpconnect/wrappers/XrayWrapper.cpp +++ b/js/xpconnect/wrappers/XrayWrapper.cpp @@ -10,6 +10,7 @@ #include "WrapperFactory.h" #include "nsIContent.h" +#include "nsIControllers.h" #include "nsContentUtils.h" #include "XPCWrapper.h" @@ -713,6 +714,32 @@ XPCWrappedNativeXrayTraits::resolveNativeProperty(JSContext *cx, HandleObject wr return resolveDOMCollectionProperty(cx, wrapper, holder, id, desc, flags); } + + // The |controllers| property is accessible as a [ChromeOnly] property on + // Window.WebIDL, and [noscript] in XPIDL. Chrome needs to see this over + // Xray, so we need to special-case it until we move |Window| to WebIDL. + nsGlobalWindow *win = nullptr; + if (id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_CONTROLLERS) && + AccessCheck::isChrome(wrapper) && + (win = static_cast(As(wrapper)))) + { + nsCOMPtr c; + nsresult rv = win->GetControllers(getter_AddRefs(c)); + if (NS_SUCCEEDED(rv) && c) { + rv = nsXPConnect::XPConnect()->WrapNativeToJSVal(cx, CurrentGlobalOrNull(cx), + c, nullptr, nullptr, true, + desc.value()); + } + + if (NS_FAILED(rv) || !c) { + JS_ReportError(cx, "Failed to invoke GetControllers via Xrays"); + return false; + } + + desc.object().set(wrapper); + return true; + } + XPCNativeInterface *iface; XPCNativeMember *member; XPCWrappedNative *wn = getWN(wrapper); diff --git a/layout/forms/nsComboboxControlFrame.cpp b/layout/forms/nsComboboxControlFrame.cpp index 5daa0b1d5866..0b4714ed6023 100644 --- a/layout/forms/nsComboboxControlFrame.cpp +++ b/layout/forms/nsComboboxControlFrame.cpp @@ -446,8 +446,8 @@ nsComboboxControlFrame::ReflowDropdown(nsPresContext* aPresContext, ignoredStatus); // Set the child's width and height to its desired size - FinishReflowChild(mDropdownFrame, aPresContext, &kidReflowState, - desiredSize, rect.x, rect.y, flags); + FinishReflowChild(mDropdownFrame, aPresContext, desiredSize, + &kidReflowState, rect.x, rect.y, flags); return rv; } diff --git a/layout/forms/nsFieldSetFrame.cpp b/layout/forms/nsFieldSetFrame.cpp index eeb582ce0ac8..a5c2bcf8eb4c 100644 --- a/layout/forms/nsFieldSetFrame.cpp +++ b/layout/forms/nsFieldSetFrame.cpp @@ -512,8 +512,8 @@ nsFieldSetFrame::Reflow(nsPresContext* aPresContext, reflowInner = true; } - FinishReflowChild(legend, aPresContext, &legendReflowState.ref(), - legendDesiredSize, 0, 0, NS_FRAME_NO_MOVE_FRAME); + FinishReflowChild(legend, aPresContext, legendDesiredSize, + &legendReflowState.ref(), 0, 0, NS_FRAME_NO_MOVE_FRAME); } else if (!legend) { mLegendRect.SetEmpty(); mLegendSpace = 0; @@ -557,8 +557,8 @@ nsFieldSetFrame::Reflow(nsPresContext* aPresContext, ReflowChild(inner, aPresContext, kidDesiredSize, kidReflowState, pt.x, pt.y, 0, aStatus); - FinishReflowChild(inner, aPresContext, &kidReflowState, - kidDesiredSize, pt.x, pt.y, 0); + FinishReflowChild(inner, aPresContext, kidDesiredSize, + &kidReflowState, pt.x, pt.y, 0); NS_FRAME_TRACE_REFLOW_OUT("FieldSet::Reflow", aStatus); } diff --git a/layout/forms/nsHTMLButtonControlFrame.cpp b/layout/forms/nsHTMLButtonControlFrame.cpp index 5d84d4ca8f59..6e6ab4d2d272 100644 --- a/layout/forms/nsHTMLButtonControlFrame.cpp +++ b/layout/forms/nsHTMLButtonControlFrame.cpp @@ -329,7 +329,7 @@ nsHTMLButtonControlFrame::ReflowButtonContents(nsPresContext* aPresContext, // Place the child FinishReflowChild(aFirstKid, aPresContext, - &contentsReflowState, contentsDesiredSize, + contentsDesiredSize, &contentsReflowState, xoffset, yoffset, 0); // Make sure we have a useful 'ascent' value for the child diff --git a/layout/forms/nsMeterFrame.cpp b/layout/forms/nsMeterFrame.cpp index 4403acddddef..b7a3996fa60f 100644 --- a/layout/forms/nsMeterFrame.cpp +++ b/layout/forms/nsMeterFrame.cpp @@ -182,7 +182,7 @@ nsMeterFrame::ReflowBarFrame(nsIFrame* aBarFrame, nsHTMLReflowMetrics barDesiredSize(reflowState.GetWritingMode()); ReflowChild(aBarFrame, aPresContext, barDesiredSize, reflowState, xoffset, yoffset, 0, aStatus); - FinishReflowChild(aBarFrame, aPresContext, &reflowState, barDesiredSize, + FinishReflowChild(aBarFrame, aPresContext, barDesiredSize, &reflowState, xoffset, yoffset, 0); } diff --git a/layout/forms/nsNumberControlFrame.cpp b/layout/forms/nsNumberControlFrame.cpp index d10b835450f4..1624c8b7da86 100644 --- a/layout/forms/nsNumberControlFrame.cpp +++ b/layout/forms/nsNumberControlFrame.cpp @@ -150,7 +150,7 @@ nsNumberControlFrame:: MOZ_ASSERT(NS_FRAME_IS_FULLY_COMPLETE(childStatus), "We gave our child unconstrained height, so it should be complete"); return FinishReflowChild(aOuterWrapperFrame, aPresContext, - &wrapperReflowState, aWrappersDesiredSize, + aWrappersDesiredSize, &wrapperReflowState, xoffset, yoffset, 0); } diff --git a/layout/forms/nsProgressFrame.cpp b/layout/forms/nsProgressFrame.cpp index 3a89865e65cf..74d04adb77d7 100644 --- a/layout/forms/nsProgressFrame.cpp +++ b/layout/forms/nsProgressFrame.cpp @@ -196,7 +196,7 @@ nsProgressFrame::ReflowBarFrame(nsIFrame* aBarFrame, nsHTMLReflowMetrics barDesiredSize(aReflowState.GetWritingMode()); ReflowChild(aBarFrame, aPresContext, barDesiredSize, reflowState, xoffset, yoffset, 0, aStatus); - FinishReflowChild(aBarFrame, aPresContext, &reflowState, barDesiredSize, + FinishReflowChild(aBarFrame, aPresContext, barDesiredSize, &reflowState, xoffset, yoffset, 0); } diff --git a/layout/forms/nsRangeFrame.cpp b/layout/forms/nsRangeFrame.cpp index 5724e7a01cfb..8b3327d44ee6 100644 --- a/layout/forms/nsRangeFrame.cpp +++ b/layout/forms/nsRangeFrame.cpp @@ -356,8 +356,8 @@ nsRangeFrame::ReflowAnonymousContent(nsPresContext* aPresContext, NS_ENSURE_SUCCESS(rv, rv); MOZ_ASSERT(NS_FRAME_IS_FULLY_COMPLETE(frameStatus), "We gave our child unconstrained height, so it should be complete"); - rv = FinishReflowChild(trackFrame, aPresContext, &trackReflowState, - trackDesiredSize, trackX, trackY, 0); + rv = FinishReflowChild(trackFrame, aPresContext, trackDesiredSize, + &trackReflowState, trackX, trackY, 0); NS_ENSURE_SUCCESS(rv, rv); } @@ -378,8 +378,8 @@ nsRangeFrame::ReflowAnonymousContent(nsPresContext* aPresContext, NS_ENSURE_SUCCESS(rv, rv); MOZ_ASSERT(NS_FRAME_IS_FULLY_COMPLETE(frameStatus), "We gave our child unconstrained height, so it should be complete"); - rv = FinishReflowChild(thumbFrame, aPresContext, &thumbReflowState, - thumbDesiredSize, 0, 0, 0); + rv = FinishReflowChild(thumbFrame, aPresContext, thumbDesiredSize, + &thumbReflowState, 0, 0, 0); NS_ENSURE_SUCCESS(rv, rv); DoUpdateThumbPosition(thumbFrame, nsSize(aDesiredSize.Width(), @@ -407,7 +407,7 @@ nsRangeFrame::ReflowAnonymousContent(nsPresContext* aPresContext, MOZ_ASSERT(NS_FRAME_IS_FULLY_COMPLETE(frameStatus), "We gave our child unconstrained height, so it should be complete"); rv = FinishReflowChild(rangeProgressFrame, aPresContext, - &progressReflowState, progressDesiredSize, 0, 0, 0); + progressDesiredSize, &progressReflowState, 0, 0, 0); NS_ENSURE_SUCCESS(rv, rv); DoUpdateRangeProgressFrame(rangeProgressFrame, nsSize(aDesiredSize.Width(), diff --git a/layout/forms/nsTextControlFrame.cpp b/layout/forms/nsTextControlFrame.cpp index 8133f5c955a9..04593493c882 100644 --- a/layout/forms/nsTextControlFrame.cpp +++ b/layout/forms/nsTextControlFrame.cpp @@ -549,8 +549,8 @@ nsTextControlFrame::ReflowTextControlChild(nsIFrame* aKid, xOffset, yOffset, 0, aStatus); // place the child - FinishReflowChild(aKid, aPresContext, &kidReflowState, - desiredSize, xOffset, yOffset, 0); + FinishReflowChild(aKid, aPresContext, desiredSize, + &kidReflowState, xOffset, yOffset, 0); // consider the overflow aParentDesiredSize.mOverflowAreas.UnionWith(desiredSize.mOverflowAreas); diff --git a/layout/generic/nsBlockReflowContext.cpp b/layout/generic/nsBlockReflowContext.cpp index a409e0eb145d..195af85bfcde 100644 --- a/layout/generic/nsBlockReflowContext.cpp +++ b/layout/generic/nsBlockReflowContext.cpp @@ -392,8 +392,8 @@ nsBlockReflowContext::PlaceBlock(const nsHTMLReflowState& aReflowState, aReflowState.ApplyRelativePositioning(&position); // Now place the frame and complete the reflow process - nsContainerFrame::FinishReflowChild(mFrame, mPresContext, &aReflowState, - mMetrics, position.x, position.y, 0); + nsContainerFrame::FinishReflowChild(mFrame, mPresContext, mMetrics, + &aReflowState, position.x, position.y, 0); aOverflowAreas = mMetrics.mOverflowAreas + position; diff --git a/layout/generic/nsCanvasFrame.cpp b/layout/generic/nsCanvasFrame.cpp index b6a407257b6a..edc7d9f1cc1d 100644 --- a/layout/generic/nsCanvasFrame.cpp +++ b/layout/generic/nsCanvasFrame.cpp @@ -521,7 +521,7 @@ nsCanvasFrame::Reflow(nsPresContext* aPresContext, kidPt.x, kidPt.y, 0, aStatus); // Complete the reflow and position and size the child frame - FinishReflowChild(kidFrame, aPresContext, &kidReflowState, kidDesiredSize, + FinishReflowChild(kidFrame, aPresContext, kidDesiredSize, &kidReflowState, kidPt.x, kidPt.y, 0); if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) { diff --git a/layout/generic/nsColumnSetFrame.cpp b/layout/generic/nsColumnSetFrame.cpp index ea19632fcdb9..a0079ed50041 100644 --- a/layout/generic/nsColumnSetFrame.cpp +++ b/layout/generic/nsColumnSetFrame.cpp @@ -591,8 +591,8 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize, *aBottomMarginCarriedOut = kidDesiredSize.mCarriedOutBottomMargin; - FinishReflowChild(child, PresContext(), &kidReflowState, - kidDesiredSize, childOrigin.x, childOrigin.y, 0); + FinishReflowChild(child, PresContext(), kidDesiredSize, + &kidReflowState, childOrigin.x, childOrigin.y, 0); childContentBottom = nsLayoutUtils::CalculateContentBottom(child); if (childContentBottom > aConfig.mColMaxHeight) { diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp index f59e05118950..cfb191f440ad 100644 --- a/layout/generic/nsContainerFrame.cpp +++ b/layout/generic/nsContainerFrame.cpp @@ -1034,8 +1034,8 @@ nsContainerFrame::PositionChildViews(nsIFrame* aFrame) nsresult nsContainerFrame::FinishReflowChild(nsIFrame* aKidFrame, nsPresContext* aPresContext, - const nsHTMLReflowState* aReflowState, const nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState* aReflowState, nscoord aX, nscoord aY, uint32_t aFlags) @@ -1158,7 +1158,7 @@ nsContainerFrame::ReflowOverflowContainerChildren(nsPresContext* aPres NS_ENSURE_SUCCESS(rv, rv); //XXXfr Do we need to override any shrinkwrap effects here? // e.g. desiredSize.Width() = prevRect.width; - rv = FinishReflowChild(frame, aPresContext, &frameState, desiredSize, + rv = FinishReflowChild(frame, aPresContext, desiredSize, &frameState, prevRect.x, 0, aFlags); NS_ENSURE_SUCCESS(rv, rv); diff --git a/layout/generic/nsContainerFrame.h b/layout/generic/nsContainerFrame.h index be9da874ed2d..519b45d7f072 100644 --- a/layout/generic/nsContainerFrame.h +++ b/layout/generic/nsContainerFrame.h @@ -227,8 +227,8 @@ public: */ static nsresult FinishReflowChild(nsIFrame* aKidFrame, nsPresContext* aPresContext, - const nsHTMLReflowState* aReflowState, const nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState* aReflowState, nscoord aX, nscoord aY, uint32_t aFlags); diff --git a/layout/generic/nsFlexContainerFrame.cpp b/layout/generic/nsFlexContainerFrame.cpp index 5da05bda0228..667b4044b437 100644 --- a/layout/generic/nsFlexContainerFrame.cpp +++ b/layout/generic/nsFlexContainerFrame.cpp @@ -953,7 +953,7 @@ nsFlexContainerFrame:: "should be complete"); rv = FinishReflowChild(aFlexItem.Frame(), aPresContext, - &childRSForMeasuringHeight, childDesiredSize, + childDesiredSize, &childRSForMeasuringHeight, 0, 0, flags); NS_ENSURE_SUCCESS(rv, rv); @@ -2526,7 +2526,7 @@ nsFlexContainerFrame::SizeItemInCrossAxis( // Tell the child we're done with its initial reflow. // (Necessary for e.g. GetBaseline() to work below w/out asserting) rv = FinishReflowChild(aItem.Frame(), aPresContext, - &aChildReflowState, childDesiredSize, 0, 0, flags); + childDesiredSize, &aChildReflowState, 0, 0, flags); NS_ENSURE_SUCCESS(rv, rv); // Save the sizing info that we learned from this reflow @@ -2863,7 +2863,7 @@ nsFlexContainerFrame::Reflow(nsPresContext* aPresContext, childReflowState.ApplyRelativePositioning(&physicalPosn); rv = FinishReflowChild(curItem.Frame(), aPresContext, - &childReflowState, childDesiredSize, + childDesiredSize, &childReflowState, physicalPosn.x, physicalPosn.y, 0); NS_ENSURE_SUCCESS(rv, rv); diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 18a4a5ae06e9..5bced56145ca 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -7975,8 +7975,8 @@ nsFrame::BoxReflow(nsBoxLayoutState& aState, NS_ASSERTION(NS_FRAME_IS_COMPLETE(status), "bad status"); uint32_t layoutFlags = aState.LayoutFlags(); - nsContainerFrame::FinishReflowChild(this, aPresContext, &reflowState, - aDesiredSize, aX, aY, layoutFlags | NS_FRAME_NO_MOVE_FRAME); + nsContainerFrame::FinishReflowChild(this, aPresContext, aDesiredSize, + &reflowState, aX, aY, layoutFlags | NS_FRAME_NO_MOVE_FRAME); // Save the ascent. (bug 103925) if (IsCollapsed()) { diff --git a/layout/generic/nsFrameSetFrame.cpp b/layout/generic/nsFrameSetFrame.cpp index ad6cbee9b2d2..c3a1cd06654b 100644 --- a/layout/generic/nsFrameSetFrame.cpp +++ b/layout/generic/nsFrameSetFrame.cpp @@ -751,7 +751,7 @@ nsHTMLFramesetFrame::ReflowPlaceChild(nsIFrame* aChild, // Place and size the child metrics.Width() = aSize.width; metrics.Height() = aSize.height; - FinishReflowChild(aChild, aPresContext, nullptr, metrics, aOffset.x, aOffset.y, 0); + FinishReflowChild(aChild, aPresContext, metrics, nullptr, aOffset.x, aOffset.y, 0); } static diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 39ea0d4a0280..aee0cfa9b243 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -467,7 +467,7 @@ nsHTMLScrollFrame::ReflowScrolledFrame(ScrollReflowState* aState, // which will usually be different from the scrollport height; // invalidating the difference will cause unnecessary repainting. FinishReflowChild(mHelper.mScrolledFrame, presContext, - &kidReflowState, *aMetrics, 0, 0, + *aMetrics, &kidReflowState, 0, 0, NS_FRAME_NO_MOVE_FRAME | NS_FRAME_NO_SIZE_VIEW); // XXX Some frames (e.g., nsObjectFrame, nsFrameFrame, nsTextFrame) don't bother diff --git a/layout/generic/nsHTMLCanvasFrame.cpp b/layout/generic/nsHTMLCanvasFrame.cpp index 90cdda7a89d8..e3533b4ade81 100644 --- a/layout/generic/nsHTMLCanvasFrame.cpp +++ b/layout/generic/nsHTMLCanvasFrame.cpp @@ -214,8 +214,8 @@ nsHTMLCanvasFrame::Reflow(nsPresContext* aPresContext, availSize); ReflowChild(childFrame, aPresContext, childDesiredSize, childReflowState, 0, 0, 0, childStatus, nullptr); - FinishReflowChild(childFrame, aPresContext, &childReflowState, - childDesiredSize, 0, 0, 0); + FinishReflowChild(childFrame, aPresContext, childDesiredSize, + &childReflowState, 0, 0, 0); NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("exit nsHTMLCanvasFrame::Reflow: size=%d,%d", diff --git a/layout/generic/nsPageContentFrame.cpp b/layout/generic/nsPageContentFrame.cpp index 66f151f80986..0676d9665ea7 100644 --- a/layout/generic/nsPageContentFrame.cpp +++ b/layout/generic/nsPageContentFrame.cpp @@ -81,7 +81,7 @@ nsPageContentFrame::Reflow(nsPresContext* aPresContext, } // Place and size the child - FinishReflowChild(frame, aPresContext, &kidReflowState, aDesiredSize, 0, 0, 0); + FinishReflowChild(frame, aPresContext, aDesiredSize, &kidReflowState, 0, 0, 0); NS_ASSERTION(aPresContext->IsDynamic() || !NS_FRAME_IS_FULLY_COMPLETE(aStatus) || !frame->GetNextInFlow(), "bad child flow list"); diff --git a/layout/generic/nsPageFrame.cpp b/layout/generic/nsPageFrame.cpp index 4a7722382482..0e711c5c8221 100644 --- a/layout/generic/nsPageFrame.cpp +++ b/layout/generic/nsPageFrame.cpp @@ -138,7 +138,7 @@ NS_IMETHODIMP nsPageFrame::Reflow(nsPresContext* aPresContext, ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, xc, yc, 0, aStatus); // Place and size the child - FinishReflowChild(frame, aPresContext, &kidReflowState, aDesiredSize, xc, yc, 0); + FinishReflowChild(frame, aPresContext, aDesiredSize, &kidReflowState, xc, yc, 0); NS_ASSERTION(!NS_FRAME_IS_FULLY_COMPLETE(aStatus) || !frame->GetNextInFlow(), "bad child flow list"); diff --git a/layout/generic/nsSimplePageSequence.cpp b/layout/generic/nsSimplePageSequence.cpp index c52ca3925204..101b13d7e1aa 100644 --- a/layout/generic/nsSimplePageSequence.cpp +++ b/layout/generic/nsSimplePageSequence.cpp @@ -223,7 +223,7 @@ nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext, // max width then center it horizontally ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, x, y, 0, status); - FinishReflowChild(kidFrame, aPresContext, nullptr, kidSize, x, y, 0); + FinishReflowChild(kidFrame, aPresContext, kidSize, nullptr, x, y, 0); y += kidSize.Height(); y += pageCSSMargin.bottom; diff --git a/layout/generic/nsVideoFrame.cpp b/layout/generic/nsVideoFrame.cpp index 50fe23f77f02..d0558b6d8429 100644 --- a/layout/generic/nsVideoFrame.cpp +++ b/layout/generic/nsVideoFrame.cpp @@ -306,7 +306,7 @@ nsVideoFrame::Reflow(nsPresContext* aPresContext, ReflowChild(imageFrame, aPresContext, kidDesiredSize, kidReflowState, posterTopLeft.x, posterTopLeft.y, 0, aStatus); - FinishReflowChild(imageFrame, aPresContext, &kidReflowState, kidDesiredSize, + FinishReflowChild(imageFrame, aPresContext, kidDesiredSize, &kidReflowState, posterTopLeft.x, posterTopLeft.y, 0); } else if (child->GetContent() == mVideoControls) { // Reflow the video controls frame. @@ -343,7 +343,7 @@ nsVideoFrame::Reflow(nsPresContext* aPresContext, ReflowChild(child, aPresContext, kidDesiredSize, kidReflowState, mBorderPadding.left, mBorderPadding.top, 0, aStatus); FinishReflowChild(child, aPresContext, - &kidReflowState, kidDesiredSize, + kidDesiredSize, &kidReflowState, mBorderPadding.left, mBorderPadding.top, 0); } } diff --git a/layout/generic/nsViewportFrame.cpp b/layout/generic/nsViewportFrame.cpp index 9d14b77e871f..913100afa3b9 100644 --- a/layout/generic/nsViewportFrame.cpp +++ b/layout/generic/nsViewportFrame.cpp @@ -222,7 +222,7 @@ ViewportFrame::Reflow(nsPresContext* aPresContext, 0, 0, 0, aStatus); kidHeight = kidDesiredSize.Height(); - FinishReflowChild(kidFrame, aPresContext, nullptr, kidDesiredSize, 0, 0, 0); + FinishReflowChild(kidFrame, aPresContext, kidDesiredSize, nullptr, 0, 0, 0); } else { kidHeight = mFrames.FirstChild()->GetSize().height; } diff --git a/layout/mathml/nsMathMLContainerFrame.cpp b/layout/mathml/nsMathMLContainerFrame.cpp index d9dd8f7cc1a8..14c397497f1f 100644 --- a/layout/mathml/nsMathMLContainerFrame.cpp +++ b/layout/mathml/nsMathMLContainerFrame.cpp @@ -1325,8 +1325,8 @@ nsMathMLContainerFrame::PositionRowChildFrames(nscoord aOffsetX, while (child.Frame()) { nscoord dx = aOffsetX + child.X(); nscoord dy = aBaseline - child.Ascent(); - FinishReflowChild(child.Frame(), PresContext(), nullptr, - child.ReflowMetrics(), dx, dy, 0); + FinishReflowChild(child.Frame(), PresContext(), child.ReflowMetrics(), + nullptr, dx, dy, 0); ++child; } } diff --git a/layout/mathml/nsMathMLSelectedFrame.cpp b/layout/mathml/nsMathMLSelectedFrame.cpp index 84788889083a..46b4cc0cbaf3 100644 --- a/layout/mathml/nsMathMLSelectedFrame.cpp +++ b/layout/mathml/nsMathMLSelectedFrame.cpp @@ -144,7 +144,7 @@ nsMathMLSelectedFrame::Place(nsRenderingContext& aRenderingContext, if (childFrame) { GetReflowAndBoundingMetricsFor(childFrame, aDesiredSize, mBoundingMetrics); if (aPlaceOrigin) { - FinishReflowChild(childFrame, PresContext(), nullptr, aDesiredSize, 0, 0, 0); + FinishReflowChild(childFrame, PresContext(), aDesiredSize, nullptr, 0, 0, 0); } mReference.x = 0; mReference.y = aDesiredSize.TopAscent(); diff --git a/layout/mathml/nsMathMLTokenFrame.cpp b/layout/mathml/nsMathMLTokenFrame.cpp index 781511b35ae4..4c39dad1ce88 100644 --- a/layout/mathml/nsMathMLTokenFrame.cpp +++ b/layout/mathml/nsMathMLTokenFrame.cpp @@ -215,7 +215,7 @@ nsMathMLTokenFrame::Place(nsRenderingContext& aRenderingContext, // place and size the child; (dx,0) makes the caret happy - bug 188146 dy = childSize.Height() == 0 ? 0 : aDesiredSize.TopAscent() - childSize.TopAscent(); - FinishReflowChild(childFrame, PresContext(), nullptr, childSize, dx, dy, 0); + FinishReflowChild(childFrame, PresContext(), childSize, nullptr, dx, dy, 0); dx += childSize.Width(); } } diff --git a/layout/mathml/nsMathMLmfencedFrame.cpp b/layout/mathml/nsMathMLmfencedFrame.cpp index e9dbc18b27ee..8c64f4ca259b 100644 --- a/layout/mathml/nsMathMLmfencedFrame.cpp +++ b/layout/mathml/nsMathMLmfencedFrame.cpp @@ -368,7 +368,7 @@ nsMathMLmfencedFrame::Reflow(nsPresContext* aPresContext, else aDesiredSize.mBoundingMetrics += bm; - FinishReflowChild(childFrame, aPresContext, nullptr, childSize, + FinishReflowChild(childFrame, aPresContext, childSize, nullptr, dx, ascent - childSize.TopAscent(), 0); dx += childSize.Width(); diff --git a/layout/mathml/nsMathMLmfracFrame.cpp b/layout/mathml/nsMathMLmfracFrame.cpp index a4f904bdf2cc..20318c39bca1 100644 --- a/layout/mathml/nsMathMLmfracFrame.cpp +++ b/layout/mathml/nsMathMLmfracFrame.cpp @@ -369,10 +369,10 @@ nsMathMLmfracFrame::PlaceInternal(nsRenderingContext& aRenderingContext, nscoord dy; // place numerator dy = 0; - FinishReflowChild(frameNum, presContext, nullptr, sizeNum, dxNum, dy, 0); + FinishReflowChild(frameNum, presContext, sizeNum, nullptr, dxNum, dy, 0); // place denominator dy = aDesiredSize.Height() - sizeDen.Height(); - FinishReflowChild(frameDen, presContext, nullptr, sizeDen, dxDen, dy, 0); + FinishReflowChild(frameDen, presContext, sizeDen, nullptr, dxDen, dy, 0); // place the fraction bar - dy is top of bar dy = aDesiredSize.TopAscent() - (axisHeight + actualRuleThickness/2); mLineRect.SetRect(leftSpace, dy, width - (leftSpace + rightSpace), @@ -483,7 +483,7 @@ nsMathMLmfracFrame::PlaceInternal(nsRenderingContext& aRenderingContext, dx = MirrorIfRTL(aDesiredSize.Width(), sizeNum.Width(), leadingSpace); dy = aDesiredSize.TopAscent() - numShift - sizeNum.TopAscent(); - FinishReflowChild(frameNum, presContext, nullptr, sizeNum, dx, dy, 0); + FinishReflowChild(frameNum, presContext, sizeNum, nullptr, dx, dy, 0); // place the fraction bar dx = MirrorIfRTL(aDesiredSize.Width(), mLineRect.width, @@ -496,7 +496,7 @@ nsMathMLmfracFrame::PlaceInternal(nsRenderingContext& aRenderingContext, dx = MirrorIfRTL(aDesiredSize.Width(), sizeDen.Width(), leadingSpace + bmNum.width + mLineRect.width); dy = aDesiredSize.TopAscent() + denShift - sizeDen.TopAscent(); - FinishReflowChild(frameDen, presContext, nullptr, sizeDen, dx, dy, 0); + FinishReflowChild(frameDen, presContext, sizeDen, nullptr, dx, dy, 0); } } diff --git a/layout/mathml/nsMathMLmmultiscriptsFrame.cpp b/layout/mathml/nsMathMLmmultiscriptsFrame.cpp index ab8a748f87aa..9869d56051e7 100644 --- a/layout/mathml/nsMathMLmmultiscriptsFrame.cpp +++ b/layout/mathml/nsMathMLmmultiscriptsFrame.cpp @@ -565,7 +565,7 @@ nsMathMLmmultiscriptsFrame::PlaceMultiScript(nsPresContext* aPresContext, // place the base ... childFrame = baseFrame; dy = aDesiredSize.TopAscent() - baseSize.TopAscent(); - FinishReflowChild (baseFrame, aPresContext, nullptr, baseSize, + FinishReflowChild (baseFrame, aPresContext, baseSize, nullptr, aFrame->MirrorIfRTL(aDesiredSize.Width(), baseSize.Width(), dx), @@ -598,8 +598,8 @@ nsMathMLmmultiscriptsFrame::PlaceMultiScript(nsPresContext* aPresContext, x += width - subScriptSize.Width(); dy = aDesiredSize.TopAscent() - subScriptSize.TopAscent() + maxSubScriptShift; - FinishReflowChild (subScriptFrame, aPresContext, nullptr, - subScriptSize, + FinishReflowChild (subScriptFrame, aPresContext, subScriptSize, + nullptr, aFrame->MirrorIfRTL(aDesiredSize.Width(), subScriptSize.Width(), x), @@ -612,8 +612,8 @@ nsMathMLmmultiscriptsFrame::PlaceMultiScript(nsPresContext* aPresContext, x += width - supScriptSize.Width(); dy = aDesiredSize.TopAscent() - supScriptSize.TopAscent() - maxSupScriptShift; - FinishReflowChild (supScriptFrame, aPresContext, nullptr, - supScriptSize, + FinishReflowChild (supScriptFrame, aPresContext, supScriptSize, + nullptr, aFrame->MirrorIfRTL(aDesiredSize.Width(), supScriptSize.Width(), x), diff --git a/layout/mathml/nsMathMLmrootFrame.cpp b/layout/mathml/nsMathMLmrootFrame.cpp index d49a3ee55b7b..665a7d35b540 100644 --- a/layout/mathml/nsMathMLmrootFrame.cpp +++ b/layout/mathml/nsMathMLmrootFrame.cpp @@ -327,7 +327,7 @@ nsMathMLmrootFrame::Reflow(nsPresContext* aPresContext, // place the index nscoord dx = dxIndex; nscoord dy = aDesiredSize.TopAscent() - (indexRaisedAscent + indexSize.TopAscent() - bmIndex.ascent); - FinishReflowChild(indexFrame, aPresContext, nullptr, indexSize, + FinishReflowChild(indexFrame, aPresContext, indexSize, nullptr, MirrorIfRTL(aDesiredSize.Width(), indexSize.Width(), dx), dy, 0); @@ -342,7 +342,7 @@ nsMathMLmrootFrame::Reflow(nsPresContext* aPresContext, // place the base dy = aDesiredSize.TopAscent() - baseSize.TopAscent(); - FinishReflowChild(baseFrame, aPresContext, nullptr, baseSize, + FinishReflowChild(baseFrame, aPresContext, baseSize, nullptr, MirrorIfRTL(aDesiredSize.Width(), baseSize.Width(), dx), dy, 0); diff --git a/layout/mathml/nsMathMLmunderoverFrame.cpp b/layout/mathml/nsMathMLmunderoverFrame.cpp index 7001dc0d77aa..712a95929818 100644 --- a/layout/mathml/nsMathMLmunderoverFrame.cpp +++ b/layout/mathml/nsMathMLmunderoverFrame.cpp @@ -607,16 +607,16 @@ nsMathMLmunderoverFrame::Place(nsRenderingContext& aRenderingContext, if (overFrame) { dy = aDesiredSize.TopAscent() - mBoundingMetrics.ascent + bmOver.ascent - overSize.TopAscent(); - FinishReflowChild (overFrame, PresContext(), nullptr, overSize, dxOver, dy, 0); + FinishReflowChild (overFrame, PresContext(), overSize, nullptr, dxOver, dy, 0); } // place base dy = aDesiredSize.TopAscent() - baseSize.TopAscent(); - FinishReflowChild (baseFrame, PresContext(), nullptr, baseSize, dxBase, dy, 0); + FinishReflowChild (baseFrame, PresContext(), baseSize, nullptr, dxBase, dy, 0); // place underscript if (underFrame) { dy = aDesiredSize.TopAscent() + mBoundingMetrics.descent - bmUnder.descent - underSize.TopAscent(); - FinishReflowChild (underFrame, PresContext(), nullptr, underSize, + FinishReflowChild (underFrame, PresContext(), underSize, nullptr, dxUnder, dy, 0); } } diff --git a/layout/svg/nsSVGForeignObjectFrame.cpp b/layout/svg/nsSVGForeignObjectFrame.cpp index 38e10814b2b5..92f08111f789 100644 --- a/layout/svg/nsSVGForeignObjectFrame.cpp +++ b/layout/svg/nsSVGForeignObjectFrame.cpp @@ -569,7 +569,7 @@ nsSVGForeignObjectFrame::DoReflow() NS_FRAME_NO_MOVE_FRAME, status); NS_ASSERTION(mRect.width == desiredSize.Width() && mRect.height == desiredSize.Height(), "unexpected size"); - FinishReflowChild(kid, presContext, &reflowState, desiredSize, 0, 0, + FinishReflowChild(kid, presContext, desiredSize, &reflowState, 0, 0, NS_FRAME_NO_MOVE_FRAME); mInReflow = false; diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp index 0f68b4a2a9ac..9a434fa72dea 100644 --- a/layout/tables/nsTableCellFrame.cpp +++ b/layout/tables/nsTableCellFrame.cpp @@ -948,7 +948,7 @@ NS_METHOD nsTableCellFrame::Reflow(nsPresContext* aPresContext, SetContentEmpty(isEmpty); // Place the child - FinishReflowChild(firstKid, aPresContext, &kidReflowState, kidSize, + FinishReflowChild(firstKid, aPresContext, kidSize, &kidReflowState, kidOrigin.x, kidOrigin.y, 0); nsTableFrame::InvalidateTableFrame(firstKid, origRect, origVisualOverflow, diff --git a/layout/tables/nsTableColGroupFrame.cpp b/layout/tables/nsTableColGroupFrame.cpp index e9ad4257ab98..ca6019d0d464 100644 --- a/layout/tables/nsTableColGroupFrame.cpp +++ b/layout/tables/nsTableColGroupFrame.cpp @@ -377,7 +377,7 @@ NS_METHOD nsTableColGroupFrame::Reflow(nsPresContext* aPresContext, nsReflowStatus status; ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, 0, 0, 0, status); - FinishReflowChild(kidFrame, aPresContext, nullptr, kidSize, 0, 0, 0); + FinishReflowChild(kidFrame, aPresContext, kidSize, nullptr, 0, 0, 0); } aDesiredSize.Width() = 0; diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index f644db232b78..3bef60f7e02a 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -2538,7 +2538,7 @@ void nsTableFrame::PlaceChild(nsTableReflowState& aReflowState, (aKidFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0; // Place and size the child - FinishReflowChild(aKidFrame, PresContext(), nullptr, aKidDesiredSize, + FinishReflowChild(aKidFrame, PresContext(), aKidDesiredSize, nullptr, aReflowState.x, aReflowState.y, 0); InvalidateTableFrame(aKidFrame, aOriginalKidRect, aOriginalKidVisualOverflow, @@ -3020,7 +3020,7 @@ nsTableFrame::ReflowColGroups(nsRenderingContext *aRenderingContext) nsReflowStatus cgStatus; ReflowChild(kidFrame, presContext, kidMet, kidReflowState, 0, 0, 0, cgStatus); - FinishReflowChild(kidFrame, presContext, nullptr, kidMet, 0, 0, 0); + FinishReflowChild(kidFrame, presContext, kidMet, nullptr, 0, 0, 0); } } SetHaveReflowedColGroups(true); diff --git a/layout/tables/nsTableOuterFrame.cpp b/layout/tables/nsTableOuterFrame.cpp index c6a7fce4648b..69dc517cb6e6 100644 --- a/layout/tables/nsTableOuterFrame.cpp +++ b/layout/tables/nsTableOuterFrame.cpp @@ -1032,8 +1032,8 @@ NS_METHOD nsTableOuterFrame::Reflow(nsPresContext* aPresContext, nsPoint captionOrigin; GetCaptionOrigin(captionSide, containSize, innerSize, innerMargin, captionSize, captionMargin, captionOrigin); - FinishReflowChild(mCaptionFrames.FirstChild(), aPresContext, captionRS, - captionMet, captionOrigin.x, captionOrigin.y, 0); + FinishReflowChild(mCaptionFrames.FirstChild(), aPresContext, captionMet, + captionRS, captionOrigin.x, captionOrigin.y, 0); captionRS->~nsHTMLReflowState(); } // XXX If the height is constrained then we need to check whether @@ -1042,7 +1042,7 @@ NS_METHOD nsTableOuterFrame::Reflow(nsPresContext* aPresContext, nsPoint innerOrigin; GetInnerOrigin(captionSide, containSize, captionSize, captionMargin, innerSize, innerMargin, innerOrigin); - FinishReflowChild(InnerTableFrame(), aPresContext, innerRS, innerMet, + FinishReflowChild(InnerTableFrame(), aPresContext, innerMet, innerRS, innerOrigin.x, innerOrigin.y, 0); innerRS->~nsHTMLReflowState(); diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp index 7d470a19e6d3..cae8758f2fe8 100644 --- a/layout/tables/nsTableRowFrame.cpp +++ b/layout/tables/nsTableRowFrame.cpp @@ -951,7 +951,7 @@ nsTableRowFrame::ReflowChildren(nsPresContext* aPresContext, // Place the child desiredSize.Width() = availCellWidth; - FinishReflowChild(kidFrame, aPresContext, nullptr, desiredSize, x, 0, 0); + FinishReflowChild(kidFrame, aPresContext, desiredSize, nullptr, x, 0, 0); nsTableFrame::InvalidateTableFrame(kidFrame, kidRect, kidVisualOverflow, firstReflow); diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp index b16b8795b8e1..452255768e80 100644 --- a/layout/tables/nsTableRowGroupFrame.cpp +++ b/layout/tables/nsTableRowGroupFrame.cpp @@ -270,7 +270,7 @@ nsTableRowGroupFrame::PlaceChild(nsPresContext* aPresContext, (aKidFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0; // Place and size the child - FinishReflowChild(aKidFrame, aPresContext, nullptr, aDesiredSize, 0, + FinishReflowChild(aKidFrame, aPresContext, aDesiredSize, nullptr, 0, aReflowState.y, 0); nsTableFrame::InvalidateTableFrame(aKidFrame, aOriginalKidRect, diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 084f7dc765c7..0f596d35b1f4 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -749,7 +749,6 @@ pref("javascript.options.ion.chrome", false); pref("javascript.options.asmjs", true); pref("javascript.options.parallel_parsing", true); pref("javascript.options.ion.parallel_compilation", true); -pref("javascript.options.jit_hardening", true); pref("javascript.options.typeinference.content", true); pref("javascript.options.typeinference.chrome", false); // This preference limits the memory usage of javascript. diff --git a/netwerk/base/public/security-prefs.js b/netwerk/base/public/security-prefs.js index 5d5f7cac0895..d5800eaa1deb 100644 --- a/netwerk/base/public/security-prefs.js +++ b/netwerk/base/public/security-prefs.js @@ -14,6 +14,8 @@ pref("security.ssl.enable_ocsp_stapling", true); pref("security.ssl.enable_false_start", true); pref("security.ssl.false_start.require-npn", true); pref("security.ssl.false_start.require-forward-secrecy", true); +pref("security.ssl.enable_npn", true); +pref("security.ssl.enable_alpn", false); pref("security.ssl3.ecdhe_rsa_aes_128_gcm_sha256", true); pref("security.ssl3.ecdhe_ecdsa_aes_128_gcm_sha256", true); diff --git a/security/manager/ssl/src/nsNSSCallbacks.cpp b/security/manager/ssl/src/nsNSSCallbacks.cpp index 7e0a00030573..f2b412584d32 100644 --- a/security/manager/ssl/src/nsNSSCallbacks.cpp +++ b/security/manager/ssl/src/nsNSSCallbacks.cpp @@ -892,7 +892,8 @@ PreliminaryHandshakeDone(PRFileDesc* fd) unsigned int npnlen; if (SSL_GetNextProto(fd, &state, npnbuf, &npnlen, 256) == SECSuccess) { - if (state == SSL_NEXT_PROTO_NEGOTIATED) { + if (state == SSL_NEXT_PROTO_NEGOTIATED || + state == SSL_NEXT_PROTO_SELECTED) { infoObject->SetNegotiatedNPN(reinterpret_cast(npnbuf), npnlen); } else { diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp index 5fe2374c3a3b..411bc9854665 100644 --- a/security/manager/ssl/src/nsNSSComponent.cpp +++ b/security/manager/ssl/src/nsNSSComponent.cpp @@ -1272,6 +1272,15 @@ nsNSSComponent::InitializeNSS() Preferences::GetBool("security.ssl.enable_false_start", FALSE_START_ENABLED_DEFAULT)); + /* SSL_ENABLE_NPN and SSL_ENABLE_ALPN also require calling + SSL_SetNextProtoNego in order for the extensions to be negotiated. + WebRTC does not do that so it will not use NPN or ALPN even when these + preferences are true. */ + SSL_OptionSetDefault(SSL_ENABLE_NPN, + Preferences::GetBool("security.ssl.enable_npn", true)); + SSL_OptionSetDefault(SSL_ENABLE_ALPN, + Preferences::GetBool("security.ssl.enable_alpn", false)); + if (NS_FAILED(InitializeCipherSuite())) { PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to initialize cipher suite settings\n")); return NS_ERROR_FAILURE; diff --git a/security/manager/ssl/tests/unit/test_ev_certs.js b/security/manager/ssl/tests/unit/test_ev_certs.js index 8dcac06d71da..68b1a7cac6d2 100644 --- a/security/manager/ssl/tests/unit/test_ev_certs.js +++ b/security/manager/ssl/tests/unit/test_ev_certs.js @@ -41,6 +41,8 @@ function failingOCSPResponder() { httpServer.registerPrefixHandler("/", function(request, response) { do_check_true(false); }); + httpServer.identity.setPrimary("http", "www.example.com", SERVER_PORT); + httpServer.identity.add("http", "crl.example.com", SERVER_PORT); httpServer.start(SERVER_PORT); return httpServer; } @@ -134,7 +136,10 @@ add_test(function() { add_test(function() { clearOCSPCache(); - let ocspResponder = failingOCSPResponder(); + // libpkix will attempt to validate the intermediate, which does have an + // OCSP URL. + let ocspResponder = isDebugBuild ? start_ocsp_responder(["int-ev-valid"]) + : failingOCSPResponder(); check_ee_for_ev("no-ocsp-url-cert", false); ocspResponder.stop(run_next_test); }); diff --git a/security/nss/TAG-INFO b/security/nss/TAG-INFO index ad6ce63c2b24..42eb1b47093e 100644 --- a/security/nss/TAG-INFO +++ b/security/nss/TAG-INFO @@ -1 +1 @@ -NSS_3_15_5_BETA1 +NSS_3_15_5_BETA2 diff --git a/security/nss/coreconf/WIN32.mk b/security/nss/coreconf/WIN32.mk index 168f9486f0ee..6d1297d87b8e 100644 --- a/security/nss/coreconf/WIN32.mk +++ b/security/nss/coreconf/WIN32.mk @@ -41,7 +41,7 @@ else _CC_BUILD := $(word 4,$(_CC_VERSION_WORDS)) _MSC_VER = $(_CC_VMAJOR)$(_CC_VMINOR) _MSC_VER_6 = 1200 - _MSC_VER_GTE18 := $(shell expr $(_MSC_VER) \>= 1800) + _MSC_VER_GE_18 := $(shell expr $(_MSC_VER) \>= 1800) ifeq ($(_CC_VMAJOR),14) # -DYNAMICBASE is only supported on VC8SP1 or newer, # so be very specific here! @@ -173,9 +173,9 @@ ifneq ($(_MSC_VER),$(_MSC_VER_6)) -we4015 -we4028 -we4033 -we4035 -we4045 -we4047 -we4053 -we4054 -we4063 \ -we4064 -we4078 -we4087 -we4090 -we4098 -we4390 -we4551 -we4553 -we4715 - ifeq ($(_MSC_VER_GTE18),1) - OS_CFLAGS += -FS - endif + ifeq ($(_MSC_VER_GE_18),1) + OS_CFLAGS += -FS + endif endif # !MSVC6 endif # NS_USE_GCC diff --git a/security/nss/coreconf/coreconf.dep b/security/nss/coreconf/coreconf.dep index 5182f75552c8..590d1bfaeee3 100644 --- a/security/nss/coreconf/coreconf.dep +++ b/security/nss/coreconf/coreconf.dep @@ -10,3 +10,4 @@ */ #error "Do not include this header file." + diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c index 5dc7248d5895..ffbab7f254f2 100644 --- a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c +++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c @@ -131,6 +131,8 @@ pkix_pl_AIAMgr_RegisterSelf(void *plContext) * non-NULL. * "domainName" * Address of a string pointing to a server name. Must be non-NULL. + * An empty string (which means no is given in the LDAP URL) is + * not supported. * "pClient" * Address at which the returned LDAPClient is stored. Must be non-NULL. * "plContext" @@ -155,6 +157,17 @@ pkix_pl_AiaMgr_FindLDAPClient( PKIX_ENTER(AIAMGR, "pkix_pl_AiaMgr_FindLDAPClient"); PKIX_NULLCHECK_THREE(aiaMgr, domainName, pClient); + /* + * An LDAP URL may not have a part, for example, + * ldap:///o=University%20of%20Michigan,c=US + * PKIX_PL_LdapDefaultClient doesn't know how to discover the default + * LDAP server, so we don't support this kind of LDAP URL. + */ + if (*domainName == '\0') { + /* Simulate a PKIX_PL_LdapDefaultClient_CreateByName failure. */ + PKIX_ERROR(PKIX_LDAPDEFAULTCLIENTCREATEBYNAMEFAILED); + } + /* create PKIX_PL_String from domain name */ PKIX_CHECK(PKIX_PL_String_Create (PKIX_ESCASCII, domainName, 0, &domainString, plContext), diff --git a/security/nss/lib/ssl/ssl.h b/security/nss/lib/ssl/ssl.h index 79987e69a393..b27af6658eb2 100644 --- a/security/nss/lib/ssl/ssl.h +++ b/security/nss/lib/ssl/ssl.h @@ -162,6 +162,25 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd); #define SSL_CBC_RANDOM_IV 23 #define SSL_ENABLE_OCSP_STAPLING 24 /* Request OCSP stapling (client) */ +/* SSL_ENABLE_NPN controls whether the NPN extension is enabled for the initial + * handshake when protocol negotiation is used. SSL_SetNextProtoCallback + * or SSL_SetNextProtoNego must be used to control the protocol negotiation; + * otherwise, the NPN extension will not be negotiated. SSL_ENABLE_NPN is + * currently enabled by default but this may change in future versions. + */ +#define SSL_ENABLE_NPN 25 + +/* SSL_ENABLE_ALPN controls whether the ALPN extension is enabled for the + * initial handshake when protocol negotiation is used. SSL_SetNextProtoNego + * (not SSL_SetNextProtoCallback) must be used to control the protocol + * negotiation; otherwise, the ALPN extension will not be negotiated. ALPN is + * not negotiated for renegotiation handshakes, even though the ALPN + * specification defines a way to use ALPN during renegotiations. + * SSL_ENABLE_ALPN is currently disabled by default, but this may change in + * future versions. + */ +#define SSL_ENABLE_ALPN 26 + #ifdef SSL_DEPRECATED_FUNCTION /* Old deprecated function names */ SSL_IMPORT SECStatus SSL_Enable(PRFileDesc *fd, int option, PRBool on); @@ -206,6 +225,16 @@ SSL_IMPORT SECStatus SSL_SetNextProtoCallback(PRFileDesc *fd, * protocol in server-preference order. If no matching protocol is found it * selects the first supported protocol. * + * Using this function also allows the client to transparently support ALPN. + * The same set of protocols will be advertised via ALPN and, if the server + * uses ALPN to select a protocol, SSL_GetNextProto will return + * SSL_NEXT_PROTO_SELECTED as the state. + * + * Since NPN uses the first protocol as the fallback protocol, when sending an + * ALPN extension, the first protocol is moved to the end of the list. This + * indicates that the fallback protocol is the least preferred. The other + * protocols should be in preference order. + * * The supported protocols are specified in |data| in wire-format (8-bit * length-prefixed). For example: "\010http/1.1\006spdy/2". */ SSL_IMPORT SECStatus SSL_SetNextProtoNego(PRFileDesc *fd, @@ -215,7 +244,8 @@ SSL_IMPORT SECStatus SSL_SetNextProtoNego(PRFileDesc *fd, typedef enum SSLNextProtoState { SSL_NEXT_PROTO_NO_SUPPORT = 0, /* No peer support */ SSL_NEXT_PROTO_NEGOTIATED = 1, /* Mutual agreement */ - SSL_NEXT_PROTO_NO_OVERLAP = 2 /* No protocol overlap found */ + SSL_NEXT_PROTO_NO_OVERLAP = 2, /* No protocol overlap found */ + SSL_NEXT_PROTO_SELECTED = 3 /* Server selected proto (ALPN) */ } SSLNextProtoState; /* SSL_GetNextProto can be used in the HandshakeCallback or any time after diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index a7144ea9a2b4..cc30306121ce 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -4840,6 +4840,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending) int actual_count = 0; PRBool isTLS = PR_FALSE; PRInt32 total_exten_len = 0; + unsigned paddingExtensionLen; unsigned numCompressionMethods; PRInt32 flags; @@ -5113,6 +5114,20 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending) length += 1 + ss->ssl3.hs.cookieLen; } + /* A padding extension may be included to ensure that the record containing + * the ClientHello doesn't have a length between 256 and 511 bytes + * (inclusive). Initial, ClientHello records with such lengths trigger bugs + * in F5 devices. + * + * This is not done for DTLS nor for renegotiation. */ + if (!IS_DTLS(ss) && isTLS && !ss->firstHsDone) { + paddingExtensionLen = ssl3_CalculatePaddingExtensionLength(length); + total_exten_len += paddingExtensionLen; + length += paddingExtensionLen; + } else { + paddingExtensionLen = 0; + } + rv = ssl3_AppendHandshakeHeader(ss, client_hello, length); if (rv != SECSuccess) { if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } @@ -5247,6 +5262,14 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending) return SECFailure; } maxBytes -= extLen; + + extLen = ssl3_AppendPaddingExtension(ss, paddingExtensionLen, maxBytes); + if (extLen < 0) { + if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } + return SECFailure; + } + maxBytes -= extLen; + PORT_Assert(!maxBytes); } @@ -10162,8 +10185,10 @@ ssl3_SendNextProto(sslSocket *ss) int padding_len; static const unsigned char padding[32] = {0}; - if (ss->ssl3.nextProto.len == 0) + if (ss->ssl3.nextProto.len == 0 || + ss->ssl3.nextProtoState == SSL_NEXT_PROTO_SELECTED) { return SECSuccess; + } PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); diff --git a/security/nss/lib/ssl/ssl3ext.c b/security/nss/lib/ssl/ssl3ext.c index da42bfd48bef..792a3b42117a 100644 --- a/security/nss/lib/ssl/ssl3ext.c +++ b/security/nss/lib/ssl/ssl3ext.c @@ -52,8 +52,12 @@ static SECStatus ssl3_HandleRenegotiationInfoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data); static SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data); +static SECStatus ssl3_ClientHandleAppProtoXtn(sslSocket *ss, + PRUint16 ex_type, SECItem *data); static SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data); +static PRInt32 ssl3_ClientSendAppProtoXtn(sslSocket *ss, PRBool append, + PRUint32 maxBytes); static PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes); static PRInt32 ssl3_SendUseSRTPXtn(sslSocket *ss, PRBool append, @@ -247,6 +251,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = { { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn }, { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn }, + { ssl_app_layer_protocol_xtn, &ssl3_ClientHandleAppProtoXtn }, { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn }, { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, { -1, NULL } @@ -273,6 +278,7 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = { #endif { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }, { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn }, + { ssl_app_layer_protocol_xtn, &ssl3_ClientSendAppProtoXtn }, { ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn }, { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn }, { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn } @@ -608,6 +614,16 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type, PORT_Assert(!ss->firstHsDone); + if (ssl3_ExtensionNegotiated(ss, ssl_app_layer_protocol_xtn)) { + /* If the server negotiated ALPN then it has already told us what protocol + * to use, so it doesn't make sense for us to try to negotiate a different + * one by sending the NPN handshake message. However, if we've negotiated + * NPN then we're required to send the NPN handshake message. Thus, these + * two extensions cannot both be negotiated on the same connection. */ + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + rv = ssl3_ValidateNextProtoNego(data->data, data->len); if (rv != SECSuccess) return rv; @@ -641,6 +657,43 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type, return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &result); } +static SECStatus +ssl3_ClientHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) +{ + const unsigned char* d = data->data; + PRUint16 name_list_len; + SECItem protocol_name; + + if (ssl3_ExtensionNegotiated(ss, ssl_next_proto_nego_xtn)) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + + /* The extension data from the server has the following format: + * uint16 name_list_len; + * uint8 len; + * uint8 protocol_name[len]; */ + if (data->len < 4 || data->len > 2 + 1 + 255) { + PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); + return SECFailure; + } + + name_list_len = ((PRUint16) d[0]) << 8 | + ((PRUint16) d[1]); + if (name_list_len != data->len - 2 || d[2] != data->len - 3) { + PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); + return SECFailure; + } + + protocol_name.data = data->data + 3; + protocol_name.len = data->len - 3; + + SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE); + ss->ssl3.nextProtoState = SSL_NEXT_PROTO_SELECTED; + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; + return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &protocol_name); +} + static PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes) @@ -648,7 +701,7 @@ ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss, PRBool append, PRInt32 extension_length; /* Renegotiations do not send this extension. */ - if (!ss->nextProtoCallback || ss->firstHsDone) { + if (!ss->opt.enableNPN || !ss->nextProtoCallback || ss->firstHsDone) { return 0; } @@ -674,6 +727,74 @@ loser: return -1; } +static PRInt32 +ssl3_ClientSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes) +{ + PRInt32 extension_length; + unsigned char *alpn_protos = NULL; + + /* Renegotiations do not send this extension. */ + if (!ss->opt.enableALPN || !ss->opt.nextProtoNego.data || ss->firstHsDone) { + return 0; + } + + extension_length = 2 /* extension type */ + 2 /* extension length */ + + 2 /* protocol name list length */ + + ss->opt.nextProtoNego.len; + + if (append && maxBytes >= extension_length) { + /* NPN requires that the client's fallback protocol is first in the + * list. However, ALPN sends protocols in preference order. So we + * allocate a buffer and move the first protocol to the end of the + * list. */ + SECStatus rv; + const unsigned int len = ss->opt.nextProtoNego.len; + + alpn_protos = PORT_Alloc(len); + if (alpn_protos == NULL) { + return SECFailure; + } + if (len > 0) { + /* Each protocol string is prefixed with a single byte length. */ + unsigned int i = ss->opt.nextProtoNego.data[0] + 1; + if (i <= len) { + memcpy(alpn_protos, &ss->opt.nextProtoNego.data[i], len - i); + memcpy(alpn_protos + len - i, ss->opt.nextProtoNego.data, i); + } else { + /* This seems to be invalid data so we'll send as-is. */ + memcpy(alpn_protos, ss->opt.nextProtoNego.data, len); + } + } + + rv = ssl3_AppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2); + if (rv != SECSuccess) { + goto loser; + } + rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); + if (rv != SECSuccess) { + goto loser; + } + rv = ssl3_AppendHandshakeVariable(ss, alpn_protos, len, 2); + PORT_Free(alpn_protos); + alpn_protos = NULL; + if (rv != SECSuccess) { + goto loser; + } + ss->xtnData.advertised[ss->xtnData.numAdvertised++] = + ssl_app_layer_protocol_xtn; + } else if (maxBytes < extension_length) { + return 0; + } + + return extension_length; + +loser: + if (alpn_protos) { + PORT_Free(alpn_protos); + } + return -1; +} + static SECStatus ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) @@ -2141,3 +2262,55 @@ ssl3_ClientSendSigAlgsXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes) loser: return -1; } + +unsigned int +ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength) +{ + unsigned int recordLength = 1 /* handshake message type */ + + 3 /* handshake message length */ + + clientHelloLength; + unsigned int extensionLength; + + if (recordLength < 256 || recordLength >= 512) { + return 0; + } + + extensionLength = 512 - recordLength; + /* Extensions take at least four bytes to encode. */ + if (extensionLength < 4) { + extensionLength = 4; + } + + return extensionLength; +} + +/* ssl3_AppendPaddingExtension possibly adds an extension which ensures that a + * ClientHello record is either < 256 bytes or is >= 512 bytes. This ensures + * that we don't trigger bugs in F5 products. */ +PRInt32 +ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen, + PRUint32 maxBytes) +{ + unsigned int paddingLen = extensionLen - 4; + static unsigned char padding[256]; + + if (extensionLen == 0) { + return 0; + } + + if (extensionLen < 4 || + extensionLen > maxBytes || + paddingLen > sizeof(padding)) { + PORT_Assert(0); + return -1; + } + + if (SECSuccess != ssl3_AppendHandshakeNumber(ss, ssl_padding_xtn, 2)) + return -1; + if (SECSuccess != ssl3_AppendHandshakeNumber(ss, paddingLen, 2)) + return -1; + if (SECSuccess != ssl3_AppendHandshake(ss, padding, paddingLen)) + return -1; + + return extensionLen; +} diff --git a/security/nss/lib/ssl/sslimpl.h b/security/nss/lib/ssl/sslimpl.h index eaf17af3fdd4..5f70d185b488 100644 --- a/security/nss/lib/ssl/sslimpl.h +++ b/security/nss/lib/ssl/sslimpl.h @@ -226,6 +226,13 @@ extern PRInt32 ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes, const ssl3HelloExtensionSender *sender); +extern unsigned int +ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength); + +extern PRInt32 +ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen, + PRUint32 maxBytes); + /* Socket ops */ struct sslSocketOpsStr { int (*connect) (sslSocket *, const PRNetAddr *); @@ -317,6 +324,8 @@ typedef struct sslOptionsStr { unsigned int enableFalseStart : 1; /* 23 */ unsigned int cbcRandomIV : 1; /* 24 */ unsigned int enableOCSPStapling : 1; /* 25 */ + unsigned int enableNPN : 1; /* 26 */ + unsigned int enableALPN : 1; /* 27 */ } sslOptions; typedef enum { sslHandshakingUndetermined = 0, diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c index 60916776d61b..15344b877bbe 100644 --- a/security/nss/lib/ssl/sslsock.c +++ b/security/nss/lib/ssl/sslsock.c @@ -78,7 +78,9 @@ static sslOptions ssl_defaults = { PR_FALSE, /* requireSafeNegotiation */ PR_FALSE, /* enableFalseStart */ PR_TRUE, /* cbcRandomIV */ - PR_FALSE /* enableOCSPStapling */ + PR_FALSE, /* enableOCSPStapling */ + PR_TRUE, /* enableNPN */ + PR_FALSE /* enableALPN */ }; /* @@ -764,6 +766,14 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on) ss->opt.enableOCSPStapling = on; break; + case SSL_ENABLE_NPN: + ss->opt.enableNPN = on; + break; + + case SSL_ENABLE_ALPN: + ss->opt.enableALPN = on; + break; + default: PORT_SetError(SEC_ERROR_INVALID_ARGS); rv = SECFailure; @@ -834,6 +844,8 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn) case SSL_ENABLE_FALSE_START: on = ss->opt.enableFalseStart; break; case SSL_CBC_RANDOM_IV: on = ss->opt.cbcRandomIV; break; case SSL_ENABLE_OCSP_STAPLING: on = ss->opt.enableOCSPStapling; break; + case SSL_ENABLE_NPN: on = ss->opt.enableNPN; break; + case SSL_ENABLE_ALPN: on = ss->opt.enableALPN; break; default: PORT_SetError(SEC_ERROR_INVALID_ARGS); @@ -895,6 +907,8 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn) case SSL_ENABLE_OCSP_STAPLING: on = ssl_defaults.enableOCSPStapling; break; + case SSL_ENABLE_NPN: on = ssl_defaults.enableNPN; break; + case SSL_ENABLE_ALPN: on = ssl_defaults.enableALPN; break; default: PORT_SetError(SEC_ERROR_INVALID_ARGS); @@ -1062,6 +1076,14 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on) ssl_defaults.enableOCSPStapling = on; break; + case SSL_ENABLE_NPN: + ssl_defaults.enableNPN = on; + break; + + case SSL_ENABLE_ALPN: + ssl_defaults.enableALPN = on; + break; + default: PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; diff --git a/security/nss/lib/ssl/sslt.h b/security/nss/lib/ssl/sslt.h index 6b93629340e5..fb25c6d7255b 100644 --- a/security/nss/lib/ssl/sslt.h +++ b/security/nss/lib/ssl/sslt.h @@ -187,11 +187,13 @@ typedef enum { #endif ssl_signature_algorithms_xtn = 13, ssl_use_srtp_xtn = 14, + ssl_app_layer_protocol_xtn = 16, ssl_session_ticket_xtn = 35, ssl_next_proto_nego_xtn = 13172, + ssl_padding_xtn = 35655, ssl_renegotiation_info_xtn = 0xff01 /* experimental number */ } SSLExtensionType; -#define SSL_MAX_EXTENSIONS 9 +#define SSL_MAX_EXTENSIONS 10 /* doesn't include ssl_padding_xtn. */ #endif /* __sslt_h_ */ diff --git a/testing/marionette/client/marionette/runner/base.py b/testing/marionette/client/marionette/runner/base.py index 12a1c5f19679..6e5988a2902f 100644 --- a/testing/marionette/client/marionette/runner/base.py +++ b/testing/marionette/client/marionette/runner/base.py @@ -12,6 +12,7 @@ import sys import time import traceback import random +import mozinfo import moznetwork import xml.dom.minidom as dom @@ -804,7 +805,8 @@ class BaseMarionetteTestRunner(object): manifest_tests = manifest.active_tests(exists=False, disabled=False, device=self.device, - app=self.appName) + app=self.appName, + **mozinfo.info) skip_tests = list(set([x['path'] for x in all_tests]) - set([x['path'] for x in manifest_tests])) for skipped in skip_tests: diff --git a/testing/marionette/client/requirements.txt b/testing/marionette/client/requirements.txt index cac871c70c69..8188cf847666 100644 --- a/testing/marionette/client/requirements.txt +++ b/testing/marionette/client/requirements.txt @@ -1,5 +1,6 @@ manifestdestiny mozhttpd >= 0.5 +mozinfo >= 0.7 mozprocess >= 0.9 mozrunner >= 5.15 mozdevice >= 0.22 diff --git a/testing/mochitest/runtests.py b/testing/mochitest/runtests.py index ae974e6872a6..d0a9e11a4041 100644 --- a/testing/mochitest/runtests.py +++ b/testing/mochitest/runtests.py @@ -1207,8 +1207,9 @@ class Mochitest(MochitestUtilsMixin): def record_last_test(self, line): """record last test on harness""" if "TEST-START" in line and "|" in line: - self.output_buffer = [] - self.running_test = True + if not line.endswith('Shutdown'): + self.output_buffer = [] + self.running_test = True self.harness.lastTestSeen = line.split("|")[1].strip() return line diff --git a/testing/profiles/prefs_general.js b/testing/profiles/prefs_general.js index 35a7e29d50ae..52c76f9dbdbc 100644 --- a/testing/profiles/prefs_general.js +++ b/testing/profiles/prefs_general.js @@ -27,7 +27,6 @@ user_pref("devtools.errorconsole.enabled", true); user_pref("devtools.debugger.remote-port", 6023); user_pref("layout.debug.enable_data_xbl", true); user_pref("browser.EULA.override", true); -user_pref("javascript.options.jit_hardening", true); user_pref("gfx.color_management.force_srgb", true); user_pref("network.manage-offline-status", false); user_pref("dom.min_background_timeout_value", 1000); diff --git a/widget/TextEvents.h b/widget/TextEvents.h index 92138f713839..e02280522212 100644 --- a/widget/TextEvents.h +++ b/widget/TextEvents.h @@ -394,7 +394,6 @@ private: , mExpandToClusterBoundary(true) , mSucceeded(false) { - MOZ_CRASH("WidgetSelectionEvent is created without proper arguments"); } public: