зеркало из https://github.com/mozilla/pjs.git
Bug 193011: frame recursion limits re-added/docshell limit removed (backout
of bug 98158 and follow-on patches). Also re-fixes bug 98158. r=darin, sr=dbaron
This commit is contained in:
Родитель
ca9574bfda
Коммит
dcdf4824bb
|
@ -60,14 +60,28 @@
|
|||
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
|
||||
#include "nsIURI.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
#include "nsHTMLAtoms.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
|
||||
// Bug 98158: Limit to the number of total docShells in one page.
|
||||
#define MAX_NUMBER_DOCSHELLS 100
|
||||
// Bug 136580: Limit to the number of nested content frames that can have the
|
||||
// same URL. This is to stop content that is recursively loading
|
||||
// itself. Note that "#foo" on the end of URL doesn't affect
|
||||
// whether it's considered identical, but "?foo" or ";foo" are
|
||||
// considered and compared.
|
||||
#define MAX_SAME_URL_CONTENT_FRAMES 3
|
||||
|
||||
// Bug 8065: Limit content frame depth to some reasonable level. This
|
||||
// does not count chrome frames when determining depth, nor does it
|
||||
// prevent chrome recursion. Number is fairly arbitrary, but meant to
|
||||
// keep number of shells to a reasonable number on accidental recursion with a
|
||||
// small (but not 1) branching factor. With large branching factors the number
|
||||
// of shells can rapidly become huge and run us out of memory. To solve that,
|
||||
// we'd need to re-institute a fixed version of bug 98158.
|
||||
#define MAX_DEPTH_CONTENT_FRAMES 10
|
||||
|
||||
|
||||
class nsFrameLoader : public nsIFrameLoader
|
||||
{
|
||||
|
@ -84,8 +98,6 @@ public:
|
|||
NS_IMETHOD GetDocShell(nsIDocShell **aDocShell);
|
||||
NS_IMETHOD Destroy();
|
||||
|
||||
PRInt32 GetDocShellChildCount(nsIDocShellTreeNode *aParentNode);
|
||||
|
||||
protected:
|
||||
nsresult GetPresContext(nsIPresContext **aPresContext);
|
||||
nsresult EnsureDocShell();
|
||||
|
@ -215,6 +227,98 @@ nsFrameLoader::LoadFrame()
|
|||
return rv; // We're not
|
||||
}
|
||||
|
||||
|
||||
// Bug 136580: Check for recursive frame loading
|
||||
// pre-grab these for speed
|
||||
nsCAutoString prepath;
|
||||
nsCAutoString filepath;
|
||||
nsCAutoString query;
|
||||
nsCAutoString param;
|
||||
rv = uri->GetPrePath(prepath);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
nsCOMPtr<nsIURL> aURL(do_QueryInterface(uri, &rv)); // QI can fail
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = aURL->GetFilePath(filepath);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
rv = aURL->GetQuery(query);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
rv = aURL->GetParam(param);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
} else {
|
||||
// Not a URL, so punt and just take the whole path. Note that if you
|
||||
// have a self-referential-via-refs non-URL (can't happen via nsSimpleURI,
|
||||
// but could in theory with an external protocol handler) frameset it will
|
||||
// recurse down to the depth limit before stopping, but it will stop.
|
||||
rv = uri->GetPath(filepath);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
}
|
||||
|
||||
PRInt32 matchCount = 0;
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(mDocShell);
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
|
||||
treeItem->GetParent(getter_AddRefs(parentAsItem));
|
||||
while (parentAsItem) {
|
||||
// Only interested in checking for recursion in content
|
||||
PRInt32 parentType;
|
||||
parentAsItem->GetItemType(&parentType);
|
||||
if (parentType != nsIDocShellTreeItem::typeContent) {
|
||||
break; // Not content
|
||||
}
|
||||
// Check the parent URI with the URI we're loading
|
||||
nsCOMPtr<nsIWebNavigation> parentAsNav(do_QueryInterface(parentAsItem));
|
||||
if (parentAsNav) {
|
||||
// Does the URI match the one we're about to load?
|
||||
nsCOMPtr<nsIURI> parentURI;
|
||||
parentAsNav->GetCurrentURI(getter_AddRefs(parentURI));
|
||||
if (parentURI) {
|
||||
// Bug 98158/193011: We need to ignore data after the #
|
||||
// Note that this code is back-stopped by the maximum-depth checks.
|
||||
|
||||
// Check prepath (foo://blah@bar:port/) and filepath
|
||||
// (/dir/dir/file.ext), but not # extensions.
|
||||
// There's no easy way to get the URI without extension
|
||||
// directly, so check prepath, filepath and query/param (if any)
|
||||
|
||||
// Note that while in theory a CGI could return different data for
|
||||
// the same query string, the spec states that it shouldn't, so
|
||||
// we'll compare queries (and params).
|
||||
nsCAutoString parentPrePath;
|
||||
nsCAutoString parentFilePath;
|
||||
nsCAutoString parentQuery;
|
||||
nsCAutoString parentParam;
|
||||
rv = parentURI->GetPrePath(parentPrePath);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
nsCOMPtr<nsIURL> parentURL(do_QueryInterface(parentURI, &rv)); // QI can fail
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = parentURL->GetFilePath(parentFilePath);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
rv = parentURL->GetQuery(parentQuery);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
rv = parentURL->GetParam(parentParam);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
} else {
|
||||
rv = uri->GetPath(filepath);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
}
|
||||
|
||||
// filepath will often not match; test it first
|
||||
if (filepath.Equals(parentFilePath) &&
|
||||
query.Equals(parentQuery) &&
|
||||
prepath.Equals(parentPrePath) &&
|
||||
param.Equals(parentParam))
|
||||
{
|
||||
matchCount++;
|
||||
if (matchCount >= MAX_SAME_URL_CONTENT_FRAMES) {
|
||||
NS_WARNING("Too many nested content frames have the same url (recursion?) so giving up");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nsIDocShellTreeItem* temp = parentAsItem;
|
||||
temp->GetParent(getter_AddRefs(parentAsItem));
|
||||
}
|
||||
|
||||
// Kick off the load...
|
||||
rv = mDocShell->LoadURI(uri, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE,
|
||||
PR_FALSE);
|
||||
|
@ -266,28 +370,6 @@ nsFrameLoader::Destroy()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the total number of docshell children in each page.
|
||||
*/
|
||||
PRInt32
|
||||
nsFrameLoader::GetDocShellChildCount(nsIDocShellTreeNode* aParentNode)
|
||||
{
|
||||
PRInt32 retval = 1;
|
||||
|
||||
PRInt32 childCount;
|
||||
PRInt32 i;
|
||||
aParentNode->GetChildCount(&childCount);
|
||||
for(i=0;i<childCount;i++)
|
||||
{
|
||||
nsCOMPtr<nsIDocShellTreeItem> child;
|
||||
aParentNode->GetChildAt(i,getter_AddRefs(child));
|
||||
nsCOMPtr<nsIDocShellTreeNode> childAsNode(do_QueryInterface(child));
|
||||
retval += GetDocShellChildCount(childAsNode);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFrameLoader::GetPresContext(nsIPresContext **aPresContext)
|
||||
{
|
||||
|
@ -325,26 +407,36 @@ nsFrameLoader::EnsureDocShell()
|
|||
GetPresContext(getter_AddRefs(presContext));
|
||||
NS_ENSURE_TRUE(presContext, NS_ERROR_UNEXPECTED);
|
||||
|
||||
// Bug 8065: Don't exceed some maximum depth in content frames
|
||||
// (MAX_DEPTH_CONTENT_FRAMES)
|
||||
PRInt32 depth = 0;
|
||||
nsCOMPtr<nsISupports> parentAsSupports;
|
||||
presContext->GetContainer(getter_AddRefs(parentAsSupports));
|
||||
|
||||
// bug98158:count the children under the root docshell.
|
||||
// if the total number of children under the root docshell
|
||||
// beyond the limit,return a error.
|
||||
if (parentAsSupports) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentAsItem = do_QueryInterface(parentAsSupports);
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentAsItem =
|
||||
do_QueryInterface(parentAsSupports);
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> root;
|
||||
parentAsItem->GetSameTypeRootTreeItem(getter_AddRefs(root));
|
||||
while (parentAsItem) {
|
||||
++depth;
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeNode> rootNode(do_QueryInterface(root));
|
||||
if (depth >= MAX_DEPTH_CONTENT_FRAMES) {
|
||||
NS_WARNING("Too many nested content frames so giving up");
|
||||
|
||||
PRInt32 childrenCount;
|
||||
childrenCount = GetDocShellChildCount(rootNode);
|
||||
return NS_ERROR_UNEXPECTED; // Too deep, give up! (silently?)
|
||||
}
|
||||
|
||||
if(childrenCount >= MAX_NUMBER_DOCSHELLS) {
|
||||
NS_WARNING("Too many docshell (recursion?) so giving up");
|
||||
return NS_ERROR_FAILURE;
|
||||
// Only count depth on content, not chrome.
|
||||
// If we wanted to limit total depth, skip the following check:
|
||||
PRInt32 parentType;
|
||||
parentAsItem->GetItemType(&parentType);
|
||||
|
||||
if (nsIDocShellTreeItem::typeContent == parentType) {
|
||||
nsIDocShellTreeItem* temp = parentAsItem;
|
||||
temp->GetParent(getter_AddRefs(parentAsItem));
|
||||
} else {
|
||||
break; // we have exited content, stop counting, depth is OK!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче