fix: a URL rule's address is capped at 2048 bytes (WR-23)

Rule.Problems had no length check, so a long address reached the
(url, match) UNIQUE btree index and failed with a 500. It now refuses an
address over models.MaxRuleURL with rules.url_invalid, like redirect
sources.
This commit is contained in:
2026-10-27 15:41:55 +01:00
parent 7677d8d8af
commit 4ca26e9a89
2 changed files with 20 additions and 4 deletions

View File

@@ -96,14 +96,20 @@ func NormalizeMatch(m string) string {
return MatchExact
}
// Problems refuses an address that does not start with "/" or carries * in
// an exact rule, and an address and match another rule already has (db is
// the save transaction; nil skips the uniqueness check).
// MaxRuleURL caps a URL rule's address in bytes, like MaxRedirectURL: the
// (url, match) UNIQUE btree index refuses rows over about 2.7 KB with a
// database error (WR-23).
const MaxRuleURL = 2048
// Problems refuses an address that does not start with "/", is longer than
// MaxRuleURL or carries * in an exact rule, and an address and match
// another rule already has (db is the save transaction; nil skips the
// uniqueness check).
func (r Rule) Problems(db *gorm.DB) map[string][]Problem {
out := map[string][]Problem{}
url := strings.TrimSpace(r.URL)
match := NormalizeMatch(r.Match)
if !strings.HasPrefix(url, "/") || strings.HasPrefix(url, "//") || strings.ContainsAny(url, " \t\r\n") || (match == MatchExact && strings.Contains(url, "*")) {
if len(url) > MaxRuleURL || !strings.HasPrefix(url, "/") || strings.HasPrefix(url, "//") || strings.ContainsAny(url, " \t\r\n") || (match == MatchExact && strings.Contains(url, "*")) {
out["url"] = []Problem{{Key: errRuleURLInvalid}}
return out
}