Fake pushback of invalid eCSSToken_URL results from NextURL. (Bug 541434) r=bzbarsky
authorL. David Baron <dbaron@dbaron.org>
Sun, 24 Jan 2010 12:06:19 -0800
changeset 37458 0ff87d9d2d73f319dd7a1f2b5f7106ccd2852a97
parent 37457 2c1b2b5f4d50bcfd7a50693019503d4666aa6f98
child 37459 dbb25266f4fa642ac1eacdd90d16afad1af0a6e4
push idunknown
push userunknown
push dateunknown
reviewersbzbarsky
bugs541434
milestone1.9.3a1pre
Fake pushback of invalid eCSSToken_URL results from NextURL. (Bug 541434) r=bzbarsky
layout/reftests/css-parsing/invalid-url-handling-partial.xhtml
layout/reftests/css-parsing/reftest.list
layout/style/nsCSSParser.cpp
deleted file mode 100644
--- a/layout/reftests/css-parsing/invalid-url-handling-partial.xhtml
+++ /dev/null
@@ -1,102 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
-  <title>CSS Test: handling of invalid url() functions</title>
-  <link rel="author" title="L. David Baron" href="http://dbaron.org/" />
-  <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
-  <link rel="help" href="http://www.w3.org/TR/CSS21/syndata.html#tokenization" />
-  <link rel="help" href="http://www.w3.org/TR/CSS21/syndata.html#parsing-errors" />
-  <meta name="flags" content="invalid" />
-  <style type="text/css">
-  div { background-color: red }
-  </style>
-  <style type="text/css">
-  /* not a URI token, but handled according to rules for parsing errors */
-  #one { background: url(foo"bar") }
-  #one { background-color: green; }
-  </style>
-  <style type="text/css">
-  /* not a URI token, but handled according to rules for parsing errors */
-  #foo { background: url(foo"bar
-  ) }
-  #two { background-color: green; }
-  </style>
-  <style type="text/css">
-  /* not a URI token; the unterminated string ends at end of line, so
-     the brace never matches */
-  #three { background-color: green; }
-  #foo { background: url(foo"bar) }
-  #three { background-color: red; }
-  </style>
-  <style type="text/css">
-  /* not a URI token; the unterminated string ends at end of line */
-  #foo { background: url(foo"bar) }
-  ) }
-  #four { background-color: green; }
-  </style>
-  <style type="text/css">
-  /* not a URI token; the unterminated string ends at end of line, so
-     the brace never matches */
-  #five { background-color: green; }
-  #foo { background: url("bar) }
-  #five { background-color: red; }
-  </style>
-  <style type="text/css">
-  /* not a URI token; the unterminated string ends at end of line */
-  #foo { background: url("bar) }
-  ) }
-  #six { background-color: green; }
-  </style>
-  <style type="text/css">
-  /* not a URI token, but brace matching should work */
-  #seven { background: url(()); background-color: green; }
-  </style>
-  <style type="text/css">
-  /* not a URI token, but brace matching should work */
-  #eight { background: url([{}]); background-color: green; }
-  </style>
-  <style type="text/css">
-  /* not a URI token, but brace matching should work */
-  #nine { background: url([)]); background-color: green; }
-  </style>
-  <style type="text/css">
-  /* perfectly good URI token (image is a 404, though) */
-  #ten { background: url({) green; }
-  </style>
-  <style type="text/css">
-  /* perfectly good URI token (image is a 404, though) */
-  #eleven { background: url([) green; }
-  </style>
-  <style type="text/css">
-  /* not a URI token, but brace matching should work */
-  /* COMMENT OUT THIS TEST IN THE PARTIAL VERSION SINCE IT FAILS */
-  #twelve { /* background: url({"")}); */ background-color: green; }
-  </style>
-  <style type="text/css">
-  /* not a URI token, but brace matching should work */
-  #thirteen { background: url(["")]); background-color: green; }
-  </style>
-  <style type="text/css">
-  /* not a URI token; the opening ( is never matched */
-  #fourteen { background-color: green; }
-  #foo { background: url(() }
-  #fourteen { background-color: red; }
-  </style>
- </head>
- <body>
-  <div id="one">This should have a green background</div>
-  <div id="two">This should have a green background</div>
-  <div id="three">This should have a green background</div>
-  <div id="four">This should have a green background</div>
-  <div id="five">This should have a green background</div>
-  <div id="six">This should have a green background</div>
-  <div id="seven">This should have a green background</div>
-  <div id="eight">This should have a green background</div>
-  <div id="nine">This should have a green background</div>
-  <div id="ten">This should have a green background</div>
-  <div id="eleven">This should have a green background</div>
-  <div id="twelve">This should have a green background</div>
-  <div id="thirteen">This should have a green background</div>
-  <div id="fourteen">This should have a green background</div>
- </body>
-</html>
--- a/layout/reftests/css-parsing/reftest.list
+++ b/layout/reftests/css-parsing/reftest.list
@@ -1,2 +1,1 @@
-fails == invalid-url-handling.xhtml invalid-url-handling-ref.xhtml # Bug 541434
-== invalid-url-handling-partial.xhtml invalid-url-handling-ref.xhtml
+== invalid-url-handling.xhtml invalid-url-handling-ref.xhtml
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -283,16 +283,17 @@ protected:
     NS_PRECONDITION(!mParsingCompoundProperty, "Bad initial state");
   }
 
   PRBool ExpectSymbol(PRUnichar aSymbol, PRBool aSkipWS);
   PRBool ExpectEndProperty();
   PRBool CheckEndProperty();
   nsSubstring* NextIdent();
   void SkipUntil(PRUnichar aStopSymbol);
+  void SkipUntilStack(nsAutoTArray<PRUnichar, 16> &aStack);
   void SkipUntilOneOf(const PRUnichar* aStopSymbolChars);
   void SkipRuleSet(PRBool aInsideBraces);
   PRBool SkipAtRule();
   PRBool SkipDeclaration(PRBool aCheckForBraces);
   PRBool GetNonCloseParenToken(PRBool aSkipWS);
 
   PRBool PushGroup(nsICSSGroupRule* aRule);
   void PopGroup(void);
@@ -1329,20 +1330,35 @@ CSSParserImpl::GetURLInParens(nsString& 
 
   aURL = mToken.mIdent;
 
   if ((eCSSToken_String != mToken.mType && eCSSToken_URL != mToken.mType) ||
       !ExpectSymbol(')', PR_TRUE)) {
     // in the failure case, we have to match parentheses, as if this
     // weren't treated as a URL token by the tokenization
 
-    // XXX We really need to push aURL back into the buffer before this
-    // SkipUntil, but we won't do it as it will make no difference anyway,
-    // and it will make parsing slower.
-    SkipUntil(')');
+    nsAutoTArray<PRUnichar, 16> stack;
+    stack.AppendElement(')');
+    if (eCSSToken_URL == mToken.mType || eCSSToken_InvalidURL == mToken.mType) {
+      for (PRUint32 i = 0, iEnd = mToken.mIdent.Length(); i < iEnd; ++i) {
+        PRUnichar symbol = mToken.mIdent[i];
+        NS_ASSERTION(symbol != '(' && symbol != ')',
+                     "should not be in eCSSToken_URL");
+        if ('[' == symbol) {
+          stack.AppendElement(']');
+        } else if ('{' == symbol) {
+          stack.AppendElement('}');
+        } else if ((']' == symbol && stack[stack.Length() - 1] == '[') ||
+                   ('}' == symbol && stack[stack.Length() - 1] == '{')) {
+          stack.RemoveElementAt(stack.Length() - 1);
+        }
+      }
+    }
+    SkipUntilStack(stack);
+
     return PR_FALSE;
   }
 
   return PR_TRUE;
 }
 
 void
 CSSParserImpl::UngetToken()
@@ -2219,40 +2235,46 @@ CSSParserImpl::ParsePageRule(RuleAppendF
 {
   // XXX not yet implemented
   return PR_FALSE;
 }
 
 void
 CSSParserImpl::SkipUntil(PRUnichar aStopSymbol)
 {
-  nsCSSToken* tk = &mToken;
   nsAutoTArray<PRUnichar, 16> stack;
   stack.AppendElement(aStopSymbol);
+  SkipUntilStack(stack);
+}
+
+void
+CSSParserImpl::SkipUntilStack(nsAutoTArray<PRUnichar, 16>& aStack)
+{
+  nsCSSToken* tk = &mToken;
   for (;;) {
     if (!GetToken(PR_TRUE)) {
       break;
     }
     if (eCSSToken_Symbol == tk->mType) {
       PRUnichar symbol = tk->mSymbol;
-      PRUint32 stackTopIndex = stack.Length() - 1;
-      if (symbol == stack.ElementAt(stackTopIndex)) {
-        stack.RemoveElementAt(stackTopIndex);
+      PRUint32 stackTopIndex = aStack.Length() - 1;
+      if (symbol == aStack.ElementAt(stackTopIndex)) {
+        aStack.RemoveElementAt(stackTopIndex);
         if (stackTopIndex == 0) {
           break;
         }
       } else if ('{' == symbol) {
         // In this case and the two below, just handle out-of-memory by
         // parsing incorrectly.  It's highly unlikely we're dealing with
         // a legitimate style sheet anyway.
-        stack.AppendElement('}');
+        aStack.AppendElement('}');
       } else if ('[' == symbol) {
-        stack.AppendElement(']');
+        aStack.AppendElement(']');
       } else if ('(' == symbol) {
-        stack.AppendElement(')');
+        aStack.AppendElement(')');
       }
     }
   }
 }
 
 void
 CSSParserImpl::SkipUntilOneOf(const PRUnichar* aStopSymbolChars)
 {