dns/dnsmessage: add boundary check in unpackSVCBResource

Currently, bodyEnd is calculated using the length parameter from the
resource header without verifying if it exceeds the physical capacity
of the msg buffer.

If a malformed record provides a length that
exceeds the buffer, it bypasses the first-pass parameter validation
and causes an out-of-bounds slice during the second-pass copy.

Adding a check against len(msg) aligns this function with the boundary
enforcement used throughout the rest of the package.

Change-Id: I13f6ca83d1c30eac02286a49c12f8ec543d33e41
GitHub-Last-Rev: 78c35a160c45f09f2db04d9ec076dfb091a15595
GitHub-Pull-Request: golang/net#249
Reviewed-on: https://go-review.googlesource.com/c/net/+/781880
Reviewed-by: Sean Liao <sean@liao.dev>
Reviewed-by: ISMAIL GAMAL <ismailismailgamal52@gmail.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/dns/dnsmessage/svcb.go b/dns/dnsmessage/svcb.go
index 7729378..977d91e 100644
--- a/dns/dnsmessage/svcb.go
+++ b/dns/dnsmessage/svcb.go
@@ -188,6 +188,10 @@
 	paramsOff := off
 	bodyEnd := off + int(length)
 
+	if bodyEnd > len(msg) {
+		return SVCBResource{}, errResourceLen
+	}
+
 	var err error
 	if r.Priority, paramsOff, err = unpackUint16(msg, paramsOff); err != nil {
 		return SVCBResource{}, &nestedError{"Priority", err}
diff --git a/dns/dnsmessage/svcb_test.go b/dns/dnsmessage/svcb_test.go
index 64a1bfd..02b388b 100644
--- a/dns/dnsmessage/svcb_test.go
+++ b/dns/dnsmessage/svcb_test.go
@@ -437,3 +437,31 @@
 		})
 	}
 }
+
+func TestSVCBUnpackOutOfBounds(t *testing.T) {
+	// A minimal DNS message with an SVCB record where the header Length
+	// field (65535) maliciously exceeds the physical bounds of the buffer.
+	msg := []byte{
+		0x00, 0x01, // ID
+		0x00, 0x00, // Flags
+		0x00, 0x00, // QDCount = 0
+		0x00, 0x01, // ANCount = 1
+		0x00, 0x00, // NSCount = 0
+		0x00, 0x00, // ARCount = 0
+		0x00,       // Name: "."
+		0x00, 0x40, // Type: SVCB
+		0x00, 0x01, // Class: INET
+		0x00, 0x00, 0x00, 0x00, // TTL
+		0xff, 0xff, // Length: 65535 (Spoofed)
+		0x00, 0x01, // Priority
+		0x00,       // Target
+		0x00, 0x01, // Param Key
+		0xff, 0xf8, // Param Length
+	}
+
+	var m Message
+	err := m.Unpack(msg)
+	if err == nil {
+		t.Fatal("expected error parsing malformed message, got nil")
+	}
+}