]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
shared/calendarspec: fix formatting of entries which collapse to a star 23336/head
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 10 May 2022 09:35:52 +0000 (11:35 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 10 May 2022 12:35:57 +0000 (14:35 +0200)
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.

src/shared/calendarspec.c
src/test/test-calendarspec.c
test/fuzz/fuzz-calendarspec/crash-parse-star-non-star [new file with mode: 0644]

index 273a38f1fa419508fbf2cbe26c05eb7270ed2349..767c1b7856e11bfe4c644558923d2842bb640068 100644 (file)
@@ -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;
index 5508f8b8337ca9b2cda8e15507ef03cca816424e..8a0684ed669f2aae8a6f215af69c0c1c312177e0 100644 (file)
@@ -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 (file)
index 0000000..0c1edc2
--- /dev/null
@@ -0,0 +1 @@
+*:4,30:0/01,0
\ No newline at end of file