summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCary Clark <cary@android.com>2009-06-03 16:01:34 -0400
committerCary Clark <cary@android.com>2009-06-03 16:51:42 -0400
commitdf1815070cfd8d2ed6f7101d1b8d60d037c839e6 (patch)
tree22220c4d20b523f5900f16b5b5c6614e08fc6d43
parentd15fb80564c4e30b088ca87fa21a03d67675c662 (diff)
downloadexternal_webkit-df1815070cfd8d2ed6f7101d1b8d60d037c839e6.zip
external_webkit-df1815070cfd8d2ed6f7101d1b8d60d037c839e6.tar.gz
external_webkit-df1815070cfd8d2ed6f7101d1b8d60d037c839e6.tar.bz2
browser security patches
Bug 25420: REGRESSION: XMLHttpRequest allows loading from another origin - fix: http://trac.webkit.org/changeset/42983 Bug 24575: Cross-origin XMLHttpRequest is always allowed - fix: http://trac.webkit.org/projects/webkit/changeset/41667 Bug 21456: UXSS after navigation via directly referencing document - fix: http://trac.webkit.org/changeset/42223 Bug 22655: Stack overflow crash in WebCore::RenderBlock::layout() with deeply nested <div>s - fix: http://trac.webkit.org/projects/webkit/changeset/41938
-rw-r--r--WebCore/bindings/js/JSAudioConstructor.cpp6
-rw-r--r--WebCore/bindings/js/JSDOMWindowBase.cpp2
-rw-r--r--WebCore/bindings/js/JSDOMWindowCustom.h6
-rw-r--r--WebCore/bindings/js/JSImageConstructor.cpp3
-rw-r--r--WebCore/bindings/js/JSMessageChannelConstructor.cpp6
-rw-r--r--WebCore/bindings/js/JSXMLHttpRequestConstructor.cpp5
-rw-r--r--WebCore/bindings/js/ScriptController.cpp6
-rw-r--r--WebCore/bindings/js/ScriptController.h2
-rw-r--r--WebCore/html/HTMLParser.cpp21
-rw-r--r--WebCore/html/HTMLParser.h5
-rw-r--r--WebCore/page/DOMWindow.cpp6
-rw-r--r--WebCore/xml/XMLHttpRequest.cpp4
12 files changed, 51 insertions, 21 deletions
diff --git a/WebCore/bindings/js/JSAudioConstructor.cpp b/WebCore/bindings/js/JSAudioConstructor.cpp
index f0bdbe8..1231271 100644
--- a/WebCore/bindings/js/JSAudioConstructor.cpp
+++ b/WebCore/bindings/js/JSAudioConstructor.cpp
@@ -54,7 +54,11 @@ static JSObject* constructAudio(ExecState* exec, JSObject* constructor, const Ar
{
// FIXME: Why doesn't this need the call toJS on the document like JSImageConstructor?
- RefPtr<HTMLAudioElement> audio = new HTMLAudioElement(HTMLNames::audioTag, static_cast<JSAudioConstructor*>(constructor)->document());
+ Document* document = static_cast<JSAudioConstructor*>(constructor)->document();
+ if (!document)
+ return throwError(exec, ReferenceError, "Audio constructor associated document is unavailable");
+
+ RefPtr<HTMLAudioElement> audio = new HTMLAudioElement(HTMLNames::audioTag, document);
if (args.size() > 0) {
audio->setSrc(args.at(exec, 0).toString(exec));
audio->scheduleLoad();
diff --git a/WebCore/bindings/js/JSDOMWindowBase.cpp b/WebCore/bindings/js/JSDOMWindowBase.cpp
index 83bc202..d99abd9 100644
--- a/WebCore/bindings/js/JSDOMWindowBase.cpp
+++ b/WebCore/bindings/js/JSDOMWindowBase.cpp
@@ -157,8 +157,6 @@ void JSDOMWindowBase::updateDocument()
JSDOMWindowBase::~JSDOMWindowBase()
{
- if (d()->impl->frame())
- d()->impl->frame()->script()->clearFormerWindow(asJSDOMWindow(this));
}
ScriptExecutionContext* JSDOMWindowBase::scriptExecutionContext() const
diff --git a/WebCore/bindings/js/JSDOMWindowCustom.h b/WebCore/bindings/js/JSDOMWindowCustom.h
index 838abab..351f2dd 100644
--- a/WebCore/bindings/js/JSDOMWindowCustom.h
+++ b/WebCore/bindings/js/JSDOMWindowCustom.h
@@ -185,12 +185,6 @@ ALWAYS_INLINE bool JSDOMWindowBase::allowsAccessFromPrivate(const JSGlobalObject
if (originWindow == targetWindow)
return true;
- // JS may be attempting to access the "window" object, which should be valid,
- // even if the document hasn't been constructed yet. If the document doesn't
- // exist yet allow JS to access the window object.
- if (!originWindow->impl()->document())
- return true;
-
const SecurityOrigin* originSecurityOrigin = originWindow->impl()->securityOrigin();
const SecurityOrigin* targetSecurityOrigin = targetWindow->impl()->securityOrigin();
diff --git a/WebCore/bindings/js/JSImageConstructor.cpp b/WebCore/bindings/js/JSImageConstructor.cpp
index 0dc55b4..54e8be7 100644
--- a/WebCore/bindings/js/JSImageConstructor.cpp
+++ b/WebCore/bindings/js/JSImageConstructor.cpp
@@ -56,7 +56,8 @@ static JSObject* constructImage(ExecState* exec, JSObject* constructor, const Ar
}
Document* document = static_cast<JSImageConstructor*>(constructor)->document();
-
+ if (!document)
+ return throwError(exec, ReferenceError, "Image constructor associated document is unavailable");
// Calling toJS on the document causes the JS document wrapper to be
// added to the window object. This is done to ensure that JSDocument::mark
// will be called (which will cause the image element to be marked if necessary).
diff --git a/WebCore/bindings/js/JSMessageChannelConstructor.cpp b/WebCore/bindings/js/JSMessageChannelConstructor.cpp
index 8da9f6d..54ffb18 100644
--- a/WebCore/bindings/js/JSMessageChannelConstructor.cpp
+++ b/WebCore/bindings/js/JSMessageChannelConstructor.cpp
@@ -70,7 +70,11 @@ ConstructType JSMessageChannelConstructor::getConstructData(ConstructData& const
JSObject* JSMessageChannelConstructor::construct(ExecState* exec, JSObject* constructor, const ArgList&)
{
- return asObject(toJS(exec, MessageChannel::create(static_cast<JSMessageChannelConstructor*>(constructor)->scriptExecutionContext())));
+ ScriptExecutionContext* context = static_cast<JSMessageChannelConstructor*>(constructor)->scriptExecutionContext();
+ if (!context)
+ return throwError(exec, ReferenceError, "MessageChannel constructor associated document is unavailable");
+
+ return asObject(toJS(exec, MessageChannel::create(context)));
}
void JSMessageChannelConstructor::mark()
diff --git a/WebCore/bindings/js/JSXMLHttpRequestConstructor.cpp b/WebCore/bindings/js/JSXMLHttpRequestConstructor.cpp
index d7f54de..ba9e6ed 100644
--- a/WebCore/bindings/js/JSXMLHttpRequestConstructor.cpp
+++ b/WebCore/bindings/js/JSXMLHttpRequestConstructor.cpp
@@ -43,7 +43,10 @@ JSXMLHttpRequestConstructor::JSXMLHttpRequestConstructor(ExecState* exec, Script
static JSObject* constructXMLHttpRequest(ExecState* exec, JSObject* constructor, const ArgList&)
{
- RefPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(static_cast<JSXMLHttpRequestConstructor*>(constructor)->document());
+ WebCore::Document* doc = static_cast<JSXMLHttpRequestConstructor*>(constructor)->document();
+ if (!doc)
+ return throwError(exec, ReferenceError, "XMLHttpRequest constructor associated document is unavailable");
+ RefPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(doc);
return CREATE_DOM_OBJECT_WRAPPER(exec, XMLHttpRequest, xmlHttpRequest.get());
}
diff --git a/WebCore/bindings/js/ScriptController.cpp b/WebCore/bindings/js/ScriptController.cpp
index efd3a70..11d2945 100644
--- a/WebCore/bindings/js/ScriptController.cpp
+++ b/WebCore/bindings/js/ScriptController.cpp
@@ -133,7 +133,6 @@ void ScriptController::clearWindowShell()
JSLock lock(false);
m_windowShell->window()->clear();
- m_liveFormerWindows.add(m_windowShell->window());
m_windowShell->setWindow(m_frame->domWindow());
if (Page* page = m_frame->page()) {
attachDebugger(page->debugger());
@@ -168,7 +167,7 @@ void ScriptController::initScript()
JSLock lock(false);
m_windowShell = new JSDOMWindowShell(m_frame->domWindow());
- updateDocument();
+ m_windowShell->window()->updateDocument();
if (Page* page = m_frame->page()) {
attachDebugger(page->debugger());
@@ -265,9 +264,6 @@ void ScriptController::updateDocument()
JSLock lock(false);
if (m_windowShell)
m_windowShell->window()->updateDocument();
- HashSet<JSDOMWindow*>::iterator end = m_liveFormerWindows.end();
- for (HashSet<JSDOMWindow*>::iterator it = m_liveFormerWindows.begin(); it != end; ++it)
- (*it)->updateDocument();
}
void ScriptController::updateSecurityOrigin()
diff --git a/WebCore/bindings/js/ScriptController.h b/WebCore/bindings/js/ScriptController.h
index 28fd7e9..2a9ea45 100644
--- a/WebCore/bindings/js/ScriptController.h
+++ b/WebCore/bindings/js/ScriptController.h
@@ -101,7 +101,6 @@ public:
const String* sourceURL() const { return m_sourceURL; } // 0 if we are not evaluating any script
void clearWindowShell();
- void clearFormerWindow(JSDOMWindow* window) { m_liveFormerWindows.remove(window); }
void updateDocument();
// Notifies the ScriptController that the securityOrigin of the current
@@ -146,7 +145,6 @@ private:
bool isJavaScriptAnchorNavigation() const;
JSC::ProtectedPtr<JSDOMWindowShell> m_windowShell;
- HashSet<JSDOMWindow*> m_liveFormerWindows;
Frame* m_frame;
int m_handlerLineno;
const String* m_sourceURL;
diff --git a/WebCore/html/HTMLParser.cpp b/WebCore/html/HTMLParser.cpp
index 0403dad..a719d7d 100644
--- a/WebCore/html/HTMLParser.cpp
+++ b/WebCore/html/HTMLParser.cpp
@@ -61,6 +61,13 @@ using namespace HTMLNames;
static const unsigned cMaxRedundantTagDepth = 20;
static const unsigned cResidualStyleMaxDepth = 200;
+static const int minBlockLevelTagPriority = 3;
+
+// A cap on the number of tags with priority minBlockLevelTagPriority or higher
+// allowed in blockStack. The cap is enforced by adding such new elements as
+// siblings instead of children once it is reached.
+static const size_t cMaxBlockDepth = 4096;
+
struct HTMLStackElem : Noncopyable {
HTMLStackElem(const AtomicString& t, int lvl, Node* n, bool r, HTMLStackElem* nx)
: tagName(t)
@@ -117,6 +124,7 @@ HTMLParser::HTMLParser(HTMLDocument* doc, bool reportErrors)
, current(doc)
, didRefCurrent(false)
, blockStack(0)
+ , m_blocksInStack(0)
, m_hasPElementInScope(NotInScope)
, head(0)
, inBody(false)
@@ -134,6 +142,7 @@ HTMLParser::HTMLParser(DocumentFragment* frag)
, current(frag)
, didRefCurrent(true)
, blockStack(0)
+ , m_blocksInStack(0)
, m_hasPElementInScope(NotInScope)
, head(0)
, inBody(true)
@@ -320,6 +329,11 @@ bool HTMLParser::insertNode(Node* n, bool flat)
if (inStrayTableContent && localName == tableTag)
popBlock(tableTag);
+ if (tagPriority >= minBlockLevelTagPriority) {
+ while (m_blocksInStack >= cMaxBlockDepth)
+ popBlock(blockStack->tagName);
+ }
+
// let's be stupid and just try to insert it.
// this should work if the document is well-formed
Node* newNode = current->addChild(n);
@@ -1306,6 +1320,8 @@ void HTMLParser::reopenResidualStyleTags(HTMLStackElem* elem, Node* malformedTab
void HTMLParser::pushBlock(const AtomicString& tagName, int level)
{
blockStack = new HTMLStackElem(tagName, level, current, didRefCurrent, blockStack);
+ if (level >= minBlockLevelTagPriority)
+ m_blocksInStack++;
didRefCurrent = false;
if (tagName == pTag)
m_hasPElementInScope = InScope;
@@ -1408,6 +1424,10 @@ inline HTMLStackElem* HTMLParser::popOneBlockCommon()
if (current && elem->node != current)
current->finishParsingChildren();
+ if (blockStack->level >= minBlockLevelTagPriority) {
+ ASSERT(m_blocksInStack > 0);
+ m_blocksInStack--;
+ }
blockStack = elem->next;
current = elem->node;
didRefCurrent = elem->didRefNode;
@@ -1482,6 +1502,7 @@ void HTMLParser::freeBlock()
{
while (blockStack)
popOneBlock();
+ ASSERT(!m_blocksInStack);
}
void HTMLParser::createHead()
diff --git a/WebCore/html/HTMLParser.h b/WebCore/html/HTMLParser.h
index 866835f..251b323 100644
--- a/WebCore/html/HTMLParser.h
+++ b/WebCore/html/HTMLParser.h
@@ -159,6 +159,11 @@ private:
HTMLStackElem* blockStack;
+ // The number of tags with priority minBlockLevelTagPriority or higher
+ // currently in m_blockStack. The parser enforces a cap on this value by
+ // adding such new elements as siblings instead of children once it is reached.
+ size_t m_blocksInStack;
+
enum ElementInScopeState { NotInScope, InScope, Unknown };
ElementInScopeState m_hasPElementInScope;
diff --git a/WebCore/page/DOMWindow.cpp b/WebCore/page/DOMWindow.cpp
index 70ee79e..f28e356 100644
--- a/WebCore/page/DOMWindow.cpp
+++ b/WebCore/page/DOMWindow.cpp
@@ -764,9 +764,15 @@ DOMWindow* DOMWindow::top() const
Document* DOMWindow::document() const
{
+ // FIXME: This function shouldn't need a frame to work.
if (!m_frame)
return 0;
+ // The m_frame pointer is not zeroed out when the window is put into b/f cache, so it can hold an unrelated document/window pair.
+ // FIXME: We should always zero out the frame pointer on navigation to avoid accidentally accessing the new frame content.
+ if (m_frame->domWindow() != this)
+ return 0;
+
ASSERT(m_frame->document());
return m_frame->document();
}
diff --git a/WebCore/xml/XMLHttpRequest.cpp b/WebCore/xml/XMLHttpRequest.cpp
index f16755a..b62679b 100644
--- a/WebCore/xml/XMLHttpRequest.cpp
+++ b/WebCore/xml/XMLHttpRequest.cpp
@@ -934,6 +934,7 @@ void XMLHttpRequest::networkError()
if (m_upload)
m_upload->dispatchErrorEvent();
}
+ internalAbort();
}
void XMLHttpRequest::abortError()
@@ -1159,7 +1160,6 @@ void XMLHttpRequest::didFail()
if (m_error)
return;
- internalAbort();
networkError();
}
@@ -1294,7 +1294,7 @@ void XMLHttpRequest::didReceiveAuthenticationCancellation(const ResourceResponse
void XMLHttpRequest::didReceiveData(const char* data, int len)
{
- if (m_inPreflight)
+ if (m_inPreflight || m_error)
return;
if (m_state < HEADERS_RECEIVED)