From 7a314d18f726b36b64221274ceb1f3b3b1849404 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Sat, 16 May 2020 13:13:50 +0200 Subject: [PATCH] src/tools/systemd/parse_time.rs: check max values --- src/tools/systemd/parse_time.rs | 54 +++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/src/tools/systemd/parse_time.rs b/src/tools/systemd/parse_time.rs index deab31fd..a9f07467 100644 --- a/src/tools/systemd/parse_time.rs +++ b/src/tools/systemd/parse_time.rs @@ -18,7 +18,7 @@ type IResult> = Result<(I, O), nom::Err>; fn parse_error<'a>(i: &'a str, context: &'static str) -> nom::Err> { let err = VerboseError { errors: Vec::new() }; - let err =VerboseError::add_context(i, context, err); + let err = VerboseError::add_context(i, context, err); nom::Err::Error(err) } @@ -90,8 +90,14 @@ lazy_static! { map }; } -fn parse_u32(i: &str) -> IResult<&str, u32> { - map_res(recognize(digit1), str::parse)(i) +fn parse_time_comp(max: usize) -> impl Fn(&str) -> IResult<&str, u32> { + move |i: &str| { + let (i, v) = map_res(recognize(digit1), str::parse)(i)?; + if (v as usize) >= max { + return Err(parse_error(i, "time value too large")); + } + Ok((i, v)) + } } fn parse_u64(i: &str) -> IResult<&str, u64> { @@ -142,38 +148,40 @@ fn parse_weekdays_range(i: &str) -> IResult<&str, WeekDays> { } } -fn parse_date_time_comp(i: &str) -> IResult<&str, DateTimeValue> { +fn parse_date_time_comp(max: usize) -> impl Fn(&str) -> IResult<&str, DateTimeValue> { + move |i: &str| { + let (i, value) = parse_time_comp(max)(i)?; - let (i, value) = parse_u32(i)?; + if let (i, Some(end)) = opt(preceded(tag(".."), parse_time_comp(max)))(i)? { + return Ok((i, DateTimeValue::Range(value, end))) + } - if let (i, Some(end)) = opt(preceded(tag(".."), parse_u32))(i)? { - return Ok((i, DateTimeValue::Range(value, end))) - } - - if i.starts_with("/") { - let i = &i[1..]; - let (i, repeat) = parse_u32(i)?; - Ok((i, DateTimeValue::Repeated(value, repeat))) - } else { - Ok((i, DateTimeValue::Single(value))) + if i.starts_with("/") { + let i = &i[1..]; + let (i, repeat) = parse_time_comp(max)(i)?; + Ok((i, DateTimeValue::Repeated(value, repeat))) + } else { + Ok((i, DateTimeValue::Single(value))) + } } } -fn parse_date_time_comp_list(i: &str) -> IResult<&str, Vec> { +fn parse_date_time_comp_list(max: usize) -> impl Fn(&str) -> IResult<&str, Vec> { + move |i: &str| { + if i.starts_with("*") { + return Ok((&i[1..], Vec::new())); + } - if i.starts_with("*") { - return Ok((&i[1..], Vec::new())); + separated_nonempty_list(tag(","), parse_date_time_comp(max))(i) } - - separated_nonempty_list(tag(","), parse_date_time_comp)(i) } fn parse_time_spec(i: &str) -> IResult<&str, (Vec, Vec, Vec)> { let (i, (hour, minute, opt_second)) = tuple(( - parse_date_time_comp_list, - preceded(tag(":"), parse_date_time_comp_list), - opt(preceded(tag(":"), parse_date_time_comp_list)), + parse_date_time_comp_list(24), + preceded(tag(":"), parse_date_time_comp_list(60)), + opt(preceded(tag(":"), parse_date_time_comp_list(60))), ))(i)?; if let Some(second) = opt_second {