dns/dnsmessage: reject names with dots inside label

Fixes golang/go#56246

Change-Id: I9c8d611d1305536a7510bf6c4a02a5e551aa657a
GitHub-Last-Rev: 8a8703a1a7bde3457682c27db3e7d63856bd0cbc
GitHub-Pull-Request: golang/net#154
Reviewed-on: https://go-review.googlesource.com/c/net/+/443215
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Mateusz Poliwczak <mpoliwczak34@gmail.com>
Auto-Submit: Roland Shoemaker <roland@golang.org>
diff --git a/dns/dnsmessage/message.go b/dns/dnsmessage/message.go
index 69c611b..1577d4a 100644
--- a/dns/dnsmessage/message.go
+++ b/dns/dnsmessage/message.go
@@ -260,6 +260,7 @@
 	errReserved           = errors.New("segment prefix is reserved")
 	errTooManyPtr         = errors.New("too many pointers (>10)")
 	errInvalidPtr         = errors.New("invalid pointer")
+	errInvalidName        = errors.New("invalid dns name")
 	errNilResouceBody     = errors.New("nil resource body")
 	errResourceLen        = errors.New("insufficient data for resource body length")
 	errSegTooLong         = errors.New("segment length too long")
@@ -2034,6 +2035,15 @@
 			if endOff > len(msg) {
 				return off, errCalcLen
 			}
+
+			// Reject names containing dots.
+			// See issue golang/go#56246
+			for _, v := range msg[currOff:endOff] {
+				if v == '.' {
+					return off, errInvalidName
+				}
+			}
+
 			name = append(name, msg[currOff:endOff]...)
 			name = append(name, '.')
 			currOff = endOff
diff --git a/dns/dnsmessage/message_test.go b/dns/dnsmessage/message_test.go
index ef5326d..ce2716e 100644
--- a/dns/dnsmessage/message_test.go
+++ b/dns/dnsmessage/message_test.go
@@ -211,6 +211,15 @@
 	}
 }
 
+func TestNameWithDotsUnpack(t *testing.T) {
+	name := []byte{3, 'w', '.', 'w', 2, 'g', 'o', 3, 'd', 'e', 'v', 0}
+	var n Name
+	_, err := n.unpack(name, 0)
+	if err != errInvalidName {
+		t.Fatalf("expected %v, got %v", errInvalidName, err)
+	}
+}
+
 func TestNamePackUnpack(t *testing.T) {
 	const suffix = ".go.dev."
 	var longDNSPrefix = strings.Repeat("verylongdomainlabel.", 20)