Allow recursive define until limit

This commit is contained in:
dalance 2019-12-12 10:26:03 +09:00
parent 0919af22c9
commit bd4b28868a
4 changed files with 18 additions and 15 deletions

View File

@ -2,6 +2,8 @@
## [Unreleased](https://github.com/dalance/sv-parser/compare/v0.4.7...Unreleased) - ReleaseDate ## [Unreleased](https://github.com/dalance/sv-parser/compare/v0.4.7...Unreleased) - ReleaseDate
* [Fixed] allow recursive define until limit
## [v0.4.7](https://github.com/dalance/sv-parser/compare/v0.4.6...v0.4.7) - 2019-12-10 ## [v0.4.7](https://github.com/dalance/sv-parser/compare/v0.4.6...v0.4.7) - 2019-12-10
* [Added] recursive define detection * [Added] recursive define detection

View File

@ -24,8 +24,8 @@ pub enum ErrorKind {
DefineNotFound(String), DefineNotFound(String),
#[fail(display = "Define must have argument")] #[fail(display = "Define must have argument")]
DefineNoArgs, DefineNoArgs,
#[fail(display = "Recursive define is detected: {}", _0)] #[fail(display = "Exceed recursive limit")]
DefineRecursive(String), ExceedRecursiveLimit,
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@ -13,6 +13,8 @@ use sv_parser_syntaxtree::{
IncludeCompilerDirective, Locate, NodeEvent, RefNode, SourceDescription, TextMacroUsage, IncludeCompilerDirective, Locate, NodeEvent, RefNode, SourceDescription, TextMacroUsage,
}; };
const RECURSIVE_LIMIT: usize = 128;
#[derive(Debug)] #[derive(Debug)]
pub struct PreprocessedText { pub struct PreprocessedText {
text: String, text: String,
@ -124,7 +126,7 @@ pub fn preprocess<T: AsRef<Path>, U: AsRef<Path>>(
let mut s = String::new(); let mut s = String::new();
reader.read_to_string(&mut s)?; reader.read_to_string(&mut s)?;
preprocess_str(&s, path, pre_defines, include_paths, vec![]) preprocess_str(&s, path, pre_defines, include_paths, 0)
} }
pub fn preprocess_str<T: AsRef<Path>, U: AsRef<Path>>( pub fn preprocess_str<T: AsRef<Path>, U: AsRef<Path>>(
@ -132,7 +134,7 @@ pub fn preprocess_str<T: AsRef<Path>, U: AsRef<Path>>(
path: T, path: T,
pre_defines: &Defines, pre_defines: &Defines,
include_paths: &[U], include_paths: &[U],
resolved_defines: Vec<String>, resolve_depth: usize,
) -> Result<(PreprocessedText, Defines), Error> { ) -> Result<(PreprocessedText, Defines), Error> {
let mut skip = false; let mut skip = false;
let mut skip_nodes = vec![]; let mut skip_nodes = vec![];
@ -335,7 +337,7 @@ pub fn preprocess_str<T: AsRef<Path>, U: AsRef<Path>>(
path.as_ref(), path.as_ref(),
&defines, &defines,
include_paths, include_paths,
resolved_defines.clone(), resolve_depth + 1,
)? { )? {
let p = p.trim().trim_matches('"'); let p = p.trim().trim_matches('"');
PathBuf::from(p) PathBuf::from(p)
@ -367,7 +369,7 @@ pub fn preprocess_str<T: AsRef<Path>, U: AsRef<Path>>(
path.as_ref(), path.as_ref(),
&defines, &defines,
include_paths, include_paths,
resolved_defines.clone(), resolve_depth + 1,
)? { )? {
ret.push(&text, origin); ret.push(&text, origin);
defines = new_defines; defines = new_defines;
@ -444,15 +446,14 @@ fn resolve_text_macro_usage<T: AsRef<Path>, U: AsRef<Path>>(
path: T, path: T,
defines: &Defines, defines: &Defines,
include_paths: &[U], include_paths: &[U],
mut resolved_defines: Vec<String>, resolve_depth: usize,
) -> Result<Option<(String, Option<(PathBuf, Range)>, Defines)>, Error> { ) -> Result<Option<(String, Option<(PathBuf, Range)>, Defines)>, Error> {
let (_, ref name, ref args) = x.nodes; let (_, ref name, ref args) = x.nodes;
let id = identifier((&name.nodes.0).into(), &s).unwrap(); let id = identifier((&name.nodes.0).into(), &s).unwrap();
if resolved_defines.contains(&id) { if resolve_depth > RECURSIVE_LIMIT {
return Err(ErrorKind::DefineRecursive(id).into()); return Err(ErrorKind::ExceedRecursiveLimit.into());
} }
resolved_defines.push(id.clone());
let mut actual_args = Vec::new(); let mut actual_args = Vec::new();
let no_args = args.is_none(); let no_args = args.is_none();
@ -526,7 +527,7 @@ fn resolve_text_macro_usage<T: AsRef<Path>, U: AsRef<Path>>(
path.as_ref(), path.as_ref(),
&defines, &defines,
include_paths, include_paths,
resolved_defines, resolve_depth,
)?; )?;
Ok(Some(( Ok(Some((
String::from(replaced.text()), String::from(replaced.text()),
@ -709,7 +710,7 @@ endmodule
let ret = preprocess(get_testcase("test7.sv"), &HashMap::new(), &[] as &[String]); let ret = preprocess(get_testcase("test7.sv"), &HashMap::new(), &[] as &[String]);
assert_eq!( assert_eq!(
format!("{:?}", ret), format!("{:?}", ret),
"Err(Error { inner: \n\nRecursive define is detected: a })" "Err(Error { inner: \n\nExceed recursive limit })"
); );
} }
@ -718,7 +719,7 @@ endmodule
let ret = preprocess(get_testcase("test8.sv"), &HashMap::new(), &[] as &[String]); let ret = preprocess(get_testcase("test8.sv"), &HashMap::new(), &[] as &[String]);
assert_eq!( assert_eq!(
format!("{:?}", ret), format!("{:?}", ret),
"Err(Error { inner: \n\nRecursive define is detected: b })" "Err(Error { inner: \n\nExceed recursive limit })"
); );
} }
} }

View File

@ -130,7 +130,7 @@ pub fn parse_sv_str<T: AsRef<Path>, U: AsRef<Path>>(
pre_defines: &HashMap<String, Option<Define>>, pre_defines: &HashMap<String, Option<Define>>,
include_paths: &[U], include_paths: &[U],
) -> Result<(SyntaxTree, Defines), Error> { ) -> Result<(SyntaxTree, Defines), Error> {
let (text, defines) = preprocess_str(s, path, pre_defines, include_paths, vec![])?; let (text, defines) = preprocess_str(s, path, pre_defines, include_paths, 0)?;
let span = Span::new_extra(text.text(), SpanInfo::default()); let span = Span::new_extra(text.text(), SpanInfo::default());
let result = all_consuming(sv_parser)(span); let result = all_consuming(sv_parser)(span);
match result { match result {
@ -203,7 +203,7 @@ pub fn parse_lib_str<T: AsRef<Path>, U: AsRef<Path>>(
pre_defines: &HashMap<String, Option<Define>>, pre_defines: &HashMap<String, Option<Define>>,
include_paths: &[U], include_paths: &[U],
) -> Result<(SyntaxTree, Defines), Error> { ) -> Result<(SyntaxTree, Defines), Error> {
let (text, defines) = preprocess_str(s, path, pre_defines, include_paths, vec![])?; let (text, defines) = preprocess_str(s, path, pre_defines, include_paths, 0)?;
let span = Span::new_extra(text.text(), SpanInfo::default()); let span = Span::new_extra(text.text(), SpanInfo::default());
let result = all_consuming(lib_parser)(span); let result = all_consuming(lib_parser)(span);
match result { match result {