REGRESSION (r173698): Leaks of selector lists in CSS parsing
authordarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 28 Jan 2015 17:50:00 +0000 (17:50 +0000)
committerdarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 28 Jan 2015 17:50:00 +0000 (17:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=140993

Reviewed by Anders Carlsson.

* css/CSSGrammar.y.in: Fixed logic in rules that were not moving a parser-
owned pointer into a unique_ptr in all code paths. The magic value
invalidSelectorVector makes this really messy. We might want to find a
different seolution in the future.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@179258 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/css/CSSGrammar.y.in

index 1d2c13d7dcf34fa56cf3632b34e02f150b7ad205..9e5a236ac1f43395dc08a11f96dd4d532e15a689 100644 (file)
@@ -1,3 +1,15 @@
+2015-01-28  Darin Adler  <darin@apple.com>
+
+        REGRESSION (r173698): Leaks of selector lists in CSS parsing
+        https://bugs.webkit.org/show_bug.cgi?id=140993
+
+        Reviewed by Anders Carlsson.
+
+        * css/CSSGrammar.y.in: Fixed logic in rules that were not moving a parser-
+        owned pointer into a unique_ptr in all code paths. The magic value
+        invalidSelectorVector makes this really messy. We might want to find a
+        different seolution in the future.
+
 2015-01-28  Brent Fulgham  <bfulgham@apple.com>
 
         [Win] Unreviewed build fix after r179247.
index 1903d9e253f75c8c72cf279fc42bd828ffb890ca..3c500f992a7e14c2754f7f9c32f86779c9883b67 100644 (file)
@@ -85,16 +85,13 @@ static inline CSSParserValue makeIdentValue(CSSParserString string)
     return v;
 }
 
-auto invalidSelectorVector = reinterpret_cast<Vector<std::unique_ptr<CSSParserSelector>>*>(-1);
+static auto* const invalidSelectorVector = reinterpret_cast<Vector<std::unique_ptr<CSSParserSelector>>*>(-1);
 
 static bool selectorListDoesNotMatchAnyPseudoElement(const Vector<std::unique_ptr<CSSParserSelector>>* selectorVector)
 {
     if (!selectorVector)
         return true;
 
-    if (selectorVector == invalidSelectorVector)
-        return false;
-
     for (unsigned i = 0; i < selectorVector->size(); ++i) {
         for (const CSSParserSelector* selector = selectorVector->at(i).get(); selector; selector = selector->tagHistory()) {
             if (selector->matchesPseudoElement())
@@ -317,7 +314,8 @@ static bool selectorListDoesNotMatchAnyPseudoElement(const Vector<std::unique_pt
 
 %union { Vector<std::unique_ptr<CSSParserSelector>>* selectorList; }
 %type <selectorList> selector_list nested_selector_list simple_selector_list nth_selector_ending
-%destructor { delete $$; } selector_list nested_selector_list simple_selector_list nth_selector_ending
+%destructor { delete $$; } selector_list nested_selector_list simple_selector_list
+%destructor { if ($$ != invalidSelectorVector) delete $$; } nth_selector_ending
 
 %union { bool boolean; }
 %type <boolean> declaration declaration_list decl_list priority
@@ -1417,45 +1415,53 @@ pseudo:
     // Definition of :nth-child().
     | ':' NTHCHILDFUNCTIONS maybe_space NTH nth_selector_ending {
         $$ = nullptr;
-        if (selectorListDoesNotMatchAnyPseudoElement($5)) {
-            auto selector = std::make_unique<CSSParserSelector>();
-            selector->setMatch(CSSSelector::PseudoClass);
-            selector->setArgument($4);
-            selector->setPseudoClassValue($2);
-            if ($5)
-                selector->adoptSelectorVector(*std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>>($5));
-
-            CSSSelector::PseudoClassType pseudoClassType = selector->pseudoClassType();
-            if (pseudoClassType == CSSSelector::PseudoClassNthChild || pseudoClassType == CSSSelector::PseudoClassNthLastChild)
-                $$ = selector.release();
+        if ($5 != invalidSelectorVector) {
+            std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>> ending($5);
+            if (selectorListDoesNotMatchAnyPseudoElement(ending.get())) {
+                auto selector = std::make_unique<CSSParserSelector>();
+                selector->setMatch(CSSSelector::PseudoClass);
+                selector->setArgument($4);
+                selector->setPseudoClassValue($2);
+                if (ending)
+                    selector->adoptSelectorVector(*ending);
+                CSSSelector::PseudoClassType pseudoClassType = selector->pseudoClassType();
+                if (pseudoClassType == CSSSelector::PseudoClassNthChild || pseudoClassType == CSSSelector::PseudoClassNthLastChild)
+                    $$ = selector.release();
+            }
         }
     }
     | ':' NTHCHILDFUNCTIONS maybe_space maybe_unary_operator INTEGER nth_selector_ending {
         $$ = nullptr;
-        if (selectorListDoesNotMatchAnyPseudoElement($6)) {
-            auto selector = std::make_unique<CSSParserSelector>();
-            selector->setMatch(CSSSelector::PseudoClass);
-            selector->setArgument(AtomicString::number($4 * $5));
-            selector->setPseudoClassValue($2);
-            if ($6)
-                selector->adoptSelectorVector(*std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>>($6));
-            CSSSelector::PseudoClassType pseudoClassType = selector->pseudoClassType();
-            if (pseudoClassType == CSSSelector::PseudoClassNthChild || pseudoClassType == CSSSelector::PseudoClassNthLastChild)
-                $$ = selector.release();
+        if ($6 != invalidSelectorVector) {
+            std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>> ending($6);
+            if (selectorListDoesNotMatchAnyPseudoElement(ending.get())) {
+                auto selector = std::make_unique<CSSParserSelector>();
+                selector->setMatch(CSSSelector::PseudoClass);
+                selector->setArgument(AtomicString::number($4 * $5));
+                selector->setPseudoClassValue($2);
+                if (ending)
+                    selector->adoptSelectorVector(*ending);
+                CSSSelector::PseudoClassType pseudoClassType = selector->pseudoClassType();
+                if (pseudoClassType == CSSSelector::PseudoClassNthChild || pseudoClassType == CSSSelector::PseudoClassNthLastChild)
+                    $$ = selector.release();
+            }
         }
     }
     | ':' NTHCHILDFUNCTIONS maybe_space IDENT nth_selector_ending {
         $$ = nullptr;
-        if (isValidNthToken($4) && selectorListDoesNotMatchAnyPseudoElement($5)) {
-            auto selector = std::make_unique<CSSParserSelector>();
-            selector->setMatch(CSSSelector::PseudoClass);
-            selector->setArgument($4);
-            selector->setPseudoClassValue($2);
-            if ($5)
-               selector->adoptSelectorVector(*std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>>($5));
-            CSSSelector::PseudoClassType pseudoClassType = selector->pseudoClassType();
-            if (pseudoClassType == CSSSelector::PseudoClassNthChild || pseudoClassType == CSSSelector::PseudoClassNthLastChild)
-                $$ = selector.release();
+        if ($5 != invalidSelectorVector) {
+            std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>> ending($5);
+            if (isValidNthToken($4) && selectorListDoesNotMatchAnyPseudoElement(ending.get())) {
+                auto selector = std::make_unique<CSSParserSelector>();
+                selector->setMatch(CSSSelector::PseudoClass);
+                selector->setArgument($4);
+                selector->setPseudoClassValue($2);
+                if (ending)
+                   selector->adoptSelectorVector(*ending);
+                CSSSelector::PseudoClassType pseudoClassType = selector->pseudoClassType();
+                if (pseudoClassType == CSSSelector::PseudoClassNthChild || pseudoClassType == CSSSelector::PseudoClassNthLastChild)
+                    $$ = selector.release();
+            }
         }
     }
 
@@ -1500,13 +1506,16 @@ pseudo:
     // Definition of :not().
     | ':' NOTFUNCTION maybe_space nested_selector_list maybe_space ')' {
         $$ = nullptr;
-        if ($4 && selectorListDoesNotMatchAnyPseudoElement($4)) {
-            auto selector = std::make_unique<CSSParserSelector>();
-            selector->setMatch(CSSSelector::PseudoClass);
-            selector->setPseudoClassValue($2);
-            selector->adoptSelectorVector(*std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>>($4));
-            if (selector->pseudoClassType() == CSSSelector::PseudoClassNot)
-                $$ = selector.release();
+        if ($4 != invalidSelectorVector) {
+            std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>> list($4);
+            if (list && selectorListDoesNotMatchAnyPseudoElement(list.get())) {
+                auto selector = std::make_unique<CSSParserSelector>();
+                selector->setMatch(CSSSelector::PseudoClass);
+                selector->setPseudoClassValue($2);
+                selector->adoptSelectorVector(*list);
+                if (selector->pseudoClassType() == CSSSelector::PseudoClassNot)
+                    $$ = selector.release();
+            }
         }
     }
   ;