Fix places where we should skip to a closing parenthesis during errors parsing functions. (Bug 575672) r=bzbarsky a2.0=blocking2.0+
authorL. David Baron <dbaron@dbaron.org>
Wed, 11 Aug 2010 12:32:52 -0700
changeset 49560 4c518456865ab48157ea782678eec457391e084d
parent 49559 638dab2836b540fae2bd1530d220a847e8db9f20
child 49561 17316f38926ee0c1667b54a2238e5083aa4c6ce4
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs575672
milestone2.0b4pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Fix places where we should skip to a closing parenthesis during errors parsing functions. (Bug 575672) r=bzbarsky a2.0=blocking2.0+
layout/style/nsCSSParser.cpp
layout/style/test/Makefile.in
layout/style/test/property_database.js
layout/style/test/test_unclosed_parentheses.html
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -1304,16 +1304,17 @@ CSSParserImpl::GetToken(PRBool aSkipWS)
 }
 
 PRBool
 CSSParserImpl::GetURLInParens(nsString& aURL)
 {
   NS_ASSERTION(!mHavePushBack, "mustn't have pushback at this point");
   do {
     if (! mScanner.NextURL(mToken)) {
+      // EOF
       return PR_FALSE;
     }
   } while (eCSSToken_WhiteSpace == mToken.mType);
 
   aURL = mToken.mIdent;
 
   if ((eCSSToken_String != mToken.mType && eCSSToken_URL != mToken.mType) ||
       !ExpectSymbol(')', PR_TRUE)) {
@@ -3610,53 +3611,57 @@ CSSParserImpl::ParseColor(nsCSSValue& aV
         PRUint8 r, g, b;
         PRInt32 type = COLOR_TYPE_UNKNOWN;
         if (ParseColorComponent(r, type, ',') &&
             ParseColorComponent(g, type, ',') &&
             ParseColorComponent(b, type, ')')) {
           aValue.SetColorValue(NS_RGB(r,g,b));
           return PR_TRUE;
         }
-        return PR_FALSE;  // already pushed back
+        SkipUntil(')');
+        return PR_FALSE;
       }
       else if (mToken.mIdent.LowerCaseEqualsLiteral("-moz-rgba") ||
                mToken.mIdent.LowerCaseEqualsLiteral("rgba")) {
         // rgba ( component , component , component , opacity )
         PRUint8 r, g, b, a;
         PRInt32 type = COLOR_TYPE_UNKNOWN;
         if (ParseColorComponent(r, type, ',') &&
             ParseColorComponent(g, type, ',') &&
             ParseColorComponent(b, type, ',') &&
             ParseColorOpacity(a)) {
           aValue.SetColorValue(NS_RGBA(r, g, b, a));
           return PR_TRUE;
         }
-        return PR_FALSE;  // already pushed back
+        SkipUntil(')');
+        return PR_FALSE;
       }
       else if (mToken.mIdent.LowerCaseEqualsLiteral("hsl")) {
         // hsl ( hue , saturation , lightness )
         // "hue" is a number, "saturation" and "lightness" are percentages.
         if (ParseHSLColor(rgba, ')')) {
           aValue.SetColorValue(rgba);
           return PR_TRUE;
         }
+        SkipUntil(')');
         return PR_FALSE;
       }
       else if (mToken.mIdent.LowerCaseEqualsLiteral("-moz-hsla") ||
                mToken.mIdent.LowerCaseEqualsLiteral("hsla")) {
         // hsla ( hue , saturation , lightness , opacity )
         // "hue" is a number, "saturation" and "lightness" are percentages,
         // "opacity" is a number.
         PRUint8 a;
         if (ParseHSLColor(rgba, ',') &&
             ParseColorOpacity(a)) {
           aValue.SetColorValue(NS_RGBA(NS_GET_R(rgba), NS_GET_G(rgba),
                                        NS_GET_B(rgba), a));
           return PR_TRUE;
         }
+        SkipUntil(')');
         return PR_FALSE;
       }
       break;
     default:
       break;
   }
 
   // try 'xxyyzz' without '#' prefix for compatibility with IE and Nav4x (bug 23236 and 45804)
@@ -4469,22 +4474,30 @@ CSSParserImpl::ParseVariant(nsCSSValue& 
       (eCSSToken_Function == tk->mType) &&
       (tk->mIdent.LowerCaseEqualsLiteral("counter") ||
        tk->mIdent.LowerCaseEqualsLiteral("counters"))) {
     return ParseCounter(aValue);
   }
   if (((aVariantMask & VARIANT_ATTR) != 0) &&
       (eCSSToken_Function == tk->mType) &&
       tk->mIdent.LowerCaseEqualsLiteral("attr")) {
-    return ParseAttr(aValue);
+    if (!ParseAttr(aValue)) {
+      SkipUntil(')');
+      return PR_FALSE;
+    }
+    return PR_TRUE;
   }
   if (((aVariantMask & VARIANT_CUBIC_BEZIER) != 0) &&
       (eCSSToken_Function == tk->mType)) {
      if (tk->mIdent.LowerCaseEqualsLiteral("cubic-bezier")) {
-      return ParseTransitionTimingFunctionValues(aValue);
+      if (!ParseTransitionTimingFunctionValues(aValue)) {
+        SkipUntil(')');
+        return PR_FALSE;
+      }
+      return PR_TRUE;
     }
   }
   if ((aVariantMask & VARIANT_CALC) &&
       (eCSSToken_Function == tk->mType) &&
       (tk->mIdent.LowerCaseEqualsLiteral("-moz-calc") ||
        tk->mIdent.LowerCaseEqualsLiteral("-moz-min") ||
        tk->mIdent.LowerCaseEqualsLiteral("-moz-max"))) {
     // calc() currently allows only lengths and percents inside it.
--- a/layout/style/test/Makefile.in
+++ b/layout/style/test/Makefile.in
@@ -170,16 +170,17 @@ GARBAGE += css_properties.js
 		test_system_font_serialization.html \
 		test_transitions_computed_values.html \
 		test_transitions_computed_value_combinations.html \
 		test_transitions_events.html \
 		test_transitions.html \
 		test_transitions_per_property.html \
 		test_transitions_dynamic_changes.html \
 		test_transitions_bug537151.html \
+		test_unclosed_parentheses.html \
 		test_units_angle.html \
 		test_units_frequency.html \
 		test_units_length.html \
 		test_units_time.html \
 		test_value_cloning.html \
 		test_value_computation.html \
 		test_value_storage.html \
 		test_visited_image_loading.html \
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -1026,17 +1026,20 @@ var gCSSProperties = {
 		"-moz-repeating-radial-gradient(99deg, cover, red, blue)",
 		"-moz-repeating-radial-gradient(-1.2345rad, circle, red, blue)",
 		"-moz-repeating-radial-gradient(399grad, ellipse closest-corner, red, blue)",
 		"-moz-repeating-radial-gradient(399grad, farthest-side circle, red, blue)",
 
 		"-moz-repeating-radial-gradient(top left 99deg, cover, red, blue)",
 		"-moz-repeating-radial-gradient(15% 20% -1.2345rad, circle, red, blue)",
 		"-moz-repeating-radial-gradient(45px 399grad, ellipse closest-corner, red, blue)",
-		"-moz-repeating-radial-gradient(45px 399grad, farthest-side circle, red, blue)"
+		"-moz-repeating-radial-gradient(45px 399grad, farthest-side circle, red, blue)",
+		"-moz-image-rect(url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), 2, 10, 10, 2)",
+		"-moz-image-rect(url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), 10%, 50%, 30%, 0%)",
+		"-moz-image-rect(url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==), 10, 50%, 30%, 0)",
 		],
 		invalid_values: [
 			/* Old syntax */
 			"-moz-linear-gradient(10px 10px, 20px, 30px 30px, 40px, from(blue), to(red))",
 			"-moz-radial-gradient(20px 20px, 10px 10px, from(green), to(#ff00ff))",
 			"-moz-radial-gradient(10px 10px, 20%, 40px 40px, 10px, from(green), to(#ff00ff))",
 			"-moz-linear-gradient(10px, 20px, 30px, 40px, color-stop(0.5, #00ccff))",
 			"-moz-linear-gradient(20px 20px, from(blue), to(red))",
new file mode 100644
--- /dev/null
+++ b/layout/style/test/test_unclosed_parentheses.html
@@ -0,0 +1,158 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=575672
+-->
+<head>
+  <title>Test for Bug 575672</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <style type="text/css" id="style"></style>
+  <style type="text/css">
+    #display { position: relative }
+  </style>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=575672">Mozilla Bug 575672</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for unclosed parentheses in CSS values. **/
+
+// Each of the following declarations should have a single missing ')'
+// in the value.
+var declarations = [
+  "content: url(",
+  "content: url( ",
+  "content: url(http://www.foo.com",
+  "content: url('http://www.foo.com'",
+  "background-image: -moz-linear-gradient(",
+  "background-image: -moz-linear-gradient( ",
+  "background-image: -moz-linear-gradient(red, blue",
+  "background-image: -moz-linear-gradient(red, yellow, blue",
+  "background-image: -moz-linear-gradient(red 1px, yellow 5px, blue 10px",
+  "background-image: -moz-linear-gradient(red, yellow, rgb(0, 0, 255)",
+  "background-image: -moz-repeating-linear-gradient(top left, red, blue",
+  "background-image: -moz-linear-gradient(top left, red, yellow, blue",
+  "background-image: -moz-linear-gradient(top left, red 1px, yellow 5px, blue 10px",
+  "background-image: -moz-linear-gradient(top left, red, yellow, rgb(0, 0, 255)",
+  "background-image: -moz-radial-gradient(",
+  "background-image: -moz-radial-gradient( ",
+  "background-image: -moz-radial-gradient(top left 45deg, red, blue",
+  "background-image: -moz-radial-gradient(cover, red, blue",
+  "background-image: -moz-repeating-radial-gradient(circle, red, blue",
+  "background-image: -moz-radial-gradient(ellipse closest-corner, red, hsl(240, 50%, 50%)",
+  "background-image: -moz-radial-gradient(farthest-side circle, red, blue",
+  "background-image: -moz-image-rect(",
+  "background-image: -moz-image-rect( ",
+  "background-image: -moz-image-rect(url(foo.jpg)",
+  "background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10",
+  "background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10 ",
+  "background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10,",
+  "background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10, ",
+  "background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10, 10",
+  "background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10, 10 ",
+  "background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10, 10,",
+  "background-image: -moz-image-rect(url(foo.jpg), 2, 10, 10, 10, ",
+  "color: rgb(",
+  "color: rgb( ",
+  "color: rgb(128, 0",
+  "color: rgb(128, 0, 128",
+  "color: rgb(128, 0, 128, 128",
+  "color: rgba(",
+  "color: rgba( ",
+  "color: rgba(128, 0",
+  "color: rgba(128, 0, 128",
+  "color: rgba(128, 0, 128, 1",
+  "color: rgba(128, 0, 128, 1, 1",
+  "color: hsl(",
+  "color: hsl( ",
+  "color: hsl(240, 50%",
+  "color: hsl(240, 50%, 50%",
+  "color: hsl(240, 50%, 50%, 50%",
+  "color: hsla(",
+  "color: hsla( ",
+  "color: hsla(240, 50%",
+  "color: hsla(240, 50%, 50%",
+  "color: hsla(240, 50%, 50%, 1",
+  "color: hsla(240, 50%, 50%, 1, 1",
+  "content: counter(",
+  "content: counter( ",
+  "content: counter(foo",
+  "content: counter(foo ",
+  "content: counter(foo,",
+  "content: counter(foo, ",
+  "content: counter(foo, upper-roman",
+  "content: counter(foo, upper-roman ",
+  "content: counter(foo, upper-roman,",
+  "content: counter(foo, upper-roman, ",
+  "content: counters(",
+  "content: counters( ",
+  "content: counters(foo, ','",
+  "content: counters(foo, ',' ",
+  "content: counters(foo, ',',",
+  "content: counters(foo, ',', ",
+  "content: counters(foo, ',', upper-roman",
+  "content: counters(foo, ',', upper-roman ",
+  "content: counters(foo, ',', upper-roman,",
+  "content: counters(foo, ',', upper-roman, ",
+  "content: attr(",
+  "content: attr( ",
+  "content: attr(href",
+  "content: attr(href ",
+  "content: attr(html",
+  "content: attr(html ",
+  "content: attr(html|",
+  "content: attr(html| ",
+  "content: attr(html|href",
+  "content: attr(html|href ",
+  "content: attr(|",
+  "content: attr(| ",
+  "content: attr(|href",
+  "content: attr(|href ",
+  "-moz-transition-timing-function: cubic-bezier(",
+  "-moz-transition-timing-function: cubic-bezier( ",
+  "-moz-transition-timing-function: cubic-bezier(0, 0, 1",
+  "-moz-transition-timing-function: cubic-bezier(0, 0, 1 ",
+  "-moz-transition-timing-function: cubic-bezier(0, 0, 1,",
+  "-moz-transition-timing-function: cubic-bezier(0, 0, 1, ",
+  "-moz-transition-timing-function: cubic-bezier(0, 0, 1, 1",
+  "-moz-transition-timing-function: cubic-bezier(0, 0, 1, 1 ",
+  "-moz-transition-timing-function: cubic-bezier(0, 0, 1, 1,",
+  "-moz-transition-timing-function: cubic-bezier(0, 0, 1, 1, ",
+  "border-top-width: -moz-calc(",
+  "border-top-width: -moz-calc( ",
+  "border-top-width: -moz-calc(2em",
+  "border-top-width: -moz-calc(2em ",
+  "border-top-width: -moz-calc(2em +",
+  "border-top-width: -moz-calc(2em + ",
+  "border-top-width: -moz-calc(2em *",
+  "border-top-width: -moz-calc(2em * ",
+  "border-top-width: -moz-calc((2em)",
+  "border-top-width: -moz-calc((2em) ",
+];
+
+var textNode = document.createTextNode("");
+document.getElementById("style").appendChild(textNode);
+var cs = getComputedStyle(document.getElementById("display"), "");
+
+for (var i = 0; i < declarations.length; ++i) {
+  var sheet = "@namespace html url(http://www.w3.org/1999/xhtml);\n" +
+              "#display { color: green; " + declarations[i] +
+              " x x x x x x x ; color: red; ) ; z-index: " + (i + 1) + " }";
+  textNode.data = sheet;
+  is(cs.color, "rgb(0, 128, 0)",
+     "color for declaration '" + declarations[i] + "'");
+  is(cs.zIndex, i+1,
+     "z-index for declaration '" + declarations[i] + "'");
+}
+
+</script>
+</pre>
+</body>
+</html>