diff options
author | Johannes Hofmann <Johannes.Hofmann@gmx.de> | 2014-03-05 21:48:42 +0100 |
---|---|---|
committer | Johannes Hofmann <Johannes.Hofmann@gmx.de> | 2014-03-05 21:48:42 +0100 |
commit | 4ef5572a6256155b6213987f71f4d836cb891ffe (patch) | |
tree | d44acbc088d4d97421a5798b5184b0d2f144baf4 /src/css.cc | |
parent | 0b04276e8e917bad961e1178a959483a7aeb5620 (diff) |
use a singe matchCache per CssContext
This fixes a crash with the following HTML:
<head>
<style type="text/css">
.first .second .third{
border-top-color:#aaa !important;
}
#n .a, .b{
color: #aaa !important;
border:#bbb;
}
</style>
</head>
<body>
<div id="submit" value="Submit" class="a">
jhu
</div>
</body>
The problem is that CssSelectors can be shared between normal and
!important rules. The matchCacheOffset was overwritten in that case
causing the crash on access.
noticed-by and test-case-by: corvid
Diffstat (limited to 'src/css.cc')
-rw-r--r-- | src/css.cc | 37 |
1 files changed, 19 insertions, 18 deletions
@@ -399,9 +399,9 @@ void CssStyleSheet::addRule (CssRule *rule) { } if (ruleList) { - rule->selector->setMatchCacheOffset (matchCacheOffset); - matchCacheOffset += rule->selector->size (); ruleList->insert (rule); + if (rule->selector->getRequiredMatchCache () > requiredMatchCache) + requiredMatchCache = rule->selector->getRequiredMatchCache (); } else { assert (top->getElement () == CssSimpleSelector::ELEMENT_NONE); delete rule; @@ -488,7 +488,7 @@ CssStyleSheet CssContext::userAgentSheet; CssContext::CssContext () { pos = 0; - matchCache[CSS_PRIMARY_USER_AGENT].setSize (userAgentSheet.matchCacheOffset, -1); + matchCache.setSize (userAgentSheet.getRequiredMatchCache (), -1); } /** @@ -505,28 +505,25 @@ void CssContext::apply (CssPropertyList *props, Doctree *docTree, CssPropertyList *tagStyle, CssPropertyList *tagStyleImportant, CssPropertyList *nonCssHints) { - userAgentSheet.apply (props, docTree, node, - &matchCache[CSS_PRIMARY_USER_AGENT]); - sheet[CSS_PRIMARY_USER].apply (props, docTree, node, - &matchCache[CSS_PRIMARY_USER]); + userAgentSheet.apply (props, docTree, node, &matchCache); + + sheet[CSS_PRIMARY_USER].apply (props, docTree, node, &matchCache); if (nonCssHints) nonCssHints->apply (props); - sheet[CSS_PRIMARY_AUTHOR].apply (props, docTree, node, - &matchCache[CSS_PRIMARY_AUTHOR]); + sheet[CSS_PRIMARY_AUTHOR].apply (props, docTree, node, &matchCache); if (tagStyle) tagStyle->apply (props); sheet[CSS_PRIMARY_AUTHOR_IMPORTANT].apply (props, docTree, node, - &matchCache[CSS_PRIMARY_AUTHOR_IMPORTANT]); + &matchCache); if (tagStyleImportant) tagStyleImportant->apply (props); - sheet[CSS_PRIMARY_USER_IMPORTANT].apply (props, docTree, node, - &matchCache[CSS_PRIMARY_USER_IMPORTANT]); + sheet[CSS_PRIMARY_USER_IMPORTANT].apply (props, docTree, node, &matchCache); } void CssContext::addRule (CssSelector *sel, CssPropertyList *props, @@ -540,12 +537,16 @@ void CssContext::addRule (CssSelector *sel, CssPropertyList *props, !rule->isSafe ()) { MSG_WARN ("Ignoring unsafe author style that might reveal browsing history\n"); delete rule; - } else if (order == CSS_PRIMARY_USER_AGENT) { - userAgentSheet.addRule (rule); - matchCache[CSS_PRIMARY_USER_AGENT].setSize (userAgentSheet.matchCacheOffset, -1); - } else { - sheet[order].addRule (rule); - matchCache[order].setSize (sheet[order].matchCacheOffset, -1); + } else { + rule->selector->setMatchCacheOffset(matchCache.size ()); + if (rule->selector->getRequiredMatchCache () > matchCache.size ()) + matchCache.setSize (rule->selector->getRequiredMatchCache (), -1); + + if (order == CSS_PRIMARY_USER_AGENT) { + userAgentSheet.addRule (rule); + } else { + sheet[order].addRule (rule); + } } } } |