Skip to content
This repository has been archived by the owner on Aug 31, 2023. It is now read-only.

Commit

Permalink
fixing parser marker bombs for some js libs (#1817)
Browse files Browse the repository at this point in the history
* fixing parser marker bombs
  • Loading branch information
xunilrj committed Nov 25, 2021
1 parent 85bd366 commit cbbdd0e
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 17 deletions.
32 changes: 32 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

60 changes: 49 additions & 11 deletions crates/rslint_parser/src/syntax/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ macro_rules! no_recover {
return None;
}
};
($p:expr, $m:expr, $t:expr, $res:expr) => {
if $res.is_none() && $p.state.no_recovery {
$m.abandon($p);
$p.rewind($t);
return None;
}
};
}

pub(crate) fn abstract_readonly_modifiers(
Expand Down Expand Up @@ -245,16 +252,26 @@ pub(crate) fn ts_decl(p: &mut Parser) -> Option<CompletedMarker> {
}

pub fn ts_type_alias_decl(p: &mut Parser) -> Option<CompletedMarker> {
let t = p.checkpoint();

let m = p.start();
let start = p.cur_tok().range.start;
p.bump_any();
no_recover!(p, identifier_name(p));
no_recover!(p, m, t, identifier_name(p));
if p.at(T![<]) {
no_recover!(p, ts_type_params(p));
}

let end = p.cur_tok().range.end;
p.expect_no_recover(T![=])?;
no_recover!(p, ts_type(p));

if p.expect_no_recover(T![=]).is_none() {
m.abandon(p);
p.rewind(t);
return None;
}

no_recover!(p, m, t, ts_type(p));

semi(p, start..end);
Some(m.complete(p, TS_TYPE_ALIAS_DECL))
}
Expand Down Expand Up @@ -860,6 +877,8 @@ pub fn ts_type_operator_or_higher(p: &mut Parser) -> Option<CompletedMarker> {
}

pub fn ts_array_type_or_higher(p: &mut Parser) -> Option<CompletedMarker> {
let t = p.checkpoint();

let mut ty = ts_non_array_type(p);

while !p.has_linebreak_before_n(0) && p.at(T!['[']) {
Expand All @@ -868,8 +887,12 @@ pub fn ts_array_type_or_higher(p: &mut Parser) -> Option<CompletedMarker> {
if p.eat(T![']']) {
ty = Some(m.complete(p, TS_ARRAY));
} else {
no_recover!(p, ts_type(p));
p.expect_no_recover(T![']'])?;
no_recover!(p, m, t, ts_type(p));
if p.expect_no_recover(T![']']).is_none() {
m.abandon(p);
p.rewind(t);
return None;
}
ty = Some(m.complete(p, TS_INDEXED_ARRAY));
}
}
Expand Down Expand Up @@ -985,14 +1008,17 @@ pub fn ts_non_array_type(p: &mut Parser) -> Option<CompletedMarker> {
Some(m.complete(p, TS_TEMPLATE))
}
T![-] => {
let t = p.checkpoint();
let m = p.start();
p.bump_any();
if p.at(JS_NUMBER_LITERAL) {
let _m = p.start();
p.bump_any();
_m.complete(p, JS_NUMBER_LITERAL_EXPRESSION);
} else {
p.expect_no_recover(JS_NUMBER_LITERAL)?;
} else if p.expect_no_recover(JS_NUMBER_LITERAL).is_none() {
m.abandon(p);
p.rewind(t);
return None;
}
Some(m.complete(p, TS_LITERAL))
}
Expand Down Expand Up @@ -1025,10 +1051,15 @@ pub fn ts_non_array_type(p: &mut Parser) -> Option<CompletedMarker> {
}
T!['['] => ts_tuple(p),
T!['('] => {
let t = p.checkpoint();
let m = p.start();
p.bump_any();
no_recover!(p, ts_type(p));
p.expect_no_recover(T![')'])?;
no_recover!(p, m, t, ts_type(p));
if p.expect_no_recover(T![')']).is_none() {
m.abandon(p);
p.rewind(t);
return None;
};
Some(m.complete(p, TS_PAREN))
}
_ => {
Expand Down Expand Up @@ -1345,6 +1376,8 @@ pub fn ts_type_ref(
p: &mut Parser,
recovery_set: impl Into<Option<TokenSet>> + Clone,
) -> Option<CompletedMarker> {
let t = p.checkpoint();

let m = p.start();
if let Some(err_m) = maybe_eat_incorrect_modifier(p) {
let err = p
Expand All @@ -1354,9 +1387,14 @@ pub fn ts_type_ref(
p.error(err);
}

ts_entity_name(p, recovery_set, true)?;
if ts_entity_name(p, recovery_set, true).is_none() {
m.abandon(p);
p.rewind(t);
return None;
}

if !p.has_linebreak_before_n(0) && p.at(T![<]) {
no_recover!(p, ts_type_args(p));
no_recover!(p, m, t, ts_type_args(p));
}

Some(m.complete(p, TS_TYPE_REF))
Expand Down
4 changes: 3 additions & 1 deletion xtask/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,6 @@ yastl = "0.1"
num_cpus = "1.13"
ungrammar = "1.14.9"
ureq = { version = "2.3.1" }
url = "2.2.2"
url = "2.2.2"
timing = "0.2.3"
ansi_rgb = "0.2.0"
10 changes: 9 additions & 1 deletion xtask/src/libs/libs.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
https://cdn.jsdelivr.net/npm/jquery@3.2.1/dist/jquery.min.js
https://cdn.jsdelivr.net/npm/vue@3.2.22/dist/vue.global.prod.js
https://cdn.jsdelivr.net/npm/vue@3.2.22/dist/vue.global.prod.js
https://cdn.jsdelivr.net/npm/react@17.0.2/cjs/react.production.min.js
https://cdn.jsdelivr.net/npm/react-dom@17.0.2/cjs/react-dom.production.min.js
https://cdn.jsdelivr.net/npm/svelte@3.44.2/compiler.js
https://cdn.jsdelivr.net/npm/dojo@1.16.4/dojo.js
https://cdn.jsdelivr.net/npm/d3@7.1.1/dist/d3.min.js
https://cdn.jsdelivr.net/npm/pixi.js@6.2.0/dist/browser/pixi.min.js
https://cdn.jsdelivr.net/npm/three@0.134.0/build/three.min.js
https://cdn.jsdelivr.net/npm/mathjax@3.2.0/es5/tex-chtml-full.js
43 changes: 40 additions & 3 deletions xtask/src/libs/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use ansi_rgb::{red, Foreground};
use std::{path::PathBuf, str::FromStr};

fn err_to_string<E: std::fmt::Debug>(e: E) -> String {
Expand All @@ -18,7 +19,7 @@ pub fn get_code(lib: &str) -> Result<String, String> {

match std::fs::read_to_string(&file) {
Ok(code) => {
println!("[{}] - using [{}]", filename, file.display());
println!("[{}] - using [{}]", filename.fg(red()), file.display());
Ok(code)
}
Err(_) => {
Expand All @@ -44,13 +45,49 @@ pub fn get_code(lib: &str) -> Result<String, String> {
}
}

pub fn run() {
pub fn run(filter: String) {
let regex = regex::Regex::new(filter.as_str()).unwrap();
let libs = include_str!("libs.txt").lines();
for lib in libs {
if !regex.is_match(lib) {
continue;
}

let code = get_code(lib);
match code {
Ok(code) => {
let _ = std::panic::catch_unwind(|| rslint_parser::parse_module(code.as_str(), 0));
let t = timing::start();
let _ = std::panic::catch_unwind(|| {
let text = code;

let tokenizer_timing = timing::start();
let (tokens, mut errors) = rslint_parser::tokenize(text.as_str(), 0);
let tok_source = rslint_parser::TokenSource::new(text.as_str(), &tokens);
println!("\ttokenizer took {:?}", tokenizer_timing.stop());

let parser_timing = timing::start();
let (events, errors, tokens) = {
let mut parser = rslint_parser::Parser::new(
tok_source,
0,
rslint_parser::Syntax::default().module(),
);
rslint_parser::syntax::program::parse(&mut parser);
let (events, p_errs) = parser.finish();
errors.extend(p_errs);
(events, errors, tokens)
};
println!("\tparser took {:?}", parser_timing.stop());

let treesink_timing = timing::start();
let mut tree_sink =
rslint_parser::LosslessTreeSink::new(text.as_str(), &tokens);
rslint_parser::process(&mut tree_sink, events, errors);
let (_green, _parse_errors) = tree_sink.finish();
println!("\ttree sink took {:?}", treesink_timing.stop());
});
let dur = t.stop();
println!("total: {:?}", dur);
}
Err(e) => println!("{:?}", e),
}
Expand Down
6 changes: 5 additions & 1 deletion xtask/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ fn main() -> Result<()> {
Ok(())
}
"coverage-libs" => {
xtask::libs::run();
let filter: String = args
.opt_value_from_str("--filter")
.unwrap()
.unwrap_or_else(|| ".*".to_string());
xtask::libs::run(filter);
Ok(())
}
_ => {
Expand Down

0 comments on commit cbbdd0e

Please sign in to comment.