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
This commit is contained in:
Erik Nordin 2020-03-12 18:11:09 +00:00 committed by Emilio Cobos Álvarez
parent 635f5fbf1b
commit edddf9e503
4 changed files with 34 additions and 3 deletions

View file

@ -59,7 +59,7 @@ pub use self::rules_iterator::{AllRules, EffectiveRules};
pub use self::rules_iterator::{NestedRuleIterationCondition, RulesIterator}; pub use self::rules_iterator::{NestedRuleIterationCondition, RulesIterator};
pub use self::style_rule::StyleRule; pub use self::style_rule::StyleRule;
pub use self::stylesheet::{DocumentStyleSheet, Namespaces, Stylesheet}; 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::stylesheet::{StylesheetContents, StylesheetInDocument, UserAgentStylesheets};
pub use self::supports_rule::SupportsRule; pub use self::supports_rule::SupportsRule;
pub use self::viewport_rule::ViewportRule; pub use self::viewport_rule::ViewportRule;
@ -369,6 +369,7 @@ impl CssRule {
shared_lock: &SharedRwLock, shared_lock: &SharedRwLock,
state: State, state: State,
loader: Option<&dyn StylesheetLoader>, loader: Option<&dyn StylesheetLoader>,
allow_import_rules: AllowImportRules,
) -> Result<Self, RulesMutateError> { ) -> Result<Self, RulesMutateError> {
let url_data = parent_stylesheet_contents.url_data.read(); let url_data = parent_stylesheet_contents.url_data.read();
let context = ParserContext::new( let context = ParserContext::new(
@ -395,6 +396,7 @@ impl CssRule {
dom_error: None, dom_error: None,
namespaces: &mut *guard, namespaces: &mut *guard,
insert_rule_context: Some(insert_rule_context), insert_rule_context: Some(insert_rule_context),
allow_import_rules,
}; };
parse_one_rule(&mut input, &mut rule_parser) parse_one_rule(&mut input, &mut rule_parser)

View file

@ -10,7 +10,7 @@ use crate::str::CssStringWriter;
use crate::stylesheets::loader::StylesheetLoader; use crate::stylesheets::loader::StylesheetLoader;
use crate::stylesheets::rule_parser::{InsertRuleContext, State}; use crate::stylesheets::rule_parser::{InsertRuleContext, State};
use crate::stylesheets::stylesheet::StylesheetContents; use crate::stylesheets::stylesheet::StylesheetContents;
use crate::stylesheets::{CssRule, RulesMutateError}; use crate::stylesheets::{CssRule, RulesMutateError, AllowImportRules};
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
use malloc_size_of::{MallocShallowSizeOf, MallocSizeOfOps}; use malloc_size_of::{MallocShallowSizeOf, MallocSizeOfOps};
use servo_arc::{Arc, RawOffsetArc}; use servo_arc::{Arc, RawOffsetArc};
@ -128,6 +128,7 @@ pub trait CssRulesHelpers {
index: usize, index: usize,
nested: bool, nested: bool,
loader: Option<&dyn StylesheetLoader>, loader: Option<&dyn StylesheetLoader>,
allow_import_rules: AllowImportRules,
) -> Result<CssRule, RulesMutateError>; ) -> Result<CssRule, RulesMutateError>;
} }
@ -140,6 +141,7 @@ impl CssRulesHelpers for RawOffsetArc<Locked<CssRules>> {
index: usize, index: usize,
nested: bool, nested: bool,
loader: Option<&dyn StylesheetLoader>, loader: Option<&dyn StylesheetLoader>,
allow_import_rules: AllowImportRules,
) -> Result<CssRule, RulesMutateError> { ) -> Result<CssRule, RulesMutateError> {
let new_rule = { let new_rule = {
let read_guard = lock.read(); let read_guard = lock.read();
@ -176,6 +178,7 @@ impl CssRulesHelpers for RawOffsetArc<Locked<CssRules>> {
lock, lock,
state, state,
loader, loader,
allow_import_rules,
)? )?
}; };

View file

@ -19,6 +19,7 @@ use crate::stylesheets::keyframes_rule::parse_keyframe_list;
use crate::stylesheets::stylesheet::Namespaces; use crate::stylesheets::stylesheet::Namespaces;
use crate::stylesheets::supports_rule::SupportsCondition; use crate::stylesheets::supports_rule::SupportsCondition;
use crate::stylesheets::viewport_rule; use crate::stylesheets::viewport_rule;
use crate::stylesheets::AllowImportRules;
use crate::stylesheets::{CorsMode, DocumentRule, FontFeatureValuesRule, KeyframesRule, MediaRule}; use crate::stylesheets::{CorsMode, DocumentRule, FontFeatureValuesRule, KeyframesRule, MediaRule};
use crate::stylesheets::{CssRule, CssRuleType, CssRules, RulesMutateError, StylesheetLoader}; use crate::stylesheets::{CssRule, CssRuleType, CssRules, RulesMutateError, StylesheetLoader};
use crate::stylesheets::{NamespaceRule, PageRule, StyleRule, SupportsRule, ViewportRule}; 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 /// This won't contain any namespaces, and only nested parsers created with
/// `ParserContext::new_with_rule_type` will. /// `ParserContext::new_with_rule_type` will.
pub context: ParserContext<'a>, pub context: ParserContext<'a>,
/// The current state of the parser. /// The current stajkj/te of the parser.
pub state: State, pub state: State,
/// Whether we have tried to parse was invalid due to being in the wrong /// 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 /// 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, pub namespaces: &'a mut Namespaces,
/// The info we need insert a rule in a list. /// The info we need insert a rule in a list.
pub insert_rule_context: Option<InsertRuleContext<'a>>, pub insert_rule_context: Option<InsertRuleContext<'a>>,
/// Whether @import rules will be allowed.
pub allow_import_rules: AllowImportRules,
} }
impl<'b> TopLevelRuleParser<'b> { impl<'b> TopLevelRuleParser<'b> {
@ -189,6 +192,10 @@ impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> {
return Err(input.new_custom_error(StyleParseErrorKind::UnexpectedImportRule)) 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 // FIXME(emilio): We should always be able to have a loader
// around! See bug 1533783. // around! See bug 1533783.
if self.loader.is_none() { 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 media = Arc::new(self.shared_lock.wrap(media));
let prelude = AtRuleNonBlockPrelude::Import(url, media); let prelude = AtRuleNonBlockPrelude::Import(url, media);
return Ok(AtRuleType::WithoutBlock(prelude)); return Ok(AtRuleType::WithoutBlock(prelude));
}, },
"namespace" => { "namespace" => {

View file

@ -81,6 +81,7 @@ impl StylesheetContents {
quirks_mode: QuirksMode, quirks_mode: QuirksMode,
line_number_offset: u32, line_number_offset: u32,
use_counters: Option<&UseCounters>, use_counters: Option<&UseCounters>,
allow_import_rules: AllowImportRules,
sanitization_data: Option<&mut SanitizationData>, sanitization_data: Option<&mut SanitizationData>,
) -> Self { ) -> Self {
let namespaces = RwLock::new(Namespaces::default()); let namespaces = RwLock::new(Namespaces::default());
@ -95,6 +96,7 @@ impl StylesheetContents {
quirks_mode, quirks_mode,
line_number_offset, line_number_offset,
use_counters, use_counters,
allow_import_rules,
sanitization_data, sanitization_data,
); );
@ -355,6 +357,16 @@ pub enum SanitizationKind {
NoConditionalRules, 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 { impl SanitizationKind {
fn allows(self, rule: &CssRule) -> bool { fn allows(self, rule: &CssRule) -> bool {
debug_assert_ne!(self, SanitizationKind::None); debug_assert_ne!(self, SanitizationKind::None);
@ -415,6 +427,7 @@ impl Stylesheet {
stylesheet_loader: Option<&dyn StylesheetLoader>, stylesheet_loader: Option<&dyn StylesheetLoader>,
error_reporter: Option<&dyn ParseErrorReporter>, error_reporter: Option<&dyn ParseErrorReporter>,
line_number_offset: u32, line_number_offset: u32,
allow_import_rules: AllowImportRules,
) { ) {
let namespaces = RwLock::new(Namespaces::default()); let namespaces = RwLock::new(Namespaces::default());
@ -430,6 +443,7 @@ impl Stylesheet {
existing.contents.quirks_mode, existing.contents.quirks_mode,
line_number_offset, line_number_offset,
/* use_counters = */ None, /* use_counters = */ None,
allow_import_rules,
/* sanitization_data = */ None, /* sanitization_data = */ None,
); );
@ -457,6 +471,7 @@ impl Stylesheet {
quirks_mode: QuirksMode, quirks_mode: QuirksMode,
line_number_offset: u32, line_number_offset: u32,
use_counters: Option<&UseCounters>, use_counters: Option<&UseCounters>,
allow_import_rules: AllowImportRules,
mut sanitization_data: Option<&mut SanitizationData>, mut sanitization_data: Option<&mut SanitizationData>,
) -> (Vec<CssRule>, Option<String>, Option<String>) { ) -> (Vec<CssRule>, Option<String>, Option<String>) {
let mut rules = Vec::new(); let mut rules = Vec::new();
@ -481,6 +496,7 @@ impl Stylesheet {
dom_error: None, dom_error: None,
insert_rule_context: None, insert_rule_context: None,
namespaces, namespaces,
allow_import_rules,
}; };
{ {
@ -537,6 +553,7 @@ impl Stylesheet {
error_reporter: Option<&dyn ParseErrorReporter>, error_reporter: Option<&dyn ParseErrorReporter>,
quirks_mode: QuirksMode, quirks_mode: QuirksMode,
line_number_offset: u32, line_number_offset: u32,
allow_import_rules: AllowImportRules,
) -> Self { ) -> Self {
// FIXME: Consider adding use counters to Servo? // FIXME: Consider adding use counters to Servo?
let contents = StylesheetContents::from_str( let contents = StylesheetContents::from_str(
@ -549,6 +566,7 @@ impl Stylesheet {
quirks_mode, quirks_mode,
line_number_offset, line_number_offset,
/* use_counters = */ None, /* use_counters = */ None,
allow_import_rules,
/* sanitized_output = */ None, /* sanitized_output = */ None,
); );