XBL needs simple defense against infinite recursion. b=55070 r+sr=bzbarsky

This commit is contained in:
mats.palmgren%bredband.net 2006-11-09 01:58:12 +00:00
Родитель d660796ee2
Коммит ec8d1d8cb7
3 изменённых файлов: 70 добавлений и 9 удалений

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

@ -23,6 +23,7 @@
* Original Author: David W. Hyatt (hyatt@netscape.com) * Original Author: David W. Hyatt (hyatt@netscape.com)
* - Brendan Eich (brendan@mozilla.org) * - Brendan Eich (brendan@mozilla.org)
* - Mike Pinkerton (pinkerton@netscape.com) * - Mike Pinkerton (pinkerton@netscape.com)
* Mats Palmgren <mats.palmgren@bredband.net>
* *
* Alternatively, the contents of this file may be used under the terms of * Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"), * either of the GNU General Public License Version 2 or later (the "GPL"),
@ -121,7 +122,8 @@ IsAncestorBinding(nsIDocument* aDocument,
nsresult rv = nsresult rv =
binding->PrototypeBinding()->BindingURI()->Equals(aChildBindingURI, binding->PrototypeBinding()->BindingURI()->Equals(aChildBindingURI,
&equal); &equal);
if (NS_FAILED(rv) || equal) { NS_ENSURE_SUCCESS(rv, PR_TRUE); // assume the worst
if (equal) {
nsCAutoString spec; nsCAutoString spec;
aChildBindingURI->GetSpec(spec); aChildBindingURI->GetSpec(spec);
NS_ConvertUTF8toUTF16 bindingURI(spec); NS_ConvertUTF8toUTF16 bindingURI(spec);
@ -838,6 +840,17 @@ nsresult
nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI, nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
PRBool aPeekOnly, PRBool* aIsReady, PRBool aPeekOnly, PRBool* aIsReady,
nsXBLBinding** aResult) nsXBLBinding** aResult)
{
// More than 6 binding URIs are rare, see bug 55070 comment 18.
nsTArray<nsIURI*> uris(6);
return GetBinding(aBoundElement, aURI, aPeekOnly, aIsReady, aResult, uris);
}
nsresult
nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
PRBool aPeekOnly, PRBool* aIsReady,
nsXBLBinding** aResult,
nsTArray<nsIURI*>& aDontExtendURIs)
{ {
NS_ASSERTION(aPeekOnly || aResult, NS_ASSERTION(aPeekOnly || aResult,
"Must have non-null out param if not just peeking to see " "Must have non-null out param if not just peeking to see "
@ -849,6 +862,8 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
if (!aURI) if (!aURI)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
NS_ENSURE_TRUE(aDontExtendURIs.AppendElement(aURI), NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsIURL> url(do_QueryInterface(aURI)); nsCOMPtr<nsIURL> url(do_QueryInterface(aURI));
if (!url) { if (!url) {
#ifdef DEBUG #ifdef DEBUG
@ -903,9 +918,11 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
PRBool hasBase = protoBinding->HasBasePrototype(); PRBool hasBase = protoBinding->HasBasePrototype();
nsXBLPrototypeBinding* baseProto = protoBinding->GetBasePrototype(); nsXBLPrototypeBinding* baseProto = protoBinding->GetBasePrototype();
if (baseProto) { if (baseProto) {
if (NS_FAILED(GetBinding(aBoundElement, baseProto->BindingURI(), nsresult rv = GetBinding(aBoundElement, baseProto->BindingURI(), aPeekOnly,
aPeekOnly, aIsReady, getter_AddRefs(baseBinding)))) aIsReady, getter_AddRefs(baseBinding),
return NS_ERROR_FAILURE; // We aren't ready yet. aDontExtendURIs);
if (NS_FAILED(rv))
return rv; // We aren't ready yet.
} }
else if (hasBase) { else if (hasBase) {
// Check for the presence of 'extends' and 'display' attributes // Check for the presence of 'extends' and 'display' attributes
@ -976,9 +993,31 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
doc->GetBaseURI()); doc->GetBaseURI());
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (NS_FAILED(GetBinding(aBoundElement, bindingURI, aPeekOnly, PRUint32 count = aDontExtendURIs.Length();
aIsReady, getter_AddRefs(baseBinding)))) for (PRUint32 index = 0; index < count; ++index) {
return NS_ERROR_FAILURE; // Binding not yet ready or an error occurred. PRBool equal;
rv = aDontExtendURIs[index]->Equals(bindingURI, &equal);
NS_ENSURE_SUCCESS(rv, rv);
if (equal) {
nsCAutoString spec;
protoBinding->BindingURI()->GetSpec(spec);
NS_ConvertUTF8toUTF16 protoSpec(spec);
const PRUnichar* params[] = { protoSpec.get(), value.get() };
nsContentUtils::ReportToConsole(nsContentUtils::eXBL_PROPERTIES,
"CircularExtendsBinding",
params, NS_ARRAY_LENGTH(params),
boundDocument->GetDocumentURI(),
EmptyString(), 0, 0,
nsIScriptError::warningFlag,
"XBL");
return NS_ERROR_ILLEGAL_VALUE;
}
}
rv = GetBinding(aBoundElement, bindingURI, aPeekOnly, aIsReady,
getter_AddRefs(baseBinding), aDontExtendURIs);
if (NS_FAILED(rv))
return rv; // Binding not yet ready or an error occurred.
if (!aPeekOnly) { if (!aPeekOnly) {
// Make sure to set the base prototype. // Make sure to set the base prototype.
baseProto = baseBinding->PrototypeBinding(); baseProto = baseBinding->PrototypeBinding();

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

@ -46,6 +46,7 @@
#include "jsapi.h" // nsXBLJSClass derives from JSClass #include "jsapi.h" // nsXBLJSClass derives from JSClass
#include "jsclist.h" // nsXBLJSClass derives from JSCList #include "jsclist.h" // nsXBLJSClass derives from JSCList
#include "nsFixedSizeAllocator.h" #include "nsFixedSizeAllocator.h"
#include "nsTArray.h"
class nsXBLBinding; class nsXBLBinding;
class nsIXBLDocumentInfo; class nsIXBLDocumentInfo;
@ -104,12 +105,32 @@ protected:
nsresult GetXBLDocumentInfo(nsIURI* aURI, nsIContent* aBoundElement, nsIXBLDocumentInfo** aResult); nsresult GetXBLDocumentInfo(nsIURI* aURI, nsIContent* aBoundElement, nsIXBLDocumentInfo** aResult);
// This method loads a binding doc and then builds the specific binding required. It /**
// can also peek without building. * This method calls the one below with an empty |aDontExtendURIs| array.
*/
nsresult GetBinding(nsIContent* aBoundElement, nsIURI* aURI, nsresult GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
PRBool aPeekFlag, PRBool* aIsReady, PRBool aPeekFlag, PRBool* aIsReady,
nsXBLBinding** aResult); nsXBLBinding** aResult);
/**
* This method loads a binding doc and then builds the specific binding
* required. It can also peek without building.
* @param aBoundElement the element to get a binding for
* @param aURI the binding URI
* @param aPeekFlag if true then just peek to see if the binding is ready
* @param aIsReady [out] if the binding is ready or not
* @param aResult [out] where to store the resulting binding (not used if
* aPeekFlag is true, otherwise it must be non-null)
* @param aDontExtendURIs a set of URIs that are already bound to this
* element. If a binding extends any of these then further loading
* is aborted (because it would lead to the binding extending itself)
* and NS_ERROR_ILLEGAL_VALUE is returned.
*/
nsresult GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
PRBool aPeekFlag, PRBool* aIsReady,
nsXBLBinding** aResult,
nsTArray<nsIURI*>& aDontExtendURIs);
// MEMBER VARIABLES // MEMBER VARIABLES
public: public:
#ifdef MOZ_XUL #ifdef MOZ_XUL

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

@ -38,3 +38,4 @@ UnexpectedElement=Unexpected <%1$S> element.
GTK2Conflict=Key event not available on GTK2: key="%S" modifiers="%S" GTK2Conflict=Key event not available on GTK2: key="%S" modifiers="%S"
WinConflict=Key event not available on some keyboard layouts: key="%S" modifiers="%S" WinConflict=Key event not available on some keyboard layouts: key="%S" modifiers="%S"
RecursiveBinding=The XBL binding "%S" is already used by an ancestor element RecursiveBinding=The XBL binding "%S" is already used by an ancestor element
CircularExtendsBinding=Extending the XBL binding "%S" with "%S" would lead to it extending itself