From fa1982b341e54bdee6baa03f0dd36b1a7b6f41fc Mon Sep 17 00:00:00 2001 From: "timeless%mozdev.org" Date: Wed, 29 Jun 2005 16:29:49 +0000 Subject: [PATCH] Bug 217967 FF104 crash [@ PL_DHashTableOperate ] changing caps access control prefs More consistent DomainPolicy lifecycle management avoids use of corrupted hashtable data patch by g.maone@informaction.com r=dveditz sr=shaver a=bsmedberg git-svn-id: svn://10.0.0.236/trunk@175300 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/caps/include/nsPrincipal.h | 2 +- .../caps/include/nsScriptSecurityManager.h | 33 +++++++++++++- mozilla/caps/src/nsPrincipal.cpp | 18 ++++++-- mozilla/caps/src/nsScriptSecurityManager.cpp | 43 +++++++++++++++---- 4 files changed, 82 insertions(+), 14 deletions(-) diff --git a/mozilla/caps/include/nsPrincipal.h b/mozilla/caps/include/nsPrincipal.h index ed1d6462802..5f0375bdc17 100755 --- a/mozilla/caps/include/nsPrincipal.h +++ b/mozilla/caps/include/nsPrincipal.h @@ -111,7 +111,7 @@ protected: // it is very rare that we actually have a certificate. nsAutoPtr mCert; - void* mSecurityPolicy; + DomainPolicy* mSecurityPolicy; nsCOMPtr mCodebase; nsCOMPtr mDomain; diff --git a/mozilla/caps/include/nsScriptSecurityManager.h b/mozilla/caps/include/nsScriptSecurityManager.h index 6602c0b34ee..e110b09409a 100644 --- a/mozilla/caps/include/nsScriptSecurityManager.h +++ b/mozilla/caps/include/nsScriptSecurityManager.h @@ -259,6 +259,13 @@ public: DomainPolicy() : mWildcardPolicy(nsnull), mRefCount(0) { + mGeneration = sGeneration; + +#ifdef DEBUG_CAPS_DomainPolicyLifeCycle + ++sObjects; + _printPopulationInfo(); +#endif + } PRBool Init() @@ -283,6 +290,12 @@ public: ~DomainPolicy() { PL_DHashTableFinish(this); + +#ifdef DEBUG_CAPS_DomainPolicyLifeCycle + --sObjects; + _printPopulationInfo(); +#endif + } void Hold() @@ -295,11 +308,29 @@ public: if (--mRefCount == 0) delete this; } - + + static void InvalidateAll() + { + sGeneration++; + } + + PRBool IsInvalid() + { + return mGeneration != sGeneration; + } + ClassPolicy* mWildcardPolicy; private: PRUint32 mRefCount; + PRUint32 mGeneration; + static PRUint32 sGeneration; + +#ifdef DEBUG_CAPS_DomainPolicyLifeCycle + static PRUint32 sObjects; + static void _printPopulationInfo(); +#endif + }; ///////////////////////////// diff --git a/mozilla/caps/src/nsPrincipal.cpp b/mozilla/caps/src/nsPrincipal.cpp index 975a8705e47..f68547a3228 100755 --- a/mozilla/caps/src/nsPrincipal.cpp +++ b/mozilla/caps/src/nsPrincipal.cpp @@ -140,6 +140,7 @@ deleteElement(void* aElement, void *aData) nsPrincipal::~nsPrincipal(void) { mAnnotations.EnumerateForwards(deleteElement, nsnull); + SetSecurityPolicy(nsnull); } NS_IMETHODIMP @@ -196,14 +197,25 @@ nsPrincipal::GetOrigin(char **aOrigin) NS_IMETHODIMP nsPrincipal::GetSecurityPolicy(void** aSecurityPolicy) { - *aSecurityPolicy = mSecurityPolicy; + if (mSecurityPolicy && mSecurityPolicy->IsInvalid()) + SetSecurityPolicy(nsnull); + + *aSecurityPolicy = (void *) mSecurityPolicy; return NS_OK; } NS_IMETHODIMP nsPrincipal::SetSecurityPolicy(void* aSecurityPolicy) { - mSecurityPolicy = aSecurityPolicy; + DomainPolicy *newPolicy = NS_REINTERPRET_CAST( + DomainPolicy *, aSecurityPolicy); + if (newPolicy) + newPolicy->Hold(); + + if (mSecurityPolicy) + mSecurityPolicy->Drop(); + + mSecurityPolicy = newPolicy; return NS_OK; } @@ -558,7 +570,7 @@ nsPrincipal::SetDomain(nsIURI* aDomain) { mDomain = aDomain; // Domain has changed, forget cached security policy - mSecurityPolicy = nsnull; + SetSecurityPolicy(nsnull); return NS_OK; } diff --git a/mozilla/caps/src/nsScriptSecurityManager.cpp b/mozilla/caps/src/nsScriptSecurityManager.cpp index a6d8ab63063..b10888c4d60 100644 --- a/mozilla/caps/src/nsScriptSecurityManager.cpp +++ b/mozilla/caps/src/nsScriptSecurityManager.cpp @@ -121,6 +121,17 @@ inline void SetPendingException(JSContext *cx, const PRUnichar *aMsg) JS_SetPendingException(cx, STRING_TO_JSVAL(str)); } +// DomainPolicy members +#ifdef DEBUG_CAPS_DomainPolicyLifeCycle +PRUint32 DomainPolicy::sObjects=0; +void DomainPolicy::_printPopulationInfo() +{ + printf("CAPS.DomainPolicy: Gen. %d, %d DomainPolicy objects.\n", + sGeneration, sObjects); +} +#endif +PRUint32 DomainPolicy::sGeneration = 0; + // Helper class to get stuff from the ClassInfo and not waste extra time with // virtual method calls for things it has already gotten class ClassInfoData @@ -2953,25 +2964,36 @@ nsScriptSecurityManager::SystemPrincipalSingletonConstructor() nsresult nsScriptSecurityManager::InitPolicies() { - // Reset the "dirty" flag - mPolicyPrefsChanged = PR_FALSE; - // Clear any policies cached on XPConnect wrappers NS_ENSURE_STATE(sXPConnect); nsresult rv = sXPConnect->ClearAllWrappedNativeSecurityPolicies(); if (NS_FAILED(rv)) return rv; - //-- Reset mOriginToPolicyMap + //-- Clear mOriginToPolicyMap: delete mapped DomainEntry items, + //-- whose dtor decrements refcount of stored DomainPolicy object delete mOriginToPolicyMap; + + //-- Marks all the survivor DomainPolicy objects (those cached + //-- by nsPrincipal objects) as invalid: they will be released + //-- on first nsPrincipal::GetSecurityPolicy() attempt. + DomainPolicy::InvalidateAll(); + + //-- Release old default policy + if(mDefaultPolicy) + mDefaultPolicy->Drop(); + + //-- Initialize a new mOriginToPolicyMap mOriginToPolicyMap = new nsObjectHashtable(nsnull, nsnull, DeleteDomainEntry, nsnull); - - //-- Reset and initialize the default policy - delete mDefaultPolicy; - mDefaultPolicy = new DomainPolicy(); - if (!mOriginToPolicyMap || !mDefaultPolicy) + if (!mOriginToPolicyMap) return NS_ERROR_OUT_OF_MEMORY; + //-- Create, refcount and initialize a new default policy + mDefaultPolicy = new DomainPolicy(); + if (!mDefaultPolicy) + return NS_ERROR_OUT_OF_MEMORY; + + mDefaultPolicy->Hold(); if (!mDefaultPolicy->Init()) return NS_ERROR_UNEXPECTED; @@ -3102,6 +3124,9 @@ nsScriptSecurityManager::InitPolicies() return rv; } + // Reset the "dirty" flag + mPolicyPrefsChanged = PR_FALSE; + #ifdef DEBUG_CAPS_HACKER PrintPolicyDB(); #endif