fix bug 100773. This protects agains infinite recursion that could occur thorugh xpconnect in QI calls on elements with multiple bindings. sr=hyatt r=brendan.

This commit is contained in:
jband%netscape.com 2001-09-22 00:24:24 +00:00
Родитель ec011be750
Коммит 247367757a
1 изменённых файлов: 45 добавлений и 0 удалений

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

@ -1393,6 +1393,18 @@ nsBindingManager::FlushChromeBindings()
return NS_OK;
}
// Used below to protect from recurring in QI calls through XPConnect.
struct AntiRecursionData {
nsIContent* element;
REFNSIID iid;
AntiRecursionData* next;
AntiRecursionData(nsIContent* aElement,
REFNSIID aIID,
AntiRecursionData* aNext)
: element(aElement), iid(aIID), next(aNext) {}
};
NS_IMETHODIMP
nsBindingManager::GetBindingImplementation(nsIContent* aContent, REFNSIID aIID,
void** aResult)
@ -1408,7 +1420,40 @@ nsBindingManager::GetBindingImplementation(nsIContent* aContent, REFNSIID aIID,
GetWrappedJS(aContent, getter_AddRefs(wrappedJS));
if (wrappedJS) {
// Protect from recurring in QI calls through XPConnect.
// This can happen when a second binding is being resolved.
// At that point a wrappedJS exists, but it doesn't yet know about
// the iid we are asking for. So, without this protection,
// AggregatedQueryInterface would end up recurring back into itself
// through this code.
//
// With this protection, when we detect the recursion we return
// NS_NOINTERFACE in the inner call. The outer call will then fall
// through (see below) and build a new chained wrappedJS for the iid.
//
// We're careful to not assume that only one direct nesting can occur
// because there is a call into JS in the middle and we can't assume
// that this code won't be reached by some more complex nesting path.
//
// NOTE: We *assume* this is single threaded, so we can use a
// static linked list to do the check.
static AntiRecursionData* list = nsnull;
for (AntiRecursionData* p = list; p; p = p->next) {
if (p->element == aContent && p->iid.Equals(aIID)) {
*aResult = nsnull;
return NS_NOINTERFACE;
}
}
AntiRecursionData item(aContent, aIID, list);
list = &item;
nsresult rv = wrappedJS->AggregatedQueryInterface(aIID, aResult);
list = item.next;
if (*aResult)
return rv;