diff --git a/plugin/hosts/hostsfile.go b/plugin/hosts/hostsfile.go index f3ef2cc75..e8f3a9dd7 100644 --- a/plugin/hosts/hostsfile.go +++ b/plugin/hosts/hostsfile.go @@ -164,11 +164,20 @@ func (h *Hostsfile) initInline(inline []string) { h.inline = h.parse(strings.NewReader(strings.Join(inline, "\n"))) } +// maxLineSize is the largest hosts file line we are willing to parse. A line +// can legitimately be long when many names share a single address, so this is +// well above bufio.Scanner's 64KiB default, but still bounded. +const maxLineSize = 1024 * 1024 + // Parse reads the hostsfile and populates the byName and addr maps. func (h *Hostsfile) parse(r io.Reader) *Map { hmap := newMap() scanner := bufio.NewScanner(r) + // The scanner grows its buffer as needed; only raise the limit at which it + // gives up, otherwise a single long line aborts the scan and every entry + // after it is dropped. + scanner.Buffer(nil, maxLineSize) for scanner.Scan() { line := scanner.Bytes() if i := bytes.Index(line, []byte{'#'}); i >= 0 { @@ -220,6 +229,10 @@ func (h *Hostsfile) parse(r io.Reader) *Map { hmap.addr[addr.String()] = append(hmap.addr[addr.String()], name) } } + if err := scanner.Err(); err != nil { + // Entries after the failing line have not been read. + log.Errorf("Failed to parse hosts file %q: %v", h.path, err) + } return hmap } diff --git a/plugin/hosts/hostsfile_test.go b/plugin/hosts/hostsfile_test.go index 4d9595220..6322d9849 100644 --- a/plugin/hosts/hostsfile_test.go +++ b/plugin/hosts/hostsfile_test.go @@ -290,3 +290,19 @@ func TestLookupStaticHostReloadRace(t *testing.T) { wg.Wait() } + +func TestParseLineLongerThanDefaultScanBuffer(t *testing.T) { + // A line longer than bufio.Scanner's default 64KiB buffer must not stop + // the scan: the entries that follow it still have to be parsed. + long := strings.Repeat("a", 70*1024) + h := testHostsfile("127.0.0.1 before.example.org\n" + + "127.0.0.2 " + long + ".example.org\n" + + "127.0.0.3 after.example.org\n") + + if addrs := h.LookupStaticHostV4("before.example.org."); len(addrs) != 1 || addrs[0].String() != "127.0.0.1" { + t.Errorf("LookupStaticHostV4(before.example.org.) = %v, want [127.0.0.1]", addrs) + } + if addrs := h.LookupStaticHostV4("after.example.org."); len(addrs) != 1 || addrs[0].String() != "127.0.0.3" { + t.Errorf("LookupStaticHostV4(after.example.org.) = %v, want [127.0.0.3]", addrs) + } +}