From 52f09a1e17b302144d00c17094f5beb69b12d67c Mon Sep 17 00:00:00 2001 From: Jimmy Tanagra Date: Thu, 9 Jan 2025 14:07:14 +1000 Subject: [PATCH] Prevent infinite loop in CronAdjuster with invalid date combinations Signed-off-by: Jimmy Tanagra --- .../java/org/openhab/core/scheduler/CronAdjuster.java | 7 +++++++ .../core/internal/scheduler/CronAdjusterTest.java | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/scheduler/CronAdjuster.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/scheduler/CronAdjuster.java index 1e938d2a1c0..15f25a717b8 100644 --- a/bundles/org.openhab.core/src/main/java/org/openhab/core/scheduler/CronAdjuster.java +++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/scheduler/CronAdjuster.java @@ -71,6 +71,7 @@ interface Checker { .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); private final List fields = new ArrayList<>(7); + private String cronExpression; private final Map environmentMap; private final boolean reboot; @@ -82,6 +83,7 @@ public CronAdjuster(final String specification) { environmentMap = parseEnvironment(entries); String cronExpression = entries[entries.length - 1].trim(); + this.cronExpression = cronExpression; reboot = "@reboot".equals(cronExpression); @@ -515,6 +517,7 @@ public Temporal adjustInto(@Nullable final Temporal temporal) { // we start over with this new time. int index = 0; + int restarts = 0; final int length = fields.size(); while (index < length) { @@ -525,6 +528,10 @@ public Temporal adjustInto(@Nullable final Temporal temporal) { if (out == null) { index++; } else { + if (restarts++ > 1000) { + throw new IllegalArgumentException( + String.format("Cron expression '%s' is not valid, too many restarts", cronExpression)); + } ret = out; index = 0; } diff --git a/bundles/org.openhab.core/src/test/java/org/openhab/core/internal/scheduler/CronAdjusterTest.java b/bundles/org.openhab.core/src/test/java/org/openhab/core/internal/scheduler/CronAdjusterTest.java index 3de418a00b5..0c3cbaa227a 100644 --- a/bundles/org.openhab.core/src/test/java/org/openhab/core/internal/scheduler/CronAdjusterTest.java +++ b/bundles/org.openhab.core/src/test/java/org/openhab/core/internal/scheduler/CronAdjusterTest.java @@ -14,6 +14,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; import java.time.LocalDateTime; import java.time.temporal.Temporal; @@ -25,6 +26,7 @@ import org.junit.jupiter.api.Timeout; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; import org.openhab.core.scheduler.CronAdjuster; /** @@ -197,4 +199,13 @@ public void testCronExpression(String in, String cron, String[] outs) { equalTo(out)); } } + + @ParameterizedTest + @ValueSource(strings = { "0 0 0 31 2 *", "* * *", "80 * * * * *" }) + public void testInvalidCronExpression(String cron) { + assertThrows(IllegalArgumentException.class, () -> { + final CronAdjuster cronAdjuster = new CronAdjuster(cron); + cronAdjuster.adjustInto(java.time.ZonedDateTime.now()); + }); + } }