This is an automated email from the ASF dual-hosted git repository.

lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git


The following commit(s) were added to refs/heads/rocketmq-studio by this push:
     new 39d705248 fix(alert): reject overflowing rule durations (#2649)
39d705248 is described below

commit 39d705248babea4c86ef1e365f56d8bd8a482577
Author: btlqql <[email protected]>
AuthorDate: Wed Sep 2 17:06:30 2026 +0800

    fix(alert): reject overflowing rule durations (#2649)
---
 .../studio/ops/alert/AlertRuleDuration.java        | 34 ++++++++++++----------
 .../studio/ops/alert/NativeAlertRulePolicy.java    |  2 ++
 .../studio/ops/alert/AlertRuleDurationTest.java    | 12 ++++++++
 .../ops/alert/NativeAlertRulePolicyTest.java       | 10 +++++++
 4 files changed, 43 insertions(+), 15 deletions(-)

diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/ops/alert/AlertRuleDuration.java
 
b/server/src/main/java/org/apache/rocketmq/studio/ops/alert/AlertRuleDuration.java
index fa67e1b43..dbacfbb90 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/ops/alert/AlertRuleDuration.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/ops/alert/AlertRuleDuration.java
@@ -24,26 +24,30 @@ final class AlertRuleDuration {
         if (!StringUtils.hasText(value)) {
             return Duration.ZERO;
         }
-        Matcher matcher = PART.matcher(value.trim());
-        Duration result = Duration.ZERO;
-        int end = 0;
-        while (matcher.find()) {
-            if (matcher.start() != end) {
-                throw invalid(value);
+        try {
+            Matcher matcher = PART.matcher(value.trim());
+            Duration result = Duration.ZERO;
+            int end = 0;
+            while (matcher.find()) {
+                if (matcher.start() != end) {
+                    throw invalid(value);
+                }
+                long amount;
+                try {
+                    amount = Long.parseLong(matcher.group(1));
+                } catch (NumberFormatException error) {
+                    throw invalid(value);
+                }
+                result = result.plus(toDuration(amount, matcher.group(2), 
value));
+                end = matcher.end();
             }
-            long amount;
-            try {
-                amount = Long.parseLong(matcher.group(1));
-            } catch (NumberFormatException error) {
+            if (end != value.trim().length()) {
                 throw invalid(value);
             }
-            result = result.plus(toDuration(amount, matcher.group(2), value));
-            end = matcher.end();
-        }
-        if (end != value.trim().length()) {
+            return result;
+        } catch (ArithmeticException error) {
             throw invalid(value);
         }
-        return result;
     }
 
     private static BusinessException invalid(String value) {
diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/ops/alert/NativeAlertRulePolicy.java
 
b/server/src/main/java/org/apache/rocketmq/studio/ops/alert/NativeAlertRulePolicy.java
index 18d75d261..84aee5fe0 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/ops/alert/NativeAlertRulePolicy.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/ops/alert/NativeAlertRulePolicy.java
@@ -74,6 +74,8 @@ final class NativeAlertRulePolicy {
         if (StringUtils.hasText(rule.getTopic()) && 
!TOPIC_SCOPED_METRICS.contains(rule.getMetric())) {
             throw new BusinessException(400, "topic is not supported for 
metric " + rule.getMetric());
         }
+        AlertRuleDuration.parse(rule.getDuration());
+        AlertRuleDuration.parse(rule.getReminderInterval());
         if (rule.getConsecutiveSamples() < 1) {
             throw new BusinessException(400, "consecutiveSamples must be at 
least 1");
         }
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/ops/alert/AlertRuleDurationTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/ops/alert/AlertRuleDurationTest.java
index a22233149..463a93729 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/ops/alert/AlertRuleDurationTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/ops/alert/AlertRuleDurationTest.java
@@ -6,11 +6,13 @@
  */
 package org.apache.rocketmq.studio.ops.alert;
 
+import org.apache.rocketmq.studio.common.exception.BusinessException;
 import org.junit.jupiter.api.Test;
 
 import java.time.Duration;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 class AlertRuleDurationTest {
     @Test
@@ -18,4 +20,14 @@ class AlertRuleDurationTest {
         
assertThat(AlertRuleDuration.parse("1h30m")).isEqualTo(Duration.ofMinutes(90));
         assertThat(AlertRuleDuration.parse(null)).isEqualTo(Duration.ZERO);
     }
+
+    @Test
+    void rejectsDurationsThatOverflowTest() {
+        assertThatThrownBy(() -> 
AlertRuleDuration.parse("9223372036854775807y"))
+                .isInstanceOf(BusinessException.class)
+                .hasMessageContaining("Invalid alert duration");
+        assertThatThrownBy(() -> 
AlertRuleDuration.parse("9223372036854775807s9223372036854775807s"))
+                .isInstanceOf(BusinessException.class)
+                .hasMessageContaining("Invalid alert duration");
+    }
 }
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/ops/alert/NativeAlertRulePolicyTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/ops/alert/NativeAlertRulePolicyTest.java
index 88e0c3c79..a2de0f1f2 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/ops/alert/NativeAlertRulePolicyTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/ops/alert/NativeAlertRulePolicyTest.java
@@ -107,6 +107,16 @@ class NativeAlertRulePolicyTest {
         }
     }
 
+    @Test
+    void rejectsOverflowingNativeRuleDurationsBeforePersistenceTest() {
+        assertThatThrownBy(() -> 
NativeAlertRulePolicy.validate(rule(AlertDomain.CLUSTER, "broker.availability")
+                .instanceId("local").duration("9223372036854775807y").build()))
+                
.isInstanceOf(BusinessException.class).hasMessageContaining("Invalid alert 
duration");
+        assertThatThrownBy(() -> 
NativeAlertRulePolicy.validate(rule(AlertDomain.CLUSTER, "broker.availability")
+                
.instanceId("local").reminderInterval("9223372036854775807y").build()))
+                
.isInstanceOf(BusinessException.class).hasMessageContaining("Invalid alert 
duration");
+    }
+
     private static AlertRuleVO.AlertRuleVOBuilder rule(AlertDomain domain, 
String metric) {
         return AlertRuleVO.builder().domain(domain).name("Test 
rule").metric(metric).consecutiveSamples(1);
     }

Reply via email to