summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2022-05-10 11:35:52 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2022-05-10 14:35:57 +0200
commit8e1e59b9ade5b737e24a76bae1944ce84acf564c (patch)
treeaa76a985e1f6c9a74e43b6e295a95c9d1a47d900
parent3aff2ae9d5427498f673bcb086d3439d2047e6c9 (diff)
downloadsystemd-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.c27
-rw-r--r--src/test/test-calendarspec.c1
-rw-r--r--test/fuzz/fuzz-calendarspec/crash-parse-star-non-star1
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