From edddf9e503b9562320ae8dc32c787c86a038e640 Mon Sep 17 00:00:00 2001 From: Erik Nordin Date: Thu, 12 Mar 2020 18:11:09 +0000 Subject: [PATCH] style: Disallow @import rules for all Constructable StyleSheets functions. - Add enum AllowImportRules to CSS parsing. - `replaceSync()` will skip over @import rules and continue parsing. - `replace()` will skip over @import rules and continue parsing. - `insertRule()` will throw a syntax error on @import rules. - Modify WPT test cases to reflect these changes. Differential Revision: https://phabricator.services.mozilla.com/D61882 --- components/style/stylesheets/mod.rs | 4 +++- components/style/stylesheets/rule_list.rs | 5 ++++- components/style/stylesheets/rule_parser.rs | 10 +++++++++- components/style/stylesheets/stylesheet.rs | 18 ++++++++++++++++++ 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/components/style/stylesheets/mod.rs b/components/style/stylesheets/mod.rs index c9697ead615..9d007e45ad7 100644 --- a/components/style/stylesheets/mod.rs +++ b/components/style/stylesheets/mod.rs @@ -59,7 +59,7 @@ pub use self::rules_iterator::{AllRules, EffectiveRules}; pub use self::rules_iterator::{NestedRuleIterationCondition, RulesIterator}; pub use self::style_rule::StyleRule; pub use self::stylesheet::{DocumentStyleSheet, Namespaces, Stylesheet}; -pub use self::stylesheet::{SanitizationData, SanitizationKind}; +pub use self::stylesheet::{SanitizationData, SanitizationKind, AllowImportRules}; pub use self::stylesheet::{StylesheetContents, StylesheetInDocument, UserAgentStylesheets}; pub use self::supports_rule::SupportsRule; pub use self::viewport_rule::ViewportRule; @@ -369,6 +369,7 @@ impl CssRule { shared_lock: &SharedRwLock, state: State, loader: Option<&dyn StylesheetLoader>, + allow_import_rules: AllowImportRules, ) -> Result { let url_data = parent_stylesheet_contents.url_data.read(); let context = ParserContext::new( @@ -395,6 +396,7 @@ impl CssRule { dom_error: None, namespaces: &mut *guard, insert_rule_context: Some(insert_rule_context), + allow_import_rules, }; parse_one_rule(&mut input, &mut rule_parser) diff --git a/components/style/stylesheets/rule_list.rs b/components/style/stylesheets/rule_list.rs index 05f93eca489..4b6ac3e0a57 100644 --- a/components/style/stylesheets/rule_list.rs +++ b/components/style/stylesheets/rule_list.rs @@ -10,7 +10,7 @@ use crate::str::CssStringWriter; use crate::stylesheets::loader::StylesheetLoader; use crate::stylesheets::rule_parser::{InsertRuleContext, State}; use crate::stylesheets::stylesheet::StylesheetContents; -use crate::stylesheets::{CssRule, RulesMutateError}; +use crate::stylesheets::{CssRule, RulesMutateError, AllowImportRules}; #[cfg(feature = "gecko")] use malloc_size_of::{MallocShallowSizeOf, MallocSizeOfOps}; use servo_arc::{Arc, RawOffsetArc}; @@ -128,6 +128,7 @@ pub trait CssRulesHelpers { index: usize, nested: bool, loader: Option<&dyn StylesheetLoader>, + allow_import_rules: AllowImportRules, ) -> Result; } @@ -140,6 +141,7 @@ impl CssRulesHelpers for RawOffsetArc> { index: usize, nested: bool, loader: Option<&dyn StylesheetLoader>, + allow_import_rules: AllowImportRules, ) -> Result { let new_rule = { let read_guard = lock.read(); @@ -176,6 +178,7 @@ impl CssRulesHelpers for RawOffsetArc> { lock, state, loader, + allow_import_rules, )? }; diff --git a/components/style/stylesheets/rule_parser.rs b/components/style/stylesheets/rule_parser.rs index aefea6c504d..d380f179824 100644 --- a/components/style/stylesheets/rule_parser.rs +++ b/components/style/stylesheets/rule_parser.rs @@ -19,6 +19,7 @@ use crate::stylesheets::keyframes_rule::parse_keyframe_list; use crate::stylesheets::stylesheet::Namespaces; use crate::stylesheets::supports_rule::SupportsCondition; use crate::stylesheets::viewport_rule; +use crate::stylesheets::AllowImportRules; use crate::stylesheets::{CorsMode, DocumentRule, FontFeatureValuesRule, KeyframesRule, MediaRule}; use crate::stylesheets::{CssRule, CssRuleType, CssRules, RulesMutateError, StylesheetLoader}; use crate::stylesheets::{NamespaceRule, PageRule, StyleRule, SupportsRule, ViewportRule}; @@ -50,7 +51,7 @@ pub struct TopLevelRuleParser<'a> { /// This won't contain any namespaces, and only nested parsers created with /// `ParserContext::new_with_rule_type` will. pub context: ParserContext<'a>, - /// The current state of the parser. + /// The current stajkj/te of the parser. pub state: State, /// Whether we have tried to parse was invalid due to being in the wrong /// place (e.g. an @import rule was found while in the `Body` state). Reset @@ -62,6 +63,8 @@ pub struct TopLevelRuleParser<'a> { pub namespaces: &'a mut Namespaces, /// The info we need insert a rule in a list. pub insert_rule_context: Option>, + /// Whether @import rules will be allowed. + pub allow_import_rules: AllowImportRules, } impl<'b> TopLevelRuleParser<'b> { @@ -189,6 +192,10 @@ impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> { return Err(input.new_custom_error(StyleParseErrorKind::UnexpectedImportRule)) } + if let AllowImportRules::No = self.allow_import_rules { + return Err(input.new_custom_error(StyleParseErrorKind::UnexpectedImportRule)) + } + // FIXME(emilio): We should always be able to have a loader // around! See bug 1533783. if self.loader.is_none() { @@ -203,6 +210,7 @@ impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> { let media = Arc::new(self.shared_lock.wrap(media)); let prelude = AtRuleNonBlockPrelude::Import(url, media); + return Ok(AtRuleType::WithoutBlock(prelude)); }, "namespace" => { diff --git a/components/style/stylesheets/stylesheet.rs b/components/style/stylesheets/stylesheet.rs index 068bfb6502a..6679f587a41 100644 --- a/components/style/stylesheets/stylesheet.rs +++ b/components/style/stylesheets/stylesheet.rs @@ -81,6 +81,7 @@ impl StylesheetContents { quirks_mode: QuirksMode, line_number_offset: u32, use_counters: Option<&UseCounters>, + allow_import_rules: AllowImportRules, sanitization_data: Option<&mut SanitizationData>, ) -> Self { let namespaces = RwLock::new(Namespaces::default()); @@ -95,6 +96,7 @@ impl StylesheetContents { quirks_mode, line_number_offset, use_counters, + allow_import_rules, sanitization_data, ); @@ -355,6 +357,16 @@ pub enum SanitizationKind { NoConditionalRules, } +/// Whether @import rules are allowed. +#[repr(u8)] +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum AllowImportRules { + /// @import rules will be parsed. + Yes, + /// @import rules will not be parsed. + No, +} + impl SanitizationKind { fn allows(self, rule: &CssRule) -> bool { debug_assert_ne!(self, SanitizationKind::None); @@ -415,6 +427,7 @@ impl Stylesheet { stylesheet_loader: Option<&dyn StylesheetLoader>, error_reporter: Option<&dyn ParseErrorReporter>, line_number_offset: u32, + allow_import_rules: AllowImportRules, ) { let namespaces = RwLock::new(Namespaces::default()); @@ -430,6 +443,7 @@ impl Stylesheet { existing.contents.quirks_mode, line_number_offset, /* use_counters = */ None, + allow_import_rules, /* sanitization_data = */ None, ); @@ -457,6 +471,7 @@ impl Stylesheet { quirks_mode: QuirksMode, line_number_offset: u32, use_counters: Option<&UseCounters>, + allow_import_rules: AllowImportRules, mut sanitization_data: Option<&mut SanitizationData>, ) -> (Vec, Option, Option) { let mut rules = Vec::new(); @@ -481,6 +496,7 @@ impl Stylesheet { dom_error: None, insert_rule_context: None, namespaces, + allow_import_rules, }; { @@ -537,6 +553,7 @@ impl Stylesheet { error_reporter: Option<&dyn ParseErrorReporter>, quirks_mode: QuirksMode, line_number_offset: u32, + allow_import_rules: AllowImportRules, ) -> Self { // FIXME: Consider adding use counters to Servo? let contents = StylesheetContents::from_str( @@ -549,6 +566,7 @@ impl Stylesheet { quirks_mode, line_number_offset, /* use_counters = */ None, + allow_import_rules, /* sanitized_output = */ None, );