From ab318db7b4a3a19273852ed627f54888198c8efb Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Thu, 9 Jul 2026 10:21:45 -0700 Subject: [PATCH] plugin/transfer: Fix panic in CoreDNS transfer plugin caused by empty DNS record (#8207) This PR fixes panic in CoreDNS transfer plugin caused by empty DNS record. Signed-off-by: Yong Tang --- plugin/transfer/transfer.go | 3 +++ plugin/transfer/transfer_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/plugin/transfer/transfer.go b/plugin/transfer/transfer.go index dc59f5dff..8718b2091 100644 --- a/plugin/transfer/transfer.go +++ b/plugin/transfer/transfer.go @@ -128,6 +128,9 @@ func (t *Transfer) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Ms batchSize := 0 var soa *dns.SOA for records := range pchan { + if len(records) == 0 { + continue + } if x, ok := records[0].(*dns.SOA); ok && soa == nil { soa = x } diff --git a/plugin/transfer/transfer_test.go b/plugin/transfer/transfer_test.go index 10c77b4d9..5d858ef93 100644 --- a/plugin/transfer/transfer_test.go +++ b/plugin/transfer/transfer_test.go @@ -474,3 +474,31 @@ func TestTransferLargeRecordBatching(t *testing.T) { t.Errorf("expected multiple messages for large transfer, got %d", len(w.Msgs)) } } + +type emptyBatchTransferer struct{} + +func (emptyBatchTransferer) Transfer(_ string, _ uint32) (<-chan []dns.RR, error) { + ch := make(chan []dns.RR, 1) + + ch <- []dns.RR{} + + close(ch) + return ch, nil +} + +func TestTransferEmptyBatch(t *testing.T) { + tr := &Transfer{ + Transferers: []Transferer{emptyBatchTransferer{}}, + xfrs: []*xfr{{Zones: []string{"example.org."}, to: []string{"*"}}}, + } + + req := new(dns.Msg) + req.SetQuestion("example.org.", dns.TypeAXFR) + + rec := dnstest.NewRecorder(&test.ResponseWriter{TCP: true}) + + _, err := tr.ServeDNS(context.Background(), rec, req) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } +}