Bug 788836 - Simplify @-keyword parsing by letting ParseAtKeyword deal with everthing after the @. Make it pass the first char to GatherIdent so that it returns false for a bad escape sequence at the start. r=dbaron
authorMats Palmgren <matspal@gmail.com>
Wed, 12 Sep 2012 00:20:52 +0200
changeset 106849 1a1a98daab06467733ea7314a43f0bd70618a19a
parent 106848 c14834c3ce2df638c559179067a0b0abfa323110
child 106850 544c405fb456b4cfdc102cbe14d704c4ead17ae0
push id1708
push userakeybl@mozilla.com
push dateMon, 19 Nov 2012 21:10:21 +0000
treeherdermozilla-esr52@2704e441363f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs788836
milestone18.0a1
Bug 788836 - Simplify @-keyword parsing by letting ParseAtKeyword deal with everthing after the @. Make it pass the first char to GatherIdent so that it returns false for a bad escape sequence at the start. r=dbaron
layout/style/crashtests/788836.html
layout/style/crashtests/crashtests.list
layout/style/nsCSSScanner.cpp
layout/style/nsCSSScanner.h
new file mode 100644
--- /dev/null
+++ b/layout/style/crashtests/788836.html
@@ -0,0 +1,3 @@
+<style>@\</style>
+<style>@\
+</style>
--- a/layout/style/crashtests/crashtests.list
+++ b/layout/style/crashtests/crashtests.list
@@ -72,8 +72,9 @@ load 611922-1.html
 load 665209-1.html
 asserts(2) load 671799-1.html
 asserts(2) load 671799-2.html
 load 690990-1.html
 load 696188-1.html
 load 700116.html
 load 729126-1.html
 load 729126-2.html
+load 788836.html
--- a/layout/style/nsCSSScanner.cpp
+++ b/layout/style/nsCSSScanner.cpp
@@ -723,23 +723,17 @@ nsCSSScanner::Next(nsCSSToken& aToken)
       return ParseURange(ch, aToken);
 
     // IDENT
     if (StartsIdent(ch, Peek()))
       return ParseIdent(ch, aToken);
 
     // AT_KEYWORD
     if (ch == '@') {
-      int32_t nextChar = Read();
-      if (nextChar >= 0) {
-        int32_t followingChar = Peek();
-        Pushback(nextChar);
-        if (StartsIdent(nextChar, followingChar))
-          return ParseAtKeyword(ch, aToken);
-      }
+      return ParseAtKeyword(aToken);
     }
 
     // NUMBER or DIM
     if ((ch == '.') || (ch == '+') || (ch == '-')) {
       int32_t nextChar = Peek();
       if (IsDigit(nextChar)) {
         return ParseNumber(ch, aToken);
       }
@@ -1023,18 +1017,18 @@ nsCSSScanner::ParseAndAppendEscape(nsStr
  */
 bool
 nsCSSScanner::GatherIdent(int32_t aChar, nsString& aIdent)
 {
   if (aChar == '\\') {
     if (!ParseAndAppendEscape(aIdent, false)) {
       return false;
     }
-  }
-  else if (0 < aChar) {
+  } else {
+    MOZ_ASSERT(aChar > 0);
     aIdent.Append(aChar);
   }
   for (;;) {
     // If nothing in pushback, first try to get as much as possible in one go
     if (!mPushbackCount && mOffset < mCount) {
       // See how much we can consume and append in one go
       uint32_t n = mOffset;
       // Count number of Ident characters that can be processed
@@ -1060,16 +1054,17 @@ nsCSSScanner::GatherIdent(int32_t aChar,
       }
     } else if (IsIdent(aChar)) {
       aIdent.Append(PRUnichar(aChar));
     } else {
       Pushback(aChar);
       break;
     }
   }
+  MOZ_ASSERT(aIdent.Length() > 0);
   return true;
 }
 
 bool
 nsCSSScanner::ParseRef(int32_t aChar, nsCSSToken& aToken)
 {
   // Fall back for when we don't have name characters following:
   aToken.mType = eCSSToken_Symbol;
@@ -1119,24 +1114,31 @@ nsCSSScanner::ParseIdent(int32_t aChar, 
     }
   }
 
   aToken.mType = tokenType;
   return true;
 }
 
 bool
-nsCSSScanner::ParseAtKeyword(int32_t aChar, nsCSSToken& aToken)
+nsCSSScanner::ParseAtKeyword(nsCSSToken& aToken)
 {
-  aToken.mIdent.SetLength(0);
-  aToken.mType = eCSSToken_AtKeyword;
-  if (!GatherIdent(0, aToken.mIdent)) {
-    aToken.mType = eCSSToken_Symbol;
-    aToken.mSymbol = PRUnichar('@');
+  int32_t ch = Read();
+  if (StartsIdent(ch, Peek())) {
+    aToken.mIdent.SetLength(0);
+    aToken.mType = eCSSToken_AtKeyword;
+    if (GatherIdent(ch, aToken.mIdent)) {
+      return true;
+    }
   }
+  if (ch >= 0) {
+    Pushback(ch);
+  }
+  aToken.mType = eCSSToken_Symbol;
+  aToken.mSymbol = PRUnichar('@');
   return true;
 }
 
 bool
 nsCSSScanner::ParseNumber(int32_t c, nsCSSToken& aToken)
 {
   NS_PRECONDITION(c == '.' || c == '+' || c == '-' || IsDigit(c),
                   "Why did we get called?");
--- a/layout/style/nsCSSScanner.h
+++ b/layout/style/nsCSSScanner.h
@@ -182,17 +182,17 @@ protected:
   int32_t Read();
   int32_t Peek();
   bool LookAhead(PRUnichar aChar);
   bool LookAheadOrEOF(PRUnichar aChar); // expect either aChar or EOF
   void EatWhiteSpace();
 
   bool ParseAndAppendEscape(nsString& aOutput, bool aInString);
   bool ParseIdent(int32_t aChar, nsCSSToken& aResult);
-  bool ParseAtKeyword(int32_t aChar, nsCSSToken& aResult);
+  bool ParseAtKeyword(nsCSSToken& aResult);
   bool ParseNumber(int32_t aChar, nsCSSToken& aResult);
   bool ParseRef(int32_t aChar, nsCSSToken& aResult);
   bool ParseString(int32_t aChar, nsCSSToken& aResult);
   bool ParseURange(int32_t aChar, nsCSSToken& aResult);
   bool SkipCComment();
 
   bool GatherIdent(int32_t aChar, nsString& aIdent);