From: Michael Hendricks Date: Wed, 2 Oct 2019 15:30:51 +0000 (-0600) Subject: [release-branch.go1.13] net: avoid an infinite loop in LookupAddr X-Git-Tag: go1.13.3~22 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=f262eed9600a00f43c929d2761f02c2cecc3b0d1;p=gostls13.git [release-branch.go1.13] net: avoid an infinite loop in LookupAddr If a request for a PTR record returned a response with a non-PTR answer, goLookupPTR would loop forever. Skipping non-PTR answers guarantees progress through the DNS response. Fixes #34662 Updates #34660 Change-Id: I56f9d21e5342d07e7d843d253267e93a29707904 Reviewed-on: https://go-review.googlesource.com/c/go/+/198460 Run-TryBot: Brad Fitzpatrick TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick (cherry picked from commit f0e940ebc985661f54d31c8d9ba31a553b87041b) Reviewed-on: https://go-review.googlesource.com/c/go/+/198489 Reviewed-by: Michael Hendricks Reviewed-by: Emmanuel Odeke --- diff --git a/src/net/dnsclient_unix.go b/src/net/dnsclient_unix.go index e0a7ef8552..c90892b833 100644 --- a/src/net/dnsclient_unix.go +++ b/src/net/dnsclient_unix.go @@ -765,6 +765,14 @@ func (r *Resolver) goLookupPTR(ctx context.Context, addr string) ([]string, erro } } if h.Type != dnsmessage.TypePTR { + err := p.SkipAnswer() + if err != nil { + return nil, &DNSError{ + Err: "cannot marshal DNS message", + Name: addr, + Server: server, + } + } continue } ptr, err := p.PTRResource() diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go index 98304d36ea..31cb6f721a 100644 --- a/src/net/dnsclient_unix_test.go +++ b/src/net/dnsclient_unix_test.go @@ -1753,3 +1753,50 @@ func TestDNSUseTCP(t *testing.T) { t.Fatal("exchange failed:", err) } } + +// Issue 34660: PTR response with non-PTR answers should ignore non-PTR +func TestPTRandNonPTR(t *testing.T) { + fake := fakeDNSServer{ + rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) { + r := dnsmessage.Message{ + Header: dnsmessage.Header{ + ID: q.Header.ID, + Response: true, + RCode: dnsmessage.RCodeSuccess, + }, + Questions: q.Questions, + Answers: []dnsmessage.Resource{ + { + Header: dnsmessage.ResourceHeader{ + Name: q.Questions[0].Name, + Type: dnsmessage.TypePTR, + Class: dnsmessage.ClassINET, + }, + Body: &dnsmessage.PTRResource{ + PTR: dnsmessage.MustNewName("golang.org."), + }, + }, + { + Header: dnsmessage.ResourceHeader{ + Name: q.Questions[0].Name, + Type: dnsmessage.TypeTXT, + Class: dnsmessage.ClassINET, + }, + Body: &dnsmessage.TXTResource{ + TXT: []string{"PTR 8 6 60 ..."}, // fake RRSIG + }, + }, + }, + } + return r, nil + }, + } + r := Resolver{PreferGo: true, Dial: fake.DialContext} + names, err := r.lookupAddr(context.Background(), "192.0.2.123") + if err != nil { + t.Fatalf("LookupAddr: %v", err) + } + if want := []string{"golang.org."}; !reflect.DeepEqual(names, want) { + t.Errorf("names = %q; want %q", names, want) + } +}