Revision: 5445
Author:   [email protected]
Date:     Wed Jun 12 12:17:07 2013
Log:      parse more css attribute match operators
https://codereview.appspot.com/10236043

Right now the cajoler fails to parse stuff like
  p[x$=y] {}
and the parse failure causes it to throw out a lot more css than it should.

Fixing the error recovery is somewhat nontrivial. Adding the new operators
is trivial.

Note, this just allows the operators to parse, but rejects them as not
allowed, similar to the |= operator. So, the operators still don't work,
but we recover from that better.

R=ihab.awad


http://code.google.com/p/google-caja/source/detail?r=5445

Modified:
 /trunk/src/com/google/caja/lexer/CssLexer.java
 /trunk/src/com/google/caja/parser/css/CssParser.java
 /trunk/src/com/google/caja/parser/css/CssTree.java
 /trunk/src/com/google/caja/plugin/CssValidator.java
 /trunk/src/com/google/caja/plugin/PluginMessageType.java
 /trunk/tests/com/google/caja/parser/css/cssparsergolden2.txt
 /trunk/tests/com/google/caja/parser/css/cssparserinput2.css
 /trunk/tests/com/google/caja/parser/css/cssrendergolden2.txt
 /trunk/tests/com/google/caja/plugin/CssValidatorTest.java

=======================================
--- /trunk/src/com/google/caja/lexer/CssLexer.java      Fri Jun 22 09:42:32 2012
+++ /trunk/src/com/google/caja/lexer/CssLexer.java      Wed Jun 12 12:17:07 2013
@@ -317,14 +317,14 @@
         //               *yytext
         type = CssTokenType.PUNCTUATION;
       }
-    } else if ('~' == ch || '|' == ch) {
-      if (end < limit && '=' == buf[end]) {
-        // "~="          INCLUDES
-        // "|="          DASHMATCH
-        ++end;
-      } else {
-        //        .      *yytext
-      }
+    } else if (end < limit && '=' == buf[end] &&
+        ('~' == ch || '|' == ch || '^' == ch || '$' == ch || '*' == ch)) {
+      // "~="          INCLUDES
+      // "|="          DASHMATCH
+      // "^="          HEADMATCH
+      // "$="          TAILMATCH
+      // "*="          SUBSTRINGMATCH
+      ++end;
       type = CssTokenType.PUNCTUATION;

     } else if (ch == '\'' || ch == '"') {
=======================================
--- /trunk/src/com/google/caja/parser/css/CssParser.java Fri Jun 22 09:42:32 2012 +++ /trunk/src/com/google/caja/parser/css/CssParser.java Wed Jun 12 12:17:07 2013
@@ -595,6 +595,18 @@
         op = new CssTree.AttribOperation(
             t.pos, CssTree.AttribOperator.DASHMATCH);
         tq.advance();
+      } else if ("^=".equals(t.text)) {
+        op = new CssTree.AttribOperation(
+            t.pos, CssTree.AttribOperator.HEADMATCH);
+        tq.advance();
+      } else if ("$=".equals(t.text)) {
+        op = new CssTree.AttribOperation(
+            t.pos, CssTree.AttribOperator.TAILMATCH);
+        tq.advance();
+      } else if ("*=".equals(t.text)) {
+        op = new CssTree.AttribOperation(
+            t.pos, CssTree.AttribOperator.SUBSTRINGMATCH);
+        tq.advance();
       }
     }
     CssTree.CssLiteral value = null;
=======================================
--- /trunk/src/com/google/caja/parser/css/CssTree.java Fri Jun 22 09:42:32 2012 +++ /trunk/src/com/google/caja/parser/css/CssTree.java Wed Jun 12 12:17:07 2013
@@ -712,6 +712,9 @@
     EQUAL("="),
     INCLUDES("~="),
     DASHMATCH("|="),
+    HEADMATCH("^="),
+    TAILMATCH("$="),
+    SUBSTRINGMATCH("*="),
     ;
     private final String op;
     AttribOperator(String op) { this.op = op; }
=======================================
--- /trunk/src/com/google/caja/plugin/CssValidator.java Wed Oct 3 15:58:36 2012 +++ /trunk/src/com/google/caja/plugin/CssValidator.java Wed Jun 12 12:17:07 2013
@@ -24,6 +24,7 @@
 import com.google.caja.parser.ParseTreeNode;
 import com.google.caja.parser.css.CssPropertySignature;
 import com.google.caja.parser.css.CssTree;
+import com.google.caja.parser.css.CssTree.AttribOperator;
 import com.google.caja.parser.css.CssTree.Combinator;
 import com.google.caja.parser.html.AttribKey;
 import com.google.caja.parser.html.ElKey;
@@ -346,7 +347,8 @@
       valid = false;
     }
     if (null != attr.getOperation()) {
-      switch (attr.getOperation().getValue()) {
+      AttribOperator opType = attr.getOperation().getValue();
+      switch (opType) {
         case EQUAL:
           valid &= validateAttribValueEqual(elId, htmlAttribute, attr);
           break;
@@ -354,13 +356,17 @@
           valid &= validateAttribValueIncludes(elId, htmlAttribute, attr);
           break;
         case DASHMATCH:
+        case HEADMATCH:
+        case TAILMATCH:
+        case SUBSTRINGMATCH:
           mq.addMessage(
- PluginMessageType.CSS_DASHMATCH_ATTRIBUTE_OPERATOR_NOT_ALLOWED,
-              invalidNodeMessageLevel, attr.getFilePosition());
+              PluginMessageType.CSS_ATTRIBUTE_OPERATOR_NOT_ALLOWED,
+              invalidNodeMessageLevel, attr.getFilePosition(),
+              MessagePart.Factory.valueOf(opType.getToken()));
           valid = false;
           break;
         default:
-          return false;  // Unreachable
+          throw new SomethingWidgyHappenedError("attribute op " + opType);
       }
     }
     return valid;
=======================================
--- /trunk/src/com/google/caja/plugin/PluginMessageType.java Wed Oct 3 15:58:36 2012 +++ /trunk/src/com/google/caja/plugin/PluginMessageType.java Wed Jun 12 12:17:07 2013
@@ -61,8 +61,8 @@
   UNSAFE_CSS_PROPERTY("%s: unsafe css property %s", MessageLevel.ERROR),
   UNSAFE_CSS_PSEUDO_SELECTOR(
       "%s: unsafe css pseudo-selector %s", MessageLevel.ERROR),
-  CSS_DASHMATCH_ATTRIBUTE_OPERATOR_NOT_ALLOWED(
- "%s: css dash match attribute operation not allowed", MessageLevel.ERROR),
+  CSS_ATTRIBUTE_OPERATOR_NOT_ALLOWED(
+      "%s: css %s attribute operation not allowed", MessageLevel.ERROR),
   CSS_URI_VALUED_ATTRIBUTE_SELECTOR_NOT_ALLOWED(
"%s: css URI-valued attribute selector not allowed", MessageLevel.ERROR),
   CSS_ATTRIBUTE_NAME_NOT_ALLOWED_IN_SELECTOR(
=======================================
--- /trunk/tests/com/google/caja/parser/css/cssparsergolden2.txt Fri May 15 17:34:52 2009 +++ /trunk/tests/com/google/caja/parser/css/cssparsergolden2.txt Wed Jun 12 12:17:07 2013
@@ -118,6 +118,30 @@
           StringLiteral : bar-baz
     EmptyDeclaration
   RuleSet
+    Selector
+      SimpleSelector
+        IdentLiteral : foo
+        Attrib : attr
+          AttribOperation : HEADMATCH
+          StringLiteral : bar-baz
+    EmptyDeclaration
+  RuleSet
+    Selector
+      SimpleSelector
+        IdentLiteral : foo
+        Attrib : attr
+          AttribOperation : TAILMATCH
+          StringLiteral : bar-baz
+    EmptyDeclaration
+  RuleSet
+    Selector
+      SimpleSelector
+        IdentLiteral : foo
+        Attrib : attr
+          AttribOperation : SUBSTRINGMATCH
+          StringLiteral : bar-baz
+    EmptyDeclaration
+  RuleSet
     Selector
       SimpleSelector
         IdentLiteral : foo
=======================================
--- /trunk/tests/com/google/caja/parser/css/cssparserinput2.css Fri May 15 17:34:52 2009 +++ /trunk/tests/com/google/caja/parser/css/cssparserinput2.css Wed Jun 12 12:17:07 2013
@@ -23,6 +23,9 @@
 foo[attr = "bar"] {}
 foo[attr ~= 'bar baz'] {}
 foo[attr |= 'bar-baz'] {}
+foo[attr ^= 'bar-baz'] {}
+foo[attr $= 'bar-baz'] {}
+foo[attr *= 'bar-baz'] {}

 /* The RHS of the attribute comparison operator in the following cases
  * will parse to an IdentLiteral since it is unquoted. */
=======================================
--- /trunk/tests/com/google/caja/parser/css/cssrendergolden2.txt Fri May 15 17:34:52 2009 +++ /trunk/tests/com/google/caja/parser/css/cssrendergolden2.txt Wed Jun 12 12:17:07 2013
@@ -25,6 +25,12 @@
 }
 foo[attr |= 'bar-baz'] {
 }
+foo[attr ^= 'bar-baz'] {
+}
+foo[attr $= 'bar-baz'] {
+}
+foo[attr *= 'bar-baz'] {
+}
 foo[attr = bar] {
 }
 foo[attr |= bar-baz] {
=======================================
--- /trunk/tests/com/google/caja/plugin/CssValidatorTest.java Wed Oct 3 15:58:36 2012 +++ /trunk/tests/com/google/caja/plugin/CssValidatorTest.java Wed Jun 12 12:17:07 2013
@@ -1344,7 +1344,7 @@
                                            + "::loose-quotable-words\n"
             + "          IdentLiteral : Arial\n"
             );
-
+
runTest("p { font-family: 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' }",
             "StyleSheet\n"
             + "  RuleSet\n"
@@ -1657,6 +1657,9 @@
     fails("zork[type='radio'] { font-weight: bold }");
     fails("zork[type~='radio'] { font-weight: bold }");
     fails("zork[type|='radio'] { font-weight: bold }");
+    fails("zork[type^='radio'] { font-weight: bold }");
+    fails("zork[type$='radio'] { font-weight: bold }");
+    fails("zork[type*='radio'] { font-weight: bold }");
     // now try tags in the schema, but which we disallow
     fails("link[type] { font-weight: bold }");
     fails("object[type] { font-weight: bold }");

--

--- You received this message because you are subscribed to the Google Groups "Google Caja Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to