]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.12] net: avoid an infinite loop in LookupAddr
authorBrad Fitzpatrick <bradfitz@golang.org>
Wed, 2 Oct 2019 20:59:27 +0000 (20:59 +0000)
committerBrad Fitzpatrick <bradfitz@golang.org>
Thu, 3 Oct 2019 02:07:10 +0000 (02:07 +0000)
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 #34661
Updates #34660

Change-Id: Ib5e5263243bc34b9e2f85aa2b913c9cd50dbcaa5
Reviewed-on: https://go-review.googlesource.com/c/go/+/198497
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
src/net/dnsclient_unix.go
src/net/dnsclient_unix_test.go

index 86ce92dc437844d6c98e627fb948ebb94b2e1b8b..7f335eba9f52756bfcbc5dde77d90444fc5b5706 100644 (file)
@@ -738,6 +738,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()
index be04a44c14beaf9c28e7d1d75dfa024bda05a8cb..f5e7992f3021f20560aa1efc635a547189126f82 100644 (file)
@@ -1621,3 +1621,50 @@ func TestTXTRecordTwoStrings(t *testing.T) {
                t.Errorf("txt[1], got %q, want %q", txt[1], want)
        }
 }
+
+// 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: 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)
+       }
+}