diff --git a/lists/parsers/hosts.go b/lists/parsers/hosts.go index 67ef77f9..1cba0a3f 100644 --- a/lists/parsers/hosts.go +++ b/lists/parsers/hosts.go @@ -201,15 +201,18 @@ func (e HostsFileEntry) forEachHost(callback func(string) error) error { } func normalizeHostsListEntry(host string) (string, error) { + var err error // Lookup is the profile preferred for DNS queries, we use Punycode here as it does less validation. // That avoids rejecting domains in a list for reasons that amount to "that domain should not be used" // since the goal of the list is to determine whether the domain should be used or not, we leave // that decision to it. idnaProfile := idna.Punycode - host, err := idnaProfile.ToASCII(host) - if err != nil { - return "", fmt.Errorf("%w: %s", err, host) + if !isRegex(host) { + host, err = idnaProfile.ToASCII(host) + if err != nil { + return "", fmt.Errorf("%w: %s", err, host) + } } if err := validateHostsListEntry(host); err != nil { @@ -231,12 +234,16 @@ func validateDomainName(host string) error { return fmt.Errorf("invalid domain name: %s", host) } +func isRegex(host string) bool { + return strings.HasPrefix(host, "/") && strings.HasSuffix(host, "/") +} + func validateHostsListEntry(host string) error { if net.ParseIP(host) != nil { return nil } - if strings.HasPrefix(host, "/") && strings.HasSuffix(host, "/") { + if isRegex(host) { _, err := regexp.Compile(host) return err diff --git a/lists/parsers/hosts_test.go b/lists/parsers/hosts_test.go index 0d6e5114..3f10433e 100644 --- a/lists/parsers/hosts_test.go +++ b/lists/parsers/hosts_test.go @@ -34,6 +34,8 @@ var _ = Describe("Hosts", func() { "127.0.0.1 domain.tld # comment", "::1 localhost alias", `/domain\.(tld|local)/`, + `/^(.*\.)?2023\.xn--aptslabs-6fd\.net$/`, + `müller.com`, ) }) @@ -58,11 +60,21 @@ var _ = Describe("Hosts", func() { Expect(iteratorToList(it.ForEach)).Should(Equal([]string{`/domain\.(tld|local)/`})) Expect(sut.Position()).Should(Equal("line 6")) + it, err = sut.Next(context.Background()) + Expect(err).Should(Succeed()) + Expect(iteratorToList(it.ForEach)).Should(Equal([]string{`/^(.*\.)?2023\.xn--aptslabs-6fd\.net$/`})) + Expect(sut.Position()).Should(Equal("line 7")) + + it, err = sut.Next(context.Background()) + Expect(err).Should(Succeed()) + Expect(iteratorToList(it.ForEach)).Should(Equal([]string{`xn--mller-kva.com`})) + Expect(sut.Position()).Should(Equal("line 8")) + _, err = sut.Next(context.Background()) Expect(err).ShouldNot(Succeed()) Expect(err).Should(MatchError(io.EOF)) Expect(IsNonResumableErr(err)).Should(BeTrue()) - Expect(sut.Position()).Should(Equal("line 7")) + Expect(sut.Position()).Should(Equal("line 9")) }) }) @@ -71,6 +83,7 @@ var _ = Describe("Hosts", func() { lines := []string{ "invalidIP localhost", "!notadomain!", + "xn---mllerk1va.com", `/invalid regex ??/`, }