mirror of
https://github.com/v2fly/domain-list-community.git
synced 2026-08-27 05:30:17 +03:00
Fix: reject malformed domain rules (#3917)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Loyalsoldier <10487845+Loyalsoldier@users.noreply.github.com>
This commit is contained in:
parent
21f09bcdba
commit
e449533a4a
@ -83,7 +83,7 @@ func exportSite(name string, gs *GeoSites) error {
|
||||
}
|
||||
defer file.Close()
|
||||
w := bufio.NewWriter(file)
|
||||
fmt.Fprintf(w, "%s:\n", name)
|
||||
fmt.Fprintf(w, "%q:\n", name)
|
||||
var b strings.Builder
|
||||
b.Grow(64)
|
||||
for _, vdomain := range vDomains {
|
||||
|
||||
27
main.go
27
main.go
@ -66,6 +66,9 @@ const (
|
||||
ModeAll string = "all"
|
||||
ModeAllowlist string = "allowlist"
|
||||
ModeDenylist string = "denylist"
|
||||
|
||||
maxDomainLen int = 253 // Maximum length of a domain name
|
||||
maxLabelLen int = 63 // Maximum length of a label of a domain name
|
||||
)
|
||||
|
||||
func makeProtoList(listName string, entries []*Entry) *router.GeoSite {
|
||||
@ -208,10 +211,15 @@ func parseEntry(typ, rule string) (*Entry, []string, error) {
|
||||
return entry, nil, fmt.Errorf("invalid regexp %q: %w", parts[0], err)
|
||||
}
|
||||
entry.Value = parts[0]
|
||||
case dlc.RuleTypeDomain, dlc.RuleTypeFullDomain, dlc.RuleTypeKeyword:
|
||||
case dlc.RuleTypeDomain, dlc.RuleTypeFullDomain:
|
||||
entry.Value = strings.ToLower(parts[0])
|
||||
if !validateDomainName(entry.Value) {
|
||||
return entry, nil, fmt.Errorf("invalid domain: %q", entry.Value)
|
||||
}
|
||||
case dlc.RuleTypeKeyword:
|
||||
entry.Value = strings.ToLower(parts[0])
|
||||
if !validateDomainChars(entry.Value) {
|
||||
return entry, nil, fmt.Errorf("invalid domain: %q", entry.Value)
|
||||
return entry, nil, fmt.Errorf("invalid keyword: %q", entry.Value)
|
||||
}
|
||||
default:
|
||||
return entry, nil, fmt.Errorf("unknown rule type: %q", entry.Type)
|
||||
@ -310,6 +318,21 @@ func validateDomainChars(domain string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// validateDomainName reports whether the domain is a valid domain name, so that
|
||||
// typos like "example..com" or "-example.com" would not be silently built into
|
||||
// rules which can never match any domain.
|
||||
func validateDomainName(domain string) bool {
|
||||
if !validateDomainChars(domain) || len(domain) > maxDomainLen {
|
||||
return false
|
||||
}
|
||||
for label := range strings.SplitSeq(domain, ".") {
|
||||
if label == "" || len(label) > maxLabelLen || label[0] == '-' || label[len(label)-1] == '-' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func validateAttrChars(attr string) bool {
|
||||
if attr == "" {
|
||||
return false
|
||||
|
||||
@ -22,10 +22,19 @@ func TestParseEntry(t *testing.T) {
|
||||
{name: "duplicated attrs", typ: "domain", rule: "example.com @ads @ads", wantPlain: "domain:example.com:@ads"},
|
||||
{name: "affiliations", typ: "domain", rule: "example.com &other @ads", wantPlain: "domain:example.com:@ads", wantAffs: []string{"OTHER"}},
|
||||
{name: "regexp", typ: "regexp", rule: `^example\.com$`, wantPlain: `regexp:^example\.com$`},
|
||||
{name: "tld", typ: "domain", rule: "google", wantPlain: "domain:google"},
|
||||
{name: "hyphen inside", typ: "domain", rule: "my-example.com", wantPlain: "domain:my-example.com"},
|
||||
{name: "keyword allows partial", typ: "keyword", rule: "-ads-", wantPlain: "keyword:-ads-"},
|
||||
{name: "invalid regexp", typ: "regexp", rule: "^example(", wantErr: true},
|
||||
{name: "empty rule", typ: "domain", rule: " ", wantErr: true},
|
||||
{name: "unknown type", typ: "prefix", rule: "example.com", wantErr: true},
|
||||
{name: "invalid domain", typ: "domain", rule: "exa_mple.com @ads", wantErr: true},
|
||||
{name: "empty label", typ: "domain", rule: "example..com", wantErr: true},
|
||||
{name: "trailing dot", typ: "full", rule: "example.com.", wantErr: true},
|
||||
{name: "leading dot", typ: "domain", rule: ".example.com", wantErr: true},
|
||||
{name: "leading hyphen", typ: "domain", rule: "-example.com", wantErr: true},
|
||||
{name: "trailing hyphen", typ: "full", rule: "example-.com", wantErr: true},
|
||||
{name: "overlong label", typ: "domain", rule: strings.Repeat("a", 64) + ".com", wantErr: true},
|
||||
{name: "empty attr", typ: "domain", rule: "example.com @", wantErr: true},
|
||||
{name: "empty affiliation", typ: "domain", rule: "example.com &", wantErr: true},
|
||||
{name: "unknown field", typ: "domain", rule: "example.com ads", wantErr: true},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user