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()
|
defer file.Close()
|
||||||
w := bufio.NewWriter(file)
|
w := bufio.NewWriter(file)
|
||||||
fmt.Fprintf(w, "%s:\n", name)
|
fmt.Fprintf(w, "%q:\n", name)
|
||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
b.Grow(64)
|
b.Grow(64)
|
||||||
for _, vdomain := range vDomains {
|
for _, vdomain := range vDomains {
|
||||||
|
|||||||
27
main.go
27
main.go
@ -66,6 +66,9 @@ const (
|
|||||||
ModeAll string = "all"
|
ModeAll string = "all"
|
||||||
ModeAllowlist string = "allowlist"
|
ModeAllowlist string = "allowlist"
|
||||||
ModeDenylist string = "denylist"
|
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 {
|
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)
|
return entry, nil, fmt.Errorf("invalid regexp %q: %w", parts[0], err)
|
||||||
}
|
}
|
||||||
entry.Value = parts[0]
|
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])
|
entry.Value = strings.ToLower(parts[0])
|
||||||
if !validateDomainChars(entry.Value) {
|
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:
|
default:
|
||||||
return entry, nil, fmt.Errorf("unknown rule type: %q", entry.Type)
|
return entry, nil, fmt.Errorf("unknown rule type: %q", entry.Type)
|
||||||
@ -310,6 +318,21 @@ func validateDomainChars(domain string) bool {
|
|||||||
return true
|
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 {
|
func validateAttrChars(attr string) bool {
|
||||||
if attr == "" {
|
if attr == "" {
|
||||||
return false
|
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: "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: "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: "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: "invalid regexp", typ: "regexp", rule: "^example(", wantErr: true},
|
||||||
{name: "empty rule", typ: "domain", rule: " ", wantErr: true},
|
{name: "empty rule", typ: "domain", rule: " ", wantErr: true},
|
||||||
{name: "unknown type", typ: "prefix", rule: "example.com", 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: "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 attr", typ: "domain", rule: "example.com @", wantErr: true},
|
||||||
{name: "empty affiliation", 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},
|
{name: "unknown field", typ: "domain", rule: "example.com ads", wantErr: true},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user