Reviewers: ihab.awad,
Description:
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.
Please review this at https://codereview.appspot.com/10236043/
Affected files:
M src/com/google/caja/lexer/CssLexer.java
M src/com/google/caja/parser/css/CssParser.java
M src/com/google/caja/parser/css/CssTree.java
M src/com/google/caja/plugin/CssValidator.java
M src/com/google/caja/plugin/PluginMessageType.java
M tests/com/google/caja/parser/css/cssparsergolden2.txt
M tests/com/google/caja/parser/css/cssparserinput2.css
M tests/com/google/caja/parser/css/cssrendergolden2.txt
M tests/com/google/caja/plugin/CssValidatorTest.java
Index: src/com/google/caja/lexer/CssLexer.java
===================================================================
--- src/com/google/caja/lexer/CssLexer.java (revision 5443)
+++ src/com/google/caja/lexer/CssLexer.java (working copy)
@@ -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 == '"') {
Index: src/com/google/caja/parser/css/CssParser.java
===================================================================
--- src/com/google/caja/parser/css/CssParser.java (revision 5443)
+++ src/com/google/caja/parser/css/CssParser.java (working copy)
@@ -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;
Index: src/com/google/caja/parser/css/CssTree.java
===================================================================
--- src/com/google/caja/parser/css/CssTree.java (revision 5443)
+++ src/com/google/caja/parser/css/CssTree.java (working copy)
@@ -712,6 +712,9 @@
EQUAL("="),
INCLUDES("~="),
DASHMATCH("|="),
+ HEADMATCH("^="),
+ TAILMATCH("$="),
+ SUBSTRINGMATCH("*="),
;
private final String op;
AttribOperator(String op) { this.op = op; }
Index: src/com/google/caja/plugin/CssValidator.java
===================================================================
--- src/com/google/caja/plugin/CssValidator.java (revision 5443)
+++ src/com/google/caja/plugin/CssValidator.java (working copy)
@@ -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;
Index: src/com/google/caja/plugin/PluginMessageType.java
===================================================================
--- src/com/google/caja/plugin/PluginMessageType.java (revision 5443)
+++ src/com/google/caja/plugin/PluginMessageType.java (working copy)
@@ -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(
Index: tests/com/google/caja/parser/css/cssparsergolden2.txt
===================================================================
--- tests/com/google/caja/parser/css/cssparsergolden2.txt (revision 5443)
+++ tests/com/google/caja/parser/css/cssparsergolden2.txt (working copy)
@@ -122,6 +122,30 @@
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
+ Attrib : attr
AttribOperation : EQUAL
IdentLiteral : bar
EmptyDeclaration
Index: tests/com/google/caja/parser/css/cssparserinput2.css
===================================================================
--- tests/com/google/caja/parser/css/cssparserinput2.css (revision 5443)
+++ tests/com/google/caja/parser/css/cssparserinput2.css (working copy)
@@ -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. */
Index: tests/com/google/caja/parser/css/cssrendergolden2.txt
===================================================================
--- tests/com/google/caja/parser/css/cssrendergolden2.txt (revision 5443)
+++ tests/com/google/caja/parser/css/cssrendergolden2.txt (working copy)
@@ -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] {
Index: tests/com/google/caja/plugin/CssValidatorTest.java
===================================================================
--- tests/com/google/caja/plugin/CssValidatorTest.java (revision 5443)
+++ tests/com/google/caja/plugin/CssValidatorTest.java (working copy)
@@ -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.