mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-09-19 09:40:12 +00:00
fix(alert): prevent divide-by-zero panic and unbounded growth on zero-duration rule
A general alert rule with Duration:0 (accepted by the API, no minimum validation) drove fail*100/total with total==0, panicking with an integer divide-by-zero inside checkStatus, which has no recover and would take down the whole alert goroutine — a config-reachable DoS by any user able to create alert rules. Skip duration<=0 rules in Check via continue (not boundCheck, which would pollute hasPassedRule and skip sibling valid rules). Also trim the sample slice when max<=0 in alertsentinel, otherwise it appended every tick without ever trimming. Adds regression tests for zero-only and mixed rule sets.
This commit is contained in:
@@ -184,10 +184,15 @@ func checkStatus() {
|
||||
}
|
||||
alertsPrevState[alert.ID][server.ID] = _RuleCheckPass
|
||||
}
|
||||
// 清理旧数据
|
||||
if max > 0 && max < len(alertsStore[alert.ID][server.ID]) {
|
||||
index := len(alertsStore[alert.ID][server.ID]) - max
|
||||
alertsStore[alert.ID][server.ID] = alertsStore[alert.ID][server.ID][index:]
|
||||
// 清理旧数据:只需保留最近 max 个采样点(各规则 Duration 的最大值)。
|
||||
// max==0 表示该 alert 没有任何有效规则会回看历史(例如全部
|
||||
// Duration<=0 被跳过),此时历史采样无用,必须清空——否则每个
|
||||
// tick 都 append 而永不裁剪,切片会无限增长成内存泄漏。
|
||||
samples := alertsStore[alert.ID][server.ID]
|
||||
if max <= 0 {
|
||||
alertsStore[alert.ID][server.ID] = samples[:0]
|
||||
} else if max < len(samples) {
|
||||
alertsStore[alert.ID][server.ID] = samples[len(samples)-max:]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user