diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2022-05-10 11:35:52 +0200 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2022-05-10 14:35:57 +0200 |
commit | 8e1e59b9ade5b737e24a76bae1944ce84acf564c (patch) | |
tree | aa76a985e1f6c9a74e43b6e295a95c9d1a47d900 | |
parent | 3aff2ae9d5427498f673bcb086d3439d2047e6c9 (diff) | |
download | systemd-8e1e59b9ade5b737e24a76bae1944ce84acf564c.tar.gz |
shared/calendarspec: fix formatting of entries which collapse to a star
We canonicalize repeats that cover the whole range: "0:0:0/1" → "0:0:*". But
we'd also do "0:0:0/1,0" → "0:0:*,0", which we then refuse to parse. Thus,
first go throug the whole chain, and print a '*' and nothing else if any of the
components covers the whole range.
-rw-r--r-- | src/shared/calendarspec.c | 27 | ||||
-rw-r--r-- | src/test/test-calendarspec.c | 1 | ||||
-rw-r--r-- | test/fuzz/fuzz-calendarspec/crash-parse-star-non-star | 1 |
3 files changed, 21 insertions, 8 deletions
diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c index 273a38f1fa..767c1b7856 100644 --- a/src/shared/calendarspec.c +++ b/src/shared/calendarspec.c @@ -288,17 +288,24 @@ static void format_weekdays(FILE *f, const CalendarSpec *c) { } } -static void format_chain(FILE *f, int space, const CalendarComponent *c, bool usec) { +static bool chain_is_star(const CalendarComponent *c, bool usec) { + /* Return true if the whole chain can be replaced by '*'. + * This happens when the chain is empty or one of the components covers all. */ + if (!c) + return true; + if (usec) + for (; c; c = c->next) + if (c->start == 0 && c->stop < 0 && c->repeat == USEC_PER_SEC) + return true; + return false; +} + +static void _format_chain(FILE *f, int space, const CalendarComponent *c, bool start, bool usec) { int d = usec ? (int) USEC_PER_SEC : 1; assert(f); - if (!c) { - fputc('*', f); - return; - } - - if (usec && c->start == 0 && c->stop < 0 && c->repeat == USEC_PER_SEC && !c->next) { + if (start && chain_is_star(c, usec)) { fputc('*', f); return; } @@ -321,10 +328,14 @@ static void format_chain(FILE *f, int space, const CalendarComponent *c, bool us if (c->next) { fputc(',', f); - format_chain(f, space, c->next, usec); + _format_chain(f, space, c->next, false, usec); } } +static void format_chain(FILE *f, int space, const CalendarComponent *c, bool usec) { + _format_chain(f, space, c, /* start = */ true, usec); +} + int calendar_spec_to_string(const CalendarSpec *c, char **p) { char *buf = NULL; size_t sz = 0; diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c index 5508f8b833..8a0684ed66 100644 --- a/src/test/test-calendarspec.c +++ b/src/test/test-calendarspec.c @@ -164,6 +164,7 @@ TEST(calendar_spec_one) { test_one("00:00:01/2,02..03", "*-*-* 00:00:01/2,02..03"); test_one("*:4,30:0..3", "*-*-* *:04,30:00..03"); test_one("*:4,30:0/1", "*-*-* *:04,30:*"); + test_one("*:4,30:0/1,3,5", "*-*-* *:04,30:*"); test_one("*-*~1 Utc", "*-*~01 00:00:00 UTC"); test_one("*-*~05,3 ", "*-*~03,05 00:00:00"); test_one("*-*~* 00:00:00", "*-*-* 00:00:00"); diff --git a/test/fuzz/fuzz-calendarspec/crash-parse-star-non-star b/test/fuzz/fuzz-calendarspec/crash-parse-star-non-star new file mode 100644 index 0000000000..0c1edc2ce9 --- /dev/null +++ b/test/fuzz/fuzz-calendarspec/crash-parse-star-non-star @@ -0,0 +1 @@ +*:4,30:0/01,0
\ No newline at end of file |