mirror of
https://github.com/coredns/coredns.git
synced 2026-09-01 09:37:05 -04:00
plugin/hosts: don't drop entries after an over-long line (#8496)
bufio.Scanner stops at the first line longer than its 64KiB default buffer and reports bufio.ErrTooLong from Err(). parse() never checked Err(), so that line and every entry after it were dropped silently: the hosts file simply looked shorter than it is, with nothing in the log. Raise the scanner's limit to 1MiB (the scanner still grows its buffer lazily, so nothing is preallocated up front) and log an error if the scan does stop early, so the truncation is at least visible. Signed-off-by: Paco Cartones <pacocartones@users.noreply.github.com> Co-authored-by: Paco Cartones <pacocartones@users.noreply.github.com>
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user