diff --git a/Cargo.lock b/Cargo.lock index 4ea0c33c..fcc69153 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -69,12 +69,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "autocfg" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" - [[package]] name = "autocfg" version = "1.0.1" @@ -138,7 +132,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc38c385bfd7e444464011bb24820f40dd1c76bcdfa1b78611cb7c2e5cafab75" dependencies = [ - "rustc_version", + "rustc_version 0.2.3", ] [[package]] @@ -165,13 +159,10 @@ dependencies = [ ] [[package]] -name = "cloudabi" -version = "0.0.3" +name = "convert_case" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -dependencies = [ - "bitflags", -] +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "core-foundation" @@ -289,18 +280,16 @@ dependencies = [ [[package]] name = "cssparser" -version = "0.25.9" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbe18ca4efb9ba3716c6da66cc3d7e673bf59fa576353011f48c4cfddbdd740e" +checksum = "1db8599a9761b371751fbf13e076fa03c6e1a78f8c5288e6ab9467f10a2322c1" dependencies = [ - "autocfg 0.1.7", "cssparser-macros", "dtoa-short", "itoa", "matches", "phf", "proc-macro2", - "procedural-masquerade", "quote", "smallvec", "syn", @@ -308,13 +297,10 @@ dependencies = [ [[package]] name = "cssparser-macros" -version = "0.3.6" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb1c84e87c717666564ec056105052331431803d606bd45529b28547b611eef" +checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e" dependencies = [ - "phf_codegen", - "proc-macro2", - "procedural-masquerade", "quote", "syn", ] @@ -341,6 +327,19 @@ dependencies = [ "memchr", ] +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version 0.4.0", + "syn", +] + [[package]] name = "digest" version = "0.9.0" @@ -423,12 +422,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - [[package]] name = "futures" version = "0.3.15" @@ -483,7 +476,7 @@ version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4c40298486cdf52cc00cd6d6987892ba502c7656a16a4192a9992b1ccedd121" dependencies = [ - "autocfg 1.0.1", + "autocfg", "proc-macro-hack", "proc-macro2", "quote", @@ -508,7 +501,7 @@ version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "feb5c238d27e2bf94ffdfd27b2c29e3df4a68c4193bb6427384259e2bf191967" dependencies = [ - "autocfg 1.0.1", + "autocfg", "futures-channel", "futures-core", "futures-io", @@ -542,6 +535,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" version = "0.2.2" @@ -550,7 +554,7 @@ checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.10.2+wasi-snapshot-preview1", ] [[package]] @@ -681,7 +685,7 @@ version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" dependencies = [ - "autocfg 1.0.1", + "autocfg", "hashbrown", ] @@ -757,12 +761,6 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - [[package]] name = "memchr" version = "2.4.0" @@ -775,7 +773,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f83fb6581e8ed1f85fd45c116db8405483899489e38406156c25eb743554361d" dependencies = [ - "autocfg 1.0.1", + "autocfg", ] [[package]] @@ -791,7 +789,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" dependencies = [ "adler", - "autocfg 1.0.1", + "autocfg", ] [[package]] @@ -855,7 +853,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ - "autocfg 1.0.1", + "autocfg", ] [[package]] @@ -912,7 +910,7 @@ version = "0.9.63" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6b0d6fb7d80f877617dfcb014e605e2b5ab2fb0afdf27935219bb6bd984cb98" dependencies = [ - "autocfg 1.0.1", + "autocfg", "cc", "libc", "pkg-config", @@ -927,18 +925,20 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "phf" -version = "0.7.24" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ + "phf_macros", "phf_shared", + "proc-macro-hack", ] [[package]] name = "phf_codegen" -version = "0.7.24" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" +checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" dependencies = [ "phf_generator", "phf_shared", @@ -946,19 +946,33 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.7.24" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" +checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" dependencies = [ "phf_shared", - "rand 0.6.5", + "rand 0.7.3", +] + +[[package]] +name = "phf_macros" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "phf_shared" -version = "0.7.24" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" dependencies = [ "siphasher", ] @@ -1062,12 +1076,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "procedural-masquerade" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1383dff4092fe903ac180e391a8d4121cc48f08ccf850614b0290c6673b69d" - [[package]] name = "psl" version = "2.0.27" @@ -1094,21 +1102,16 @@ dependencies = [ [[package]] name = "rand" -version = "0.6.5" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "autocfg 0.1.7", + "getrandom 0.1.16", "libc", - "rand_chacha 0.1.1", - "rand_core 0.4.2", - "rand_hc 0.1.0", - "rand_isaac", - "rand_jitter", - "rand_os", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc 0.2.0", "rand_pcg", - "rand_xorshift", - "winapi", ] [[package]] @@ -1125,12 +1128,12 @@ dependencies = [ [[package]] name = "rand_chacha" -version = "0.1.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" dependencies = [ - "autocfg 0.1.7", - "rand_core 0.3.1", + "ppv-lite86", + "rand_core 0.5.1", ] [[package]] @@ -1145,35 +1148,29 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.3.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "rand_core 0.4.2", + "getrandom 0.1.16", ] -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - [[package]] name = "rand_core" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" dependencies = [ - "getrandom", + "getrandom 0.2.2", ] [[package]] name = "rand_hc" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ - "rand_core 0.3.1", + "rand_core 0.5.1", ] [[package]] @@ -1185,57 +1182,13 @@ dependencies = [ "rand_core 0.6.2", ] -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -dependencies = [ - "libc", - "rand_core 0.4.2", - "winapi", -] - -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -dependencies = [ - "cloudabi", - "fuchsia-cprng", - "libc", - "rand_core 0.4.2", - "rdrand", - "winapi", -] - [[package]] name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -dependencies = [ - "autocfg 0.1.7", - "rand_core 0.4.2", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" dependencies = [ - "rand_core 0.3.1", + "rand_core 0.5.1", ] [[package]] @@ -1244,7 +1197,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" dependencies = [ - "autocfg 1.0.1", + "autocfg", "crossbeam-deque", "either", "rayon-core", @@ -1263,15 +1216,6 @@ dependencies = [ "num_cpus", ] -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "redox_syscall" version = "0.2.8" @@ -1388,7 +1332,16 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver", + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.4", ] [[package]] @@ -1453,21 +1406,20 @@ dependencies = [ [[package]] name = "selectors" -version = "0.21.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b86b100bede4f651059740afc3b6cb83458d7401cb7c1ad96d8a11e91742c86" +checksum = "fdea87c686be721aab36607728047801ee21561bfdbd6bf0da7ace2536d5879f" dependencies = [ "bitflags", "cssparser", + "derive_more", "fxhash", "log", - "matches", "phf", "phf_codegen", "precomputed-hash", "servo_arc", "smallvec", - "thin-slice", ] [[package]] @@ -1479,6 +1431,12 @@ dependencies = [ "semver-parser", ] +[[package]] +name = "semver" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012" + [[package]] name = "semver-parser" version = "0.7.0" @@ -1563,9 +1521,9 @@ dependencies = [ [[package]] name = "siphasher" -version = "0.2.3" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" +checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b" [[package]] name = "slab" @@ -1575,12 +1533,9 @@ checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" [[package]] name = "smallvec" -version = "0.6.14" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" -dependencies = [ - "maybe-uninit", -] +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" [[package]] name = "socket2" @@ -1632,12 +1587,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "thin-slice" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" - [[package]] name = "tinytemplate" version = "1.2.1" @@ -1669,7 +1618,7 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "570c2eb13b3ab38208130eccd41be92520388791207fde783bda7c1e8ace28d4" dependencies = [ - "autocfg 1.0.1", + "autocfg", "bytes", "libc", "memchr", @@ -1832,6 +1781,12 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 1b3d8326..de9a0877 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,8 +33,8 @@ base64 = "0.13" rmp-serde-legacy = { package = "rmp-serde", version = "0.13.7" } # rmp-serde 0.14.0 breaks deserialization by changing how enums are deserialized rmp-serde = "0.15" lifeguard = { version = "^ 0.6.1", optional = true } -cssparser = { version = "0.25", optional = true } -selectors = { version = "0.21", optional = true } +cssparser = { version = "0.28", optional = true } +selectors = { version = "0.23", optional = true } serde_json = { version = "1.0", optional = true } [dev-dependencies] diff --git a/src/filters/cosmetic.rs b/src/filters/cosmetic.rs index a8d0501e..01ccd4ea 100644 --- a/src/filters/cosmetic.rs +++ b/src/filters/cosmetic.rs @@ -423,18 +423,81 @@ mod css_validation { #[cfg(feature="css-validation")] mod css_validation { //! Methods for validating CSS selectors and style rules extracted from cosmetic filter rules. - use cssparser::ParserInput; - use cssparser::Parser; - use selectors::parser::Selector; - - use std::fmt::{Display, Formatter, Error}; + use cssparser::{CowRcStr, ParserInput, Parser, ParseError, SourceLocation}; use core::fmt::{Write, Result as FmtResult}; + /// Checks whether the given string represents a valid CSS selector. + /// + /// For the majority of filters, this works by trivial regex matching. More complex filters are + /// assembled into a mock stylesheet which is then parsed using `cssparser` and validated. + /// + /// This function does not attempt to validate specific types of pseudoclasses, since the list + /// of valid ones is large and constantly evolving. However, it should still catch any kind of + /// comment escaping that would allow injection of `url()` styles. pub fn is_valid_css_selector(selector: &str) -> bool { - let mut pi = ParserInput::new(selector); + use once_cell::sync::Lazy; + use regex::Regex; + static RE_SIMPLE_SELECTOR: Lazy = Lazy::new(|| Regex::new(r"^[#.]?[A-Za-z_][\w-]*$").unwrap()); + + if RE_SIMPLE_SELECTOR.is_match(selector) { + return true; + } + + // Use `mock-stylesheet-marker` where uBO uses `color: red` since we have control over the + // parsing logic within the block. + let mock_stylesheet = format!("{}{{mock-stylesheet-marker}}", selector); + let mut pi = ParserInput::new(&mock_stylesheet); let mut parser = Parser::new(&mut pi); - let r = Selector::parse(&SelectorParseImpl, &mut parser); - r.is_ok() + let mut rule_list_parser = cssparser::RuleListParser::new_for_stylesheet(&mut parser, QualifiedRuleParserImpl); + + if let Some(first_rule) = rule_list_parser.next() { + match first_rule { + Ok(()) => (), + Err(_) => return false, + } + } else { + return false; + } + + let is_last_rule = rule_list_parser.next().is_none(); + + is_last_rule + } + + struct QualifiedRuleParserImpl; + + impl<'i> cssparser::QualifiedRuleParser<'i> for QualifiedRuleParserImpl { + type Prelude = (); + type QualifiedRule = (); + type Error = (); + + fn parse_prelude<'t>(&mut self, input: &mut Parser<'i, 't>) -> Result> { + selectors::SelectorList::parse(&SelectorParseImpl, input) + .map(|_| ()) + .map_err(|_| ParseError { kind: cssparser::ParseErrorKind::Custom(()), location: SourceLocation { line: 0, column: 0 } }) + } + + /// Check that the block is exactly equal to "mock-stylesheet-marker" + fn parse_block<'t>(&mut self, _prelude: Self::Prelude, _start: &cssparser::ParserState, input: &mut Parser<'i, 't>) -> Result> { + let err = Err(ParseError { kind: cssparser::ParseErrorKind::Custom(()), location: SourceLocation { line: 0, column: 0 } }); + match input.next() { + Ok(cssparser::Token::Ident(i)) if i.as_ref() == "mock-stylesheet-marker" => (), + _ => return err, + } + if input.next().is_ok() { + return err; + } + Ok(()) + } + } + + /// Default implementations for `AtRuleParser` parsing methods return false. This is + /// acceptable; at-rules should not be valid in cosmetic rules. + impl cssparser::AtRuleParser<'_> for QualifiedRuleParserImpl { + type PreludeNoBlock = (); + type PreludeBlock = (); + type AtRule = (); + type Error = (); } pub fn is_valid_css_style(style: &str) -> bool { @@ -455,6 +518,25 @@ mod css_validation { impl<'i> selectors::parser::Parser<'i> for SelectorParseImpl { type Impl = SelectorImpl; type Error = selectors::parser::SelectorParseErrorKind<'i>; + + fn parse_slotted(&self) -> bool { true } + fn parse_part(&self) -> bool { true } + fn parse_is_and_where(&self) -> bool { true } + fn parse_host(&self) -> bool { true } + fn parse_non_ts_pseudo_class(&self, _location: SourceLocation, _name: CowRcStr<'i>) -> Result<::NonTSPseudoClass, ParseError<'i, Self::Error>> { + Ok(NonTSPseudoClass) + } + fn parse_non_ts_functional_pseudo_class<'t>(&self, _name: CowRcStr<'i>, arguments: &mut Parser<'i, 't>) -> Result<::NonTSPseudoClass, ParseError<'i, Self::Error>> { + while arguments.next().is_ok() {} + Ok(NonTSPseudoClass) + } + fn parse_pseudo_element(&self, _location: SourceLocation, _name: CowRcStr<'i>) -> Result<::PseudoElement, ParseError<'i, Self::Error>> { + Ok(PseudoElement) + } + fn parse_functional_pseudo_element<'t>(&self, _name: CowRcStr<'i>, arguments: &mut Parser<'i, 't>) -> Result<::PseudoElement, ParseError<'i, Self::Error>> { + while arguments.next().is_ok() {} + Ok(PseudoElement) + } } /// The `selectors` library requires an object that implements `SelectorImpl` to store data @@ -468,23 +550,24 @@ mod css_validation { type ExtraMatchingData = (); type AttrValue = DummyValue; type Identifier = DummyValue; - type ClassName = DummyValue; - type LocalName = String; - type NamespaceUrl = String; + type LocalName = DummyValue; + type NamespaceUrl = DummyValue; type NamespacePrefix = DummyValue; - type BorrowedNamespaceUrl = String; - type BorrowedLocalName = String; + type BorrowedNamespaceUrl = DummyValue; + type BorrowedLocalName = DummyValue; type NonTSPseudoClass = NonTSPseudoClass; type PseudoElement = PseudoElement; } - /// For performance, individual fields of parsed selectors is discarded. Instead, they are + /// For performance, individual fields of parsed selectors are discarded. Instead, they are /// parsed into a `DummyValue` with no fields. #[derive(Debug, Clone, PartialEq, Eq, Default)] struct DummyValue; - impl Display for DummyValue { - fn fmt(&self, _: &mut Formatter) -> Result<(), Error> { Ok(()) } + impl cssparser::ToCss for DummyValue { + fn to_css(&self, _dest: &mut W) -> core::fmt::Result { + Ok(()) + } } impl<'a> From<&'a str> for DummyValue { @@ -498,6 +581,7 @@ mod css_validation { impl selectors::parser::NonTSPseudoClass for NonTSPseudoClass { type Impl = SelectorImpl; fn is_active_or_hover(&self) -> bool { false } + fn is_user_action_state(&self) -> bool { false } } impl cssparser::ToCss for NonTSPseudoClass { @@ -511,8 +595,6 @@ mod css_validation { impl selectors::parser::PseudoElement for PseudoElement { type Impl = SelectorImpl; - fn supports_pseudo_class(&self, _pseudo_class: &NonTSPseudoClass) -> bool { true } - fn valid_after_slotted(&self) -> bool { true } } @@ -523,12 +605,17 @@ mod css_validation { #[test] fn bad_selector_inputs() { assert!(!is_valid_css_selector(r#"rm -rf ./*"#)); - assert!(!is_valid_css_selector(r#"javascript:alert("hacked")"#)); + assert!(is_valid_css_selector(r#"javascript:alert("All pseudo-classes are valid")"#)); + assert!(!is_valid_css_selector(r#"javascript:alert("But opening comments are still forbidden" /*)"#)); assert!(!is_valid_css_selector(r#"This is not a CSS selector."#)); assert!(!is_valid_css_selector(r#"./malware.sh"#)); assert!(!is_valid_css_selector(r#"https://safesite.ru"#)); assert!(!is_valid_css_selector(r#"(function(){var e=60;return String.fromCharCode(e.charCodeAt(0))})();"#)); assert!(!is_valid_css_selector(r#"#!/usr/bin/sh"#)); + assert!(!is_valid_css_selector(r#"input,input/*"#)); + // Accept a closing comment within a string. It should still be impossible to create an + // opening comment to match it. + assert!(is_valid_css_selector(r#"input[x="*/{}*{background:url(https://hackvertor.co.uk/images/logo.gif)}"]"#)); } } diff --git a/src/lists.rs b/src/lists.rs index 9de78cdb..49d952cf 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -497,10 +497,24 @@ mod tests { #[test] fn parse_filter_failed_fuzz_4() { // \\##+js(,\xdd\x8d - assert!(parse_filter( + let parsed = parse_filter( &String::from_utf8(vec![92, 35, 35, 43, 106, 115, 40, 44, 221, 141]).unwrap(), true, Default::default(), - ).is_ok()); + ); + #[cfg(feature = "css-validation")] + assert!(parsed.is_err()); + #[cfg(not(feature = "css-validation"))] + assert!(parsed.is_ok()); + } + + #[test] + #[cfg(feature = "css-validation")] + fn parse_filter_opening_comment() { + assert!(parse_filter( + "##input,input/*", + true, + Default::default(), + ).is_err()); } }