fix panic: cached NXDOMAIN returned an empty CNAME chain as success

ResolveCNAME/ResolveIPs cached negative results as an empty Result but the
cache-hit path returned (empty, true), so enrichHost did chain[1:] on a
zero-length slice and the process panicked (exit 2). Negative cache hits now
return false, plus a defensive length guard in enrichHost and a regression test.
This commit is contained in:
StasonJatham committed 2026-09-22 16:20:47 +02:00
1 parent fe5c01666b
commit 81e53f8755
3 files changed
+23 -1

No files matched your search

+14
View File
@@ -117,6 +117,20 @@ func (ctxResolver) LookupIP(ctx context.Context, host string) ([]net.IP, error)
return nil, ctx.Err()
}
func TestResolveCNAMENegativeCacheDoesNotReturnChain(t *testing.T) {
r := &fakeResolver{err: &net.DNSError{Err: "no such host", IsNotFound: true}}
e := &Enricher{Resolver: r, Cache: NewTTLCache[Result](16, 2), PositiveTTL: time.Minute, NegativeTTL: time.Minute, Timeout: time.Second, MaxDepth: 8}
if _, ok := e.ResolveCNAME(context.Background(), "missing.example.com"); ok {
t.Fatal("first NXDOMAIN lookup must fail")
}
// The negative entry must not come back as a successful empty chain: an
// empty chain with ok=true caused a slice panic in pipeline.enrichHost.
chain, ok := e.ResolveCNAME(context.Background(), "missing.example.com")
if ok || len(chain) != 0 {
t.Fatalf("cached NXDOMAIN returned chain=%v ok=%v, want empty/false", chain, ok)
}
}
func TestResolveContextCancellation(t *testing.T) {
e := &Enricher{Resolver: ctxResolver{}, Cache: NewTTLCache[Result](16, 2), PositiveTTL: time.Minute, NegativeTTL: time.Minute, MaxDepth: 8}
ctx, cancel := context.WithCancel(context.Background())